From b30e994b0632a958bf5b2d4e085ef7426b2182b4 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 16:17:37 -0800 Subject: [PATCH 01/27] Parameterize SubCommandTest with configLevel --- .github/workflows/go.yml | 17 +++++++++++++++++ cmd/dbc/install_test.go | 2 +- cmd/dbc/subcommand_test.go | 29 +++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 0d602e3..69ac840 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -59,3 +59,20 @@ jobs: # the file with `test_registry` also requires windows, so we can safely add this tag # without it running on non-windows OSes run: go test -v -tags test_registry ./... + + # User and System level tests + - name: Run Tests (User) + run: go test -v ./... + env: + DBC_TEST_LEVEL_USER: 1 + - name: Run Tests (System, Unixlike) + # Run system tests with sudo on Unixlikes to replicate what users do + if: runner.os != 'Windows' + run: sudo go test -v ./... + env: + DBC_TEST_LEVEL_SYSTEM: 1 + - name: Run Tests (System, Windows) + if: runner.os == 'Windows' + run: go test -v ./... + env: + DBC_TEST_LEVEL_SYSTEM: 1 diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index cf16479..6614f92 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -35,7 +35,7 @@ func (suite *SubcommandTestSuite) TestInstall() { } func (suite *SubcommandTestSuite) TestInstallDriverNotFound() { - m := InstallCmd{Driver: "foo", Level: config.ConfigEnv}. + m := InstallCmd{Driver: "foo", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.validateOutput("Error: could not find driver: driver `foo` not found in driver registry index\r\n\r ", "", suite.runCmdErr(m)) } diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index 901bc30..113d938 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -27,6 +27,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/columnar-tech/dbc" + "github.com/columnar-tech/dbc/config" "github.com/go-faster/yaml" "github.com/stretchr/testify/suite" ) @@ -83,6 +84,8 @@ type SubcommandTestSuite struct { openBrowserFn func(string) error fallbackDriverDocsUrl map[string]string tempdir string + + configLevel config.ConfigLevel } func (suite *SubcommandTestSuite) SetupSuite() { @@ -90,6 +93,10 @@ func (suite *SubcommandTestSuite) SetupSuite() { getDriverRegistry = getTestDriverRegistry suite.openBrowserFn = openBrowserFunc suite.fallbackDriverDocsUrl = fallbackDriverDocsUrl + + if suite.configLevel == config.ConfigUnknown { + suite.configLevel = config.ConfigEnv + } } func (suite *SubcommandTestSuite) SetupTest() { @@ -171,6 +178,24 @@ func (suite *SubcommandTestSuite) validateOutput(expected, extra, actual string) suite.Equal(terminalPrefix+expected+terminalSuffix+extra, actual) } -func TestSubcommands(t *testing.T) { - suite.Run(t, new(SubcommandTestSuite)) +// The SubcommandTestSuite is only run for ConfigEnv by default but can be run +// for other config levels by setting DBC_TEST_LEVEL_USER=1 or +// DBC_TEST_LEVEL_SYSTEM=1 for ConfigUser and ConfigSystem (respectively). +// Testing ConfigUser and ConfigSystem is mainly intended to be done in CI. +func TestSubcommandsEnv(t *testing.T) { + suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigEnv}) +} + +func TestSubcommandsUser(t *testing.T) { + if os.Getenv("DBC_TEST_LEVEL_USER") != "1" { + t.Skip("Skipping tests for config level configUser because DBC_TEST_LEVEL_USER!=\"1\"") + } + suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigUser}) +} + +func TestSubcommandsSystem(t *testing.T) { + if os.Getenv("DBC_TEST_LEVEL_SYSTEM") != "1" { + t.Skip("Skipping tests for config level configSystem because DBC_TEST_LEVEL_SYSTEM!=\"1\"") + } + suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigSystem}) } From d53fe2eb5aa05ba817a255e6e80c614ee6c74efc Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 16:43:37 -0800 Subject: [PATCH 02/27] Rework logic --- cmd/dbc/subcommand_test.go | 39 +++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index 113d938..97ac0ad 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -178,24 +178,45 @@ func (suite *SubcommandTestSuite) validateOutput(expected, extra, actual string) suite.Equal(terminalPrefix+expected+terminalSuffix+extra, actual) } -// The SubcommandTestSuite is only run for ConfigEnv by default but can be run -// for other config levels by setting DBC_TEST_LEVEL_USER=1 or -// DBC_TEST_LEVEL_SYSTEM=1 for ConfigUser and ConfigSystem (respectively). -// Testing ConfigUser and ConfigSystem is mainly intended to be done in CI. +// The SubcommandTestSuite is only run for ConfigEnv by default but is +// parametrized by configLevel so tests can be run for other levels. Tests must +// opt into this behavior by instantiating subcommands with `suite.configLevel` +// like: +// +// m := InstallCmd{Driver: "foo", Level: suite.configLevel} +// ^---- here +// +// and can opt out of this behavior by specifying it separately like: +// +// m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. +// +// When any level is explicitly requested, tests are only run for that level. +// i.e., to run tests for multiple levels, each level must be specified +// separately. func TestSubcommandsEnv(t *testing.T) { - suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigEnv}) + _, env := os.LookupEnv("DBC_TEST_LEVEL_ENV") + _, user := os.LookupEnv("DBC_TEST_LEVEL_USER") + _, system := os.LookupEnv("DBC_TEST_LEVEL_SYSTEM") + + // Run if explicitly requested, or if no levels were requested (default + // behavior) + if env || (!user && !system) { + suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigEnv}) + return + } + t.Skip("skipping tests for config level: ConfigEnv") } func TestSubcommandsUser(t *testing.T) { - if os.Getenv("DBC_TEST_LEVEL_USER") != "1" { - t.Skip("Skipping tests for config level configUser because DBC_TEST_LEVEL_USER!=\"1\"") + if _, ok := os.LookupEnv("DBC_TEST_LEVEL_USER"); !ok { + t.Skip("skipping tests for config level: ConfigUser") } suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigUser}) } func TestSubcommandsSystem(t *testing.T) { - if os.Getenv("DBC_TEST_LEVEL_SYSTEM") != "1" { - t.Skip("Skipping tests for config level configSystem because DBC_TEST_LEVEL_SYSTEM!=\"1\"") + if _, ok := os.LookupEnv("DBC_TEST_LEVEL_SYSTEM"); !ok { + t.Skip("skipping tests for config level: ConfigSystem") } suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigSystem}) } From 01afc5b91f4b6dc25fe8ee97db1579107f9026a9 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 17:11:22 -0800 Subject: [PATCH 03/27] Use sudo -E for system tests --- .github/workflows/go.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 69ac840..d54e9d5 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -68,7 +68,7 @@ jobs: - name: Run Tests (System, Unixlike) # Run system tests with sudo on Unixlikes to replicate what users do if: runner.os != 'Windows' - run: sudo go test -v ./... + run: sudo -E go test -v ./... env: DBC_TEST_LEVEL_SYSTEM: 1 - name: Run Tests (System, Windows) From 5c1405a1a12c4165c636d771b9bbadb86356865e Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 17:23:41 -0800 Subject: [PATCH 04/27] See what tests fail with this --- cmd/dbc/install_test.go | 8 ++++---- cmd/dbc/uninstall_test.go | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 6614f92..280252f 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -23,7 +23,7 @@ import ( ) func (suite *SubcommandTestSuite) TestInstall() { - m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. + m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) out := suite.runCmd(m) @@ -162,7 +162,7 @@ func (suite *SubcommandTestSuite) TestInstallEnvironmentPrecedence() { os.Setenv("VIRTUAL_ENV", venv_path) os.Setenv("CONDA_PREFIX", conda_path) - m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. + m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) @@ -171,14 +171,14 @@ func (suite *SubcommandTestSuite) TestInstallEnvironmentPrecedence() { suite.NoFileExists(filepath.Join(conda_path, "test-driver-1.toml")) os.Unsetenv("ADBC_DRIVER_PATH") - m = InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. + m = InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(venv_path, "etc", "adbc", "drivers", "test-driver-1.toml")) suite.NoFileExists(filepath.Join(conda_path, "etc", "adbc", "drivers", "test-driver-1.toml")) os.Unsetenv("VIRTUAL_ENV") - m = InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. + m = InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(conda_path, "etc", "adbc", "drivers", "test-driver-1.toml")) diff --git a/cmd/dbc/uninstall_test.go b/cmd/dbc/uninstall_test.go index f8bf442..6136b1c 100644 --- a/cmd/dbc/uninstall_test.go +++ b/cmd/dbc/uninstall_test.go @@ -49,7 +49,7 @@ func (suite *SubcommandTestSuite) TestUninstallManifestOnly() { shared = "some.dll"` os.WriteFile(path.Join(suite.tempdir, "found.toml"), []byte(contents), 0644) - m := UninstallCmd{Driver: "found", Level: config.ConfigEnv}.GetModel() + m := UninstallCmd{Driver: "found", Level: suite.configLevel}.GetModel() suite.validateOutput("Driver `found` uninstalled successfully!\r\n\r\n\r ", "", suite.runCmd(m)) } @@ -70,7 +70,7 @@ func (suite *SubcommandTestSuite) TestUninstallDriverAndManifest() { os.WriteFile(path.Join(suite.tempdir, "found.toml"), []byte(contents), 0o644) os.WriteFile(path.Join(pkgdir, "some.dll"), []byte("anything"), 0o644) - m := UninstallCmd{Driver: "found", Level: config.ConfigEnv}.GetModel() + m := UninstallCmd{Driver: "found", Level: suite.configLevel}.GetModel() suite.validateOutput("Driver `found` uninstalled successfully!\r\n\r\n\r ", "", suite.runCmd(m)) } @@ -82,7 +82,7 @@ func (suite *SubcommandTestSuite) TestUninstallMultipleLocations() { } // Install to Env first - m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. + m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(suite.tempdir, "test-driver-1.toml")) @@ -97,7 +97,7 @@ func (suite *SubcommandTestSuite) TestUninstallMultipleLocations() { suite.FileExists(filepath.Join(installModel.cfg.Location, "test-driver-1.toml")) // Uninstall from Env level - m = UninstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. + m = UninstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) @@ -113,7 +113,7 @@ func (suite *SubcommandTestSuite) TestUninstallMultipleLocationsNonDefault() { } // Install to Env first - m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. + m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(suite.tempdir, "test-driver-1.toml")) @@ -172,7 +172,7 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { if runtime.GOOS == "windows" { suite.T().Skip() } - m := InstallCmd{Driver: "test-driver-invalid-manifest", Level: config.ConfigEnv}. + m := InstallCmd{Driver: "test-driver-invalid-manifest", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(suite.tempdir, "test-driver-invalid-manifest.toml")) @@ -198,7 +198,7 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { suite.DirExists(value) // and continue - m = UninstallCmd{Driver: "test-driver-invalid-manifest", Level: config.ConfigEnv}.GetModel() + m = UninstallCmd{Driver: "test-driver-invalid-manifest", Level: suite.configLevel}.GetModel() output := suite.runCmd(m) suite.validateOutput("Driver `test-driver-invalid-manifest` uninstalled successfully!\r\n\r\n\r ", "", output) From 2340f19dc82cea32d836fe0d9d4e0aa2423a4486 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 17:58:31 -0800 Subject: [PATCH 05/27] revert changes that were mistakes --- cmd/dbc/install_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 280252f..9e75378 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -162,7 +162,7 @@ func (suite *SubcommandTestSuite) TestInstallEnvironmentPrecedence() { os.Setenv("VIRTUAL_ENV", venv_path) os.Setenv("CONDA_PREFIX", conda_path) - m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. + m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) @@ -171,14 +171,14 @@ func (suite *SubcommandTestSuite) TestInstallEnvironmentPrecedence() { suite.NoFileExists(filepath.Join(conda_path, "test-driver-1.toml")) os.Unsetenv("ADBC_DRIVER_PATH") - m = InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. + m = InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(venv_path, "etc", "adbc", "drivers", "test-driver-1.toml")) suite.NoFileExists(filepath.Join(conda_path, "etc", "adbc", "drivers", "test-driver-1.toml")) os.Unsetenv("VIRTUAL_ENV") - m = InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. + m = InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(conda_path, "etc", "adbc", "drivers", "test-driver-1.toml")) From f58728693a8c504151aec9d78ab2ae4c2ba17fb8 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 17:59:14 -0800 Subject: [PATCH 06/27] Remove my old fake user/system level tests --- cmd/dbc/install_test.go | 66 ----------------------------------------- 1 file changed, 66 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 9e75378..a6dfe40 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -91,55 +91,6 @@ func (suite *SubcommandTestSuite) TestReinstallUpdateVersion() { "test-driver-1.1/test-driver-1-not-valid.so.sig", "test-driver-1.toml"}, suite.getFilesInTempDir()) } -func (suite *SubcommandTestSuite) TestInstallUserFake() { - if runtime.GOOS == "windows" { - suite.T().Skip() - } - - os.Unsetenv("ADBC_DRIVER_PATH") - - m := InstallCmd{Driver: "test-driver-1"}. - GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) - installModel := m.(progressiveInstallModel) - suite.Equal(installModel.cfg.Level, config.ConfigUser) - installModel.cfg.Location = filepath.Join(suite.tempdir, "root", installModel.cfg.Location) - m = installModel // <- We need to reassign to make the change stick - suite.runCmd(m) - suite.FileExists(filepath.Join(installModel.cfg.Location, "test-driver-1.toml")) -} - -func (suite *SubcommandTestSuite) TestInstallUserFakeExplicit() { - if runtime.GOOS == "windows" { - suite.T().Skip() - } - - os.Unsetenv("ADBC_DRIVER_PATH") - - m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigUser}. - GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) - installModel := m.(progressiveInstallModel) - suite.Equal(installModel.cfg.Level, config.ConfigUser) - installModel.cfg.Location = filepath.Join(suite.tempdir, "root", installModel.cfg.Location) - m = installModel // <- We need to reassign to make the change stick - suite.runCmd(m) - suite.FileExists(filepath.Join(installModel.cfg.Location, "test-driver-1.toml")) -} - -func (suite *SubcommandTestSuite) TestInstallSystemFake() { - if runtime.GOOS == "windows" { - suite.T().Skip() - } - - m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigSystem}. - GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) - installModel := m.(progressiveInstallModel) - suite.Equal(installModel.cfg.Level, config.ConfigSystem) - installModel.cfg.Location = filepath.Join(suite.tempdir, "root", installModel.cfg.Location) - m = installModel // <- We need to reassign to make the change stick - suite.runCmd(m) - suite.FileExists(filepath.Join(installModel.cfg.Location, "test-driver-1.toml")) -} - func (suite *SubcommandTestSuite) TestInstallVenv() { os.Unsetenv("ADBC_DRIVER_PATH") os.Setenv("VIRTUAL_ENV", suite.tempdir) @@ -197,23 +148,6 @@ func (suite *SubcommandTestSuite) TestInstallCondaPrefix() { "\nInstalled test-driver-1 1.1.0 to "+filepath.Join(suite.tempdir, "etc", "adbc", "drivers")+"\n", suite.runCmd(m)) } -func (suite *SubcommandTestSuite) TestInstallUserFakeExplicitLevelOverrides() { - if runtime.GOOS == "windows" { - suite.T().Skip() - } - - // If the user explicitly sets level, it should override ADBC_DRIVER_PATH - // which, when testing, is set to tempdir - m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigSystem}. - GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) - installModel := m.(progressiveInstallModel) - suite.Equal(installModel.cfg.Level, config.ConfigSystem) - installModel.cfg.Location = filepath.Join(suite.tempdir, "user", installModel.cfg.Location) - m = installModel // <- We need to reassign to make the change stick - suite.runCmd(m) - suite.FileExists(filepath.Join(installModel.cfg.Location, "test-driver-1.toml")) -} - func (suite *SubcommandTestSuite) TestInstallManifestOnlyDriver() { m := InstallCmd{Driver: "test-driver-manifest-only"}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) From b38b9b3a38cd8c45cb76994a9f7a4491cc9c9a74 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 18:02:40 -0800 Subject: [PATCH 07/27] Add test suite helpers so we can test on all platforms --- cmd/dbc/install_test.go | 12 ++++-------- cmd/dbc/subcommand_test.go | 17 +++++++++++++++++ cmd/dbc/uninstall_test.go | 8 ++------ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index a6dfe40..5fb4824 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -17,7 +17,6 @@ package main import ( "os" "path/filepath" - "runtime" "github.com/columnar-tech/dbc/config" ) @@ -29,9 +28,7 @@ func (suite *SubcommandTestSuite) TestInstall() { suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-1 1.1.0 to "+suite.tempdir+"\n", out) - if runtime.GOOS != "windows" { - suite.FileExists(filepath.Join(suite.tempdir, "test-driver-1.toml")) - } + suite.driverIsInstalled("test-driver-1") } func (suite *SubcommandTestSuite) TestInstallDriverNotFound() { @@ -54,7 +51,7 @@ func (suite *SubcommandTestSuite) TestInstallWithVersion() { for _, tt := range tests { suite.Run(tt.driver, func() { - m := InstallCmd{Driver: tt.driver}. + m := InstallCmd{Driver: tt.driver, Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) out := suite.runCmd(m) suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", @@ -63,6 +60,7 @@ func (suite *SubcommandTestSuite) TestInstallWithVersion() { m = UninstallCmd{Driver: "test-driver-1"}.GetModelCustom( baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) + suite.driverIsInstalled(tt.driver) }) } } @@ -154,9 +152,7 @@ func (suite *SubcommandTestSuite) TestInstallManifestOnlyDriver() { suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.tempdir+"\n"+ "\nMust have libtest_driver installed to load this driver\n", suite.runCmd(m)) - if runtime.GOOS != "windows" { - suite.FileExists(filepath.Join(suite.tempdir, "test-driver-manifest-only.toml")) - } + suite.driverIsInstalled("test-driver-manifest-only") } func (suite *SubcommandTestSuite) TestInstallDriverNoSignature() { diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index 97ac0ad..aecb6b1 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -220,3 +220,20 @@ func TestSubcommandsSystem(t *testing.T) { } suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigSystem}) } + +func (suite *SubcommandTestSuite) driverIsInstalled(path string) { + cfg := config.Get()[suite.configLevel] + + driver, err := config.GetDriver(cfg, path) + suite.Require().NoError(err, "driver manifest should exist for driver `%s`", path) + + sharedPath := driver.Driver.Shared.Get(config.PlatformTuple()) + suite.FileExists(sharedPath, "driver shared library should exist for driver `%s`", path) +} + +func (suite *SubcommandTestSuite) driverIsNotInstalled(path string) { + cfg := config.Get()[suite.configLevel] + + _, err := config.GetDriver(cfg, path) + suite.Require().Error(err, "driver manifest should not exist for driver `%s`", path) +} diff --git a/cmd/dbc/uninstall_test.go b/cmd/dbc/uninstall_test.go index 6136b1c..bdecbf8 100644 --- a/cmd/dbc/uninstall_test.go +++ b/cmd/dbc/uninstall_test.go @@ -145,9 +145,7 @@ func (suite *SubcommandTestSuite) TestUninstallManifestOnlyDriver() { suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.tempdir+"\n"+ "\nMust have libtest_driver installed to load this driver\n", suite.runCmd(m)) - if runtime.GOOS != "windows" { - suite.FileExists(filepath.Join(suite.tempdir, "test-driver-manifest-only.toml")) - } + suite.driverIsInstalled("test-driver-manifest-only") // Verify the sidecar folder exists before we uninstall new_sidecar_path := fmt.Sprintf("test-driver-manifest-only_%s_v1.0.0", config.PlatformTuple()) @@ -161,9 +159,7 @@ func (suite *SubcommandTestSuite) TestUninstallManifestOnlyDriver() { m = UninstallCmd{Driver: "test-driver-manifest-only"}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.validateOutput("Driver `test-driver-manifest-only` uninstalled successfully!\r\n\r\n\r ", "", suite.runCmd(m)) - if runtime.GOOS != "windows" { - suite.NoFileExists(filepath.Join(suite.tempdir, "test-driver-manifest-only.toml")) - } + suite.driverIsNotInstalled("test-driver-manifest-only") suite.NoDirExists(filepath.Join(suite.tempdir, new_sidecar_path)) } From 9217c447cbd53cc5a04cf54b7c4d2eeb052891ba Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 18:12:44 -0800 Subject: [PATCH 08/27] handle manifest-only drivers --- cmd/dbc/install_test.go | 4 ++-- cmd/dbc/subcommand_test.go | 8 +++++--- cmd/dbc/uninstall_test.go | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 5fb4824..0676d0b 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -28,7 +28,7 @@ func (suite *SubcommandTestSuite) TestInstall() { suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-1 1.1.0 to "+suite.tempdir+"\n", out) - suite.driverIsInstalled("test-driver-1") + suite.driverIsInstalled("test-driver-1", true) } func (suite *SubcommandTestSuite) TestInstallDriverNotFound() { @@ -152,7 +152,7 @@ func (suite *SubcommandTestSuite) TestInstallManifestOnlyDriver() { suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.tempdir+"\n"+ "\nMust have libtest_driver installed to load this driver\n", suite.runCmd(m)) - suite.driverIsInstalled("test-driver-manifest-only") + suite.driverIsInstalled("test-driver-manifest-only", false) } func (suite *SubcommandTestSuite) TestInstallDriverNoSignature() { diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index aecb6b1..0f4e4fc 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -221,14 +221,16 @@ func TestSubcommandsSystem(t *testing.T) { suite.Run(t, &SubcommandTestSuite{configLevel: config.ConfigSystem}) } -func (suite *SubcommandTestSuite) driverIsInstalled(path string) { +func (suite *SubcommandTestSuite) driverIsInstalled(path string, checkShared bool) { cfg := config.Get()[suite.configLevel] driver, err := config.GetDriver(cfg, path) suite.Require().NoError(err, "driver manifest should exist for driver `%s`", path) - sharedPath := driver.Driver.Shared.Get(config.PlatformTuple()) - suite.FileExists(sharedPath, "driver shared library should exist for driver `%s`", path) + if checkShared { + sharedPath := driver.Driver.Shared.Get(config.PlatformTuple()) + suite.FileExists(sharedPath, "driver shared library should exist for driver `%s`", path) + } } func (suite *SubcommandTestSuite) driverIsNotInstalled(path string) { diff --git a/cmd/dbc/uninstall_test.go b/cmd/dbc/uninstall_test.go index bdecbf8..4659559 100644 --- a/cmd/dbc/uninstall_test.go +++ b/cmd/dbc/uninstall_test.go @@ -145,7 +145,7 @@ func (suite *SubcommandTestSuite) TestUninstallManifestOnlyDriver() { suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.tempdir+"\n"+ "\nMust have libtest_driver installed to load this driver\n", suite.runCmd(m)) - suite.driverIsInstalled("test-driver-manifest-only") + suite.driverIsInstalled("test-driver-manifest-only", false) // Verify the sidecar folder exists before we uninstall new_sidecar_path := fmt.Sprintf("test-driver-manifest-only_%s_v1.0.0", config.PlatformTuple()) From ec0b84c7bd79845f5ea269459ece6e5803b89b5d Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 18:12:53 -0800 Subject: [PATCH 09/27] fix mistake --- cmd/dbc/install_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 0676d0b..eda019e 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -56,11 +56,11 @@ func (suite *SubcommandTestSuite) TestInstallWithVersion() { out := suite.runCmd(m) suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-1 "+tt.expectedVersion+" to "+suite.tempdir+"\n", out) - + suite.driverIsInstalled("test-driver-1", true) m = UninstallCmd{Driver: "test-driver-1"}.GetModelCustom( baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) - suite.driverIsInstalled(tt.driver) + suite.driverIsNotInstalled("test-driver-1") }) } } From dae5016c547d5362f56ba752965f9426af98fb50 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 18:16:21 -0800 Subject: [PATCH 10/27] Update install_test.go --- cmd/dbc/install_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index eda019e..cde849e 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -147,7 +147,7 @@ func (suite *SubcommandTestSuite) TestInstallCondaPrefix() { } func (suite *SubcommandTestSuite) TestInstallManifestOnlyDriver() { - m := InstallCmd{Driver: "test-driver-manifest-only"}. + m := InstallCmd{Driver: "test-driver-manifest-only", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.tempdir+"\n"+ From 5b5713f2f0004b5b0738380691b7e7819e0bd420 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 18:27:32 -0800 Subject: [PATCH 11/27] attempt to fix tests --- cmd/dbc/install_test.go | 7 +++---- cmd/dbc/subcommand_test.go | 4 ++++ cmd/dbc/uninstall_test.go | 10 +++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index cde849e..074c2d0 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -26,8 +26,7 @@ func (suite *SubcommandTestSuite) TestInstall() { GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) out := suite.runCmd(m) - suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", - "\nInstalled test-driver-1 1.1.0 to "+suite.tempdir+"\n", out) + suite.containsOutput("Installed test-driver-1 1.1.0", out) suite.driverIsInstalled("test-driver-1", true) } @@ -35,6 +34,7 @@ func (suite *SubcommandTestSuite) TestInstallDriverNotFound() { m := InstallCmd{Driver: "foo", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.validateOutput("Error: could not find driver: driver `foo` not found in driver registry index\r\n\r ", "", suite.runCmdErr(m)) + suite.driverIsNotInstalled("test-driver-1") } func (suite *SubcommandTestSuite) TestInstallWithVersion() { @@ -51,7 +51,7 @@ func (suite *SubcommandTestSuite) TestInstallWithVersion() { for _, tt := range tests { suite.Run(tt.driver, func() { - m := InstallCmd{Driver: tt.driver, Level: suite.configLevel}. + m := InstallCmd{Driver: tt.driver, Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) out := suite.runCmd(m) suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", @@ -60,7 +60,6 @@ func (suite *SubcommandTestSuite) TestInstallWithVersion() { m = UninstallCmd{Driver: "test-driver-1"}.GetModelCustom( baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) - suite.driverIsNotInstalled("test-driver-1") }) } } diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index 0f4e4fc..13bb520 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -178,6 +178,10 @@ func (suite *SubcommandTestSuite) validateOutput(expected, extra, actual string) suite.Equal(terminalPrefix+expected+terminalSuffix+extra, actual) } +func (suite *SubcommandTestSuite) containsOutput(expected, actual string) { + suite.Contains(expected, actual) +} + // The SubcommandTestSuite is only run for ConfigEnv by default but is // parametrized by configLevel so tests can be run for other levels. Tests must // opt into this behavior by instantiating subcommands with `suite.configLevel` diff --git a/cmd/dbc/uninstall_test.go b/cmd/dbc/uninstall_test.go index 4659559..1e23208 100644 --- a/cmd/dbc/uninstall_test.go +++ b/cmd/dbc/uninstall_test.go @@ -49,7 +49,7 @@ func (suite *SubcommandTestSuite) TestUninstallManifestOnly() { shared = "some.dll"` os.WriteFile(path.Join(suite.tempdir, "found.toml"), []byte(contents), 0644) - m := UninstallCmd{Driver: "found", Level: suite.configLevel}.GetModel() + m := UninstallCmd{Driver: "found", Level: config.ConfigEnv}.GetModel() suite.validateOutput("Driver `found` uninstalled successfully!\r\n\r\n\r ", "", suite.runCmd(m)) } @@ -70,7 +70,7 @@ func (suite *SubcommandTestSuite) TestUninstallDriverAndManifest() { os.WriteFile(path.Join(suite.tempdir, "found.toml"), []byte(contents), 0o644) os.WriteFile(path.Join(pkgdir, "some.dll"), []byte("anything"), 0o644) - m := UninstallCmd{Driver: "found", Level: suite.configLevel}.GetModel() + m := UninstallCmd{Driver: "found", Level: config.ConfigEnv}.GetModel() suite.validateOutput("Driver `found` uninstalled successfully!\r\n\r\n\r ", "", suite.runCmd(m)) } @@ -82,7 +82,7 @@ func (suite *SubcommandTestSuite) TestUninstallMultipleLocations() { } // Install to Env first - m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. + m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(suite.tempdir, "test-driver-1.toml")) @@ -97,7 +97,7 @@ func (suite *SubcommandTestSuite) TestUninstallMultipleLocations() { suite.FileExists(filepath.Join(installModel.cfg.Location, "test-driver-1.toml")) // Uninstall from Env level - m = UninstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. + m = UninstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) @@ -113,7 +113,7 @@ func (suite *SubcommandTestSuite) TestUninstallMultipleLocationsNonDefault() { } // Install to Env first - m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. + m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(suite.tempdir, "test-driver-1.toml")) From bff221b520bf6deb91761772caf73ff7fdee86c7 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 18:28:46 -0800 Subject: [PATCH 12/27] whoops --- cmd/dbc/install_test.go | 2 +- cmd/dbc/subcommand_test.go | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 074c2d0..dfdea4d 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -26,7 +26,7 @@ func (suite *SubcommandTestSuite) TestInstall() { GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) out := suite.runCmd(m) - suite.containsOutput("Installed test-driver-1 1.1.0", out) + suite.Contains(out, "Installed test-driver-1 1.1.0") suite.driverIsInstalled("test-driver-1", true) } diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index 13bb520..0f4e4fc 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -178,10 +178,6 @@ func (suite *SubcommandTestSuite) validateOutput(expected, extra, actual string) suite.Equal(terminalPrefix+expected+terminalSuffix+extra, actual) } -func (suite *SubcommandTestSuite) containsOutput(expected, actual string) { - suite.Contains(expected, actual) -} - // The SubcommandTestSuite is only run for ConfigEnv by default but is // parametrized by configLevel so tests can be run for other levels. Tests must // opt into this behavior by instantiating subcommands with `suite.configLevel` From d7792bbb65502349fb573b7980cdff38ef4caf0b Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Thu, 18 Dec 2025 18:36:21 -0800 Subject: [PATCH 13/27] Update install_test.go --- cmd/dbc/install_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index dfdea4d..cb240d2 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -146,7 +146,7 @@ func (suite *SubcommandTestSuite) TestInstallCondaPrefix() { } func (suite *SubcommandTestSuite) TestInstallManifestOnlyDriver() { - m := InstallCmd{Driver: "test-driver-manifest-only", Level: suite.configLevel}. + m := InstallCmd{Driver: "test-driver-manifest-only", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.tempdir+"\n"+ From 410be3adc1128405224db26cd72f4566c582b834 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 08:20:19 -0800 Subject: [PATCH 14/27] add user and system level test teardown --- cmd/dbc/subcommand_test.go | 4 --- cmd/dbc/subcommand_unix_test.go | 37 +++++++++++++++++++++++++++ cmd/dbc/subcommand_windows_test.go | 41 ++++++++++++++++++++++++++++++ config/config.go | 4 +++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 cmd/dbc/subcommand_unix_test.go create mode 100644 cmd/dbc/subcommand_windows_test.go diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index 0f4e4fc..839e0bd 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -104,10 +104,6 @@ func (suite *SubcommandTestSuite) SetupTest() { suite.Require().NoError(os.Setenv("ADBC_DRIVER_PATH", suite.tempdir)) } -func (suite *SubcommandTestSuite) TearDownTest() { - suite.Require().NoError(os.Unsetenv("ADBC_DRIVER_PATH")) -} - func (suite *SubcommandTestSuite) TearDownSuite() { getDriverRegistry = suite.getDriverRegistryFn openBrowserFunc = suite.openBrowserFn diff --git a/cmd/dbc/subcommand_unix_test.go b/cmd/dbc/subcommand_unix_test.go new file mode 100644 index 0000000..b855fbc --- /dev/null +++ b/cmd/dbc/subcommand_unix_test.go @@ -0,0 +1,37 @@ +// Copyright 2025 Columnar Technologies Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !windows + +package main + +import ( + "os" + + "github.com/columnar-tech/dbc/config" +) + +func (suite *SubcommandTestSuite) TearDownTest() { + suite.Require().NoError(os.Unsetenv("ADBC_DRIVER_PATH")) + + // Clean up filesystem after each test + _, user := os.LookupEnv("DBC_TEST_LEVEL_USER") + _, system := os.LookupEnv("DBC_TEST_LEVEL_SYSTEM") + if user { + suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigUser))) + } + if system { + suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigSystem))) + } +} diff --git a/cmd/dbc/subcommand_windows_test.go b/cmd/dbc/subcommand_windows_test.go new file mode 100644 index 0000000..91d0c0c --- /dev/null +++ b/cmd/dbc/subcommand_windows_test.go @@ -0,0 +1,41 @@ +// Copyright 2025 Columnar Technologies Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build windows + +package main + +import ( + "os" + + "github.com/columnar-tech/dbc/config" + "golang.org/x/sys/windows/registry" +) + +func (suite *SubcommandTestSuite) TearDownTest() { + suite.Require().NoError(os.Unsetenv("ADBC_DRIVER_PATH")) + + // Clean up the registry and filesystem after each test + _, user := os.LookupEnv("DBC_TEST_LEVEL_USER") + _, system := os.LookupEnv("DBC_TEST_LEVEL_SYSTEM") + regKeyADBC := "SOFTWARE\\ADBC\\Drivers" + if user { + suite.Require().NoError(registry.DeleteKey(registry.CURRENT_USER, regKeyADBC)) + suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigUser))) + } + if system { + suite.Require().NoError(registry.DeleteKey(registry.LOCAL_MACHINE, regKeyADBC)) + suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigSystem))) + } +} diff --git a/config/config.go b/config/config.go index 992143c..269a1d7 100644 --- a/config/config.go +++ b/config/config.go @@ -97,6 +97,10 @@ func (c ConfigLevel) String() string { } } +func GetLocation(lvl ConfigLevel) string { + return lvl.configLocation() +} + func (c *ConfigLevel) UnmarshalText(b []byte) error { switch strings.ToLower(strings.TrimSpace(string(b))) { case "system": From 9bfe476cdb09058d65940a0b2d2a590bfd3eb604 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 08:24:09 -0800 Subject: [PATCH 15/27] Fix test failures now that we can clean up --- cmd/dbc/install_test.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index cb240d2..6d16be6 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -51,13 +51,19 @@ func (suite *SubcommandTestSuite) TestInstallWithVersion() { for _, tt := range tests { suite.Run(tt.driver, func() { - m := InstallCmd{Driver: tt.driver, Level: config.ConfigEnv}. + m := InstallCmd{Driver: tt.driver, Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) out := suite.runCmd(m) + + expectedPath := suite.tempdir + if suite.configLevel != config.ConfigEnv { + expectedPath = config.GetLocation(suite.configLevel) + } + suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", - "\nInstalled test-driver-1 "+tt.expectedVersion+" to "+suite.tempdir+"\n", out) + "\nInstalled test-driver-1 "+tt.expectedVersion+" to "+expectedPath+"\n", out) suite.driverIsInstalled("test-driver-1", true) - m = UninstallCmd{Driver: "test-driver-1"}.GetModelCustom( + m = UninstallCmd{Driver: "test-driver-1", Level: suite.configLevel}.GetModelCustom( baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) }) @@ -146,10 +152,16 @@ func (suite *SubcommandTestSuite) TestInstallCondaPrefix() { } func (suite *SubcommandTestSuite) TestInstallManifestOnlyDriver() { - m := InstallCmd{Driver: "test-driver-manifest-only", Level: config.ConfigEnv}. + m := InstallCmd{Driver: "test-driver-manifest-only", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) + + expectedPath := suite.tempdir + if suite.configLevel != config.ConfigEnv { + expectedPath = config.GetLocation(suite.configLevel) + } + suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", - "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.tempdir+"\n"+ + "\nInstalled test-driver-manifest-only 1.0.0 to "+expectedPath+"\n"+ "\nMust have libtest_driver installed to load this driver\n", suite.runCmd(m)) suite.driverIsInstalled("test-driver-manifest-only", false) } From a5975be13fe72bc87c59db5071ac31738a06908c Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 08:29:13 -0800 Subject: [PATCH 16/27] Fix uninstall tests --- cmd/dbc/uninstall_test.go | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/cmd/dbc/uninstall_test.go b/cmd/dbc/uninstall_test.go index 1e23208..b793209 100644 --- a/cmd/dbc/uninstall_test.go +++ b/cmd/dbc/uninstall_test.go @@ -140,27 +140,33 @@ func (suite *SubcommandTestSuite) TestUninstallMultipleLocationsNonDefault() { } func (suite *SubcommandTestSuite) TestUninstallManifestOnlyDriver() { - m := InstallCmd{Driver: "test-driver-manifest-only"}. + m := InstallCmd{Driver: "test-driver-manifest-only", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) + + expectedPath := suite.tempdir + if suite.configLevel != config.ConfigEnv { + expectedPath = config.GetLocation(suite.configLevel) + } + suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", - "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.tempdir+"\n"+ + "\nInstalled test-driver-manifest-only 1.0.0 to "+expectedPath+"\n"+ "\nMust have libtest_driver installed to load this driver\n", suite.runCmd(m)) suite.driverIsInstalled("test-driver-manifest-only", false) // Verify the sidecar folder exists before we uninstall new_sidecar_path := fmt.Sprintf("test-driver-manifest-only_%s_v1.0.0", config.PlatformTuple()) - err := os.Rename(filepath.Join(suite.tempdir, "test-driver-manifest-only"), filepath.Join(suite.tempdir, new_sidecar_path)) + err := os.Rename(filepath.Join(expectedPath, "test-driver-manifest-only"), filepath.Join(expectedPath, new_sidecar_path)) if err != nil { suite.Fail(fmt.Sprintf("Failed to rename sidecar folder. Something is wrong with this test: %v", err)) } - suite.DirExists(filepath.Join(suite.tempdir, new_sidecar_path)) + suite.DirExists(filepath.Join(expectedPath, new_sidecar_path)) // Now uninstall and verify we clean up - m = UninstallCmd{Driver: "test-driver-manifest-only"}. + m = UninstallCmd{Driver: "test-driver-manifest-only", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.validateOutput("Driver `test-driver-manifest-only` uninstalled successfully!\r\n\r\n\r ", "", suite.runCmd(m)) suite.driverIsNotInstalled("test-driver-manifest-only") - suite.NoDirExists(filepath.Join(suite.tempdir, new_sidecar_path)) + suite.NoDirExists(filepath.Join(expectedPath, new_sidecar_path)) } // See https://github.com/columnar-tech/dbc/issues/37 @@ -168,10 +174,16 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { if runtime.GOOS == "windows" { suite.T().Skip() } + + expectedPath := suite.tempdir + if suite.configLevel != config.ConfigEnv { + expectedPath = config.GetLocation(suite.configLevel) + } + m := InstallCmd{Driver: "test-driver-invalid-manifest", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) - suite.FileExists(filepath.Join(suite.tempdir, "test-driver-invalid-manifest.toml")) + suite.FileExists(filepath.Join(expectedPath, "test-driver-invalid-manifest.toml")) // The installed manifest should have a Driver.shared set to a folder, not the .so // We only need a partial struct definition to read in the Driver.shared table @@ -181,7 +193,7 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { } } var invalidManifest partialManifest - f, err := os.Open(filepath.Join(suite.tempdir, "test-driver-invalid-manifest.toml")) + f, err := os.Open(filepath.Join(expectedPath, "test-driver-invalid-manifest.toml")) if err != nil { suite.Error(err) } @@ -199,12 +211,12 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { suite.validateOutput("Driver `test-driver-invalid-manifest` uninstalled successfully!\r\n\r\n\r ", "", output) - // Ensure we don't nuke the tempdir which is the original (major) issue - suite.DirExists(suite.tempdir) + // Ensure we don't nuke the installation directory which is the original (major) issue + suite.DirExists(expectedPath) // We do remove the manifest - suite.NoFileExists(filepath.Join(suite.tempdir, "test-driver-invalid-manifest.toml")) + suite.NoFileExists(filepath.Join(expectedPath, "test-driver-invalid-manifest.toml")) // But we don't remove the driver shared folder in this edge case, so we assert // they're still around - suite.FileExists(filepath.Join(suite.tempdir, "test-driver-invalid-manifest", "libadbc_driver_invalid_manifest.so")) + suite.FileExists(filepath.Join(expectedPath, "test-driver-invalid-manifest", "libadbc_driver_invalid_manifest.so")) } From 7fa5be7fa8709a9dd8cd18f40699256ae1a159c3 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 08:41:08 -0800 Subject: [PATCH 17/27] Tear down registry correctly --- cmd/dbc/subcommand_windows_test.go | 36 +++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/cmd/dbc/subcommand_windows_test.go b/cmd/dbc/subcommand_windows_test.go index 91d0c0c..96893f5 100644 --- a/cmd/dbc/subcommand_windows_test.go +++ b/cmd/dbc/subcommand_windows_test.go @@ -17,6 +17,8 @@ package main import ( + "errors" + "io" "os" "github.com/columnar-tech/dbc/config" @@ -29,13 +31,41 @@ func (suite *SubcommandTestSuite) TearDownTest() { // Clean up the registry and filesystem after each test _, user := os.LookupEnv("DBC_TEST_LEVEL_USER") _, system := os.LookupEnv("DBC_TEST_LEVEL_SYSTEM") - regKeyADBC := "SOFTWARE\\ADBC\\Drivers" + if user { - suite.Require().NoError(registry.DeleteKey(registry.CURRENT_USER, regKeyADBC)) + suite.Require().NoError(deleteRegistryKeyRecursive(registry.CURRENT_USER, "SOFTWARE\\ADBC\\Drivers")) suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigUser))) } if system { - suite.Require().NoError(registry.DeleteKey(registry.LOCAL_MACHINE, regKeyADBC)) + suite.Require().NoError(deleteRegistryKeyRecursive(registry.LOCAL_MACHINE, "SOFTWARE\\ADBC\\Drivers")) suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigSystem))) } } + +// recursively deletes a registry key and all its subkeys +// TODO: Somewhat duplicated with clearRegistry in registry_test.go +// This is slightly more aggressive in that it deletes the top level key too +func deleteRegistryKeyRecursive(root registry.Key, path string) error { + k, err := registry.OpenKey(root, path, registry.ALL_ACCESS) + if err != nil { + if errors.Is(err, registry.ErrNotExist) { + return nil + } + return err + } + defer k.Close() + + // Delete all subkeys + subkeys, err := k.ReadSubKeyNames(-1) + if err != nil && !errors.Is(err, io.EOF) { + return err + } + for _, subkey := range subkeys { + if err := registry.DeleteKey(k, subkey); err != nil { + return err + } + } + + // Delete the top level key + return registry.DeleteKey(root, path) +} From e69744f3c2ead08099dfb15f6b91a5296ad4fb98 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 09:42:41 -0800 Subject: [PATCH 18/27] Fix bug in sidecar removal --- config/config.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/config/config.go b/config/config.go index 269a1d7..ce8b8f7 100644 --- a/config/config.go +++ b/config/config.go @@ -386,6 +386,8 @@ func UninstallDriverShared(info DriverInfo) error { } } + // Special handling to clean up manifest-only drivers + // // Manifest only drivers can come with extra files such as a LICENSE and we // create a folder next to the driver manifest to store them, same as we'd // store the actual driver shared library. Above, we find the path of this @@ -393,9 +395,20 @@ func UninstallDriverShared(info DriverInfo) error { // Driver.shared is not a valid path (it's just a name), so this trick doesn't // work. We do want to clean this folder up so here we guess what it is and // try to remove it e.g., "somedriver_macos_arm64_v1.2.3." + // + // For the User and System config levels, info.FilePath is set to the + // appropriate registry key instead of the filesystem so so we handle that + // here first. + filesystemLocation := info.FilePath + if strings.Contains(info.FilePath, "HKCU\\") { + filesystemLocation = ConfigUser.configLocation() + } else if strings.Contains(info.FilePath, "HKLM\\") { + filesystemLocation = ConfigSystem.configLocation() + } + extra_folder := fmt.Sprintf("%s_%s_v%s", info.ID, platformTuple, info.Version) extra_folder = filepath.Clean(extra_folder) - extra_path := filepath.Join(info.FilePath, extra_folder) + extra_path := filepath.Join(filesystemLocation, extra_folder) finfo, err := os.Stat(extra_path) if err == nil && finfo.IsDir() && extra_path != "." { _ = os.RemoveAll(extra_path) From eda2623aac6e5c27763b1868b7b1336015169d88 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 11:12:29 -0800 Subject: [PATCH 19/27] Restore change in install_test.go --- cmd/dbc/install_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 6d16be6..e58ae97 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -26,7 +26,8 @@ func (suite *SubcommandTestSuite) TestInstall() { GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) out := suite.runCmd(m) - suite.Contains(out, "Installed test-driver-1 1.1.0") + suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", + "\nInstalled test-driver-1 1.1.0 to "+suite.Dir()+"\n", out) suite.driverIsInstalled("test-driver-1", true) } From ed293e742246620b2c285e127a99b2804089b71e Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 11:16:07 -0800 Subject: [PATCH 20/27] Factor out expectedDir logic --- cmd/dbc/install_test.go | 14 ++------------ cmd/dbc/subcommand_test.go | 9 +++++++++ cmd/dbc/uninstall_test.go | 28 +++++++++------------------- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index e58ae97..b3035c3 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -56,13 +56,8 @@ func (suite *SubcommandTestSuite) TestInstallWithVersion() { GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) out := suite.runCmd(m) - expectedPath := suite.tempdir - if suite.configLevel != config.ConfigEnv { - expectedPath = config.GetLocation(suite.configLevel) - } - suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", - "\nInstalled test-driver-1 "+tt.expectedVersion+" to "+expectedPath+"\n", out) + "\nInstalled test-driver-1 "+tt.expectedVersion+" to "+suite.Dir()+"\n", out) suite.driverIsInstalled("test-driver-1", true) m = UninstallCmd{Driver: "test-driver-1", Level: suite.configLevel}.GetModelCustom( baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) @@ -156,13 +151,8 @@ func (suite *SubcommandTestSuite) TestInstallManifestOnlyDriver() { m := InstallCmd{Driver: "test-driver-manifest-only", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) - expectedPath := suite.tempdir - if suite.configLevel != config.ConfigEnv { - expectedPath = config.GetLocation(suite.configLevel) - } - suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", - "\nInstalled test-driver-manifest-only 1.0.0 to "+expectedPath+"\n"+ + "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.Dir()+"\n"+ "\nMust have libtest_driver installed to load this driver\n", suite.runCmd(m)) suite.driverIsInstalled("test-driver-manifest-only", false) } diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index 839e0bd..fee3991 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -123,6 +123,15 @@ func (suite *SubcommandTestSuite) getFilesInTempDir() []string { return filelist } +// Get the base directory for where drivers are installed. Use this instead of +// hardcoding checks to suite.tempdir to make tests support other config levels. +func (suite *SubcommandTestSuite) Dir() string { + if suite.configLevel == config.ConfigEnv { + return suite.tempdir + } + return config.GetLocation(suite.configLevel) +} + func (suite *SubcommandTestSuite) runCmdErr(m tea.Model) string { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() diff --git a/cmd/dbc/uninstall_test.go b/cmd/dbc/uninstall_test.go index b793209..b1b15e6 100644 --- a/cmd/dbc/uninstall_test.go +++ b/cmd/dbc/uninstall_test.go @@ -143,30 +143,25 @@ func (suite *SubcommandTestSuite) TestUninstallManifestOnlyDriver() { m := InstallCmd{Driver: "test-driver-manifest-only", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) - expectedPath := suite.tempdir - if suite.configLevel != config.ConfigEnv { - expectedPath = config.GetLocation(suite.configLevel) - } - suite.validateOutput("\r[✓] searching\r\n[✓] downloading\r\n[✓] installing\r\n[✓] verifying signature\r\n", - "\nInstalled test-driver-manifest-only 1.0.0 to "+expectedPath+"\n"+ + "\nInstalled test-driver-manifest-only 1.0.0 to "+suite.Dir()+"\n"+ "\nMust have libtest_driver installed to load this driver\n", suite.runCmd(m)) suite.driverIsInstalled("test-driver-manifest-only", false) // Verify the sidecar folder exists before we uninstall new_sidecar_path := fmt.Sprintf("test-driver-manifest-only_%s_v1.0.0", config.PlatformTuple()) - err := os.Rename(filepath.Join(expectedPath, "test-driver-manifest-only"), filepath.Join(expectedPath, new_sidecar_path)) + err := os.Rename(filepath.Join(suite.Dir(), "test-driver-manifest-only"), filepath.Join(suite.Dir(), new_sidecar_path)) if err != nil { suite.Fail(fmt.Sprintf("Failed to rename sidecar folder. Something is wrong with this test: %v", err)) } - suite.DirExists(filepath.Join(expectedPath, new_sidecar_path)) + suite.DirExists(filepath.Join(suite.Dir(), new_sidecar_path)) // Now uninstall and verify we clean up m = UninstallCmd{Driver: "test-driver-manifest-only", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.validateOutput("Driver `test-driver-manifest-only` uninstalled successfully!\r\n\r\n\r ", "", suite.runCmd(m)) suite.driverIsNotInstalled("test-driver-manifest-only") - suite.NoDirExists(filepath.Join(expectedPath, new_sidecar_path)) + suite.NoDirExists(filepath.Join(suite.Dir(), new_sidecar_path)) } // See https://github.com/columnar-tech/dbc/issues/37 @@ -175,15 +170,10 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { suite.T().Skip() } - expectedPath := suite.tempdir - if suite.configLevel != config.ConfigEnv { - expectedPath = config.GetLocation(suite.configLevel) - } - m := InstallCmd{Driver: "test-driver-invalid-manifest", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) - suite.FileExists(filepath.Join(expectedPath, "test-driver-invalid-manifest.toml")) + suite.FileExists(filepath.Join(suite.Dir(), "test-driver-invalid-manifest.toml")) // The installed manifest should have a Driver.shared set to a folder, not the .so // We only need a partial struct definition to read in the Driver.shared table @@ -193,7 +183,7 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { } } var invalidManifest partialManifest - f, err := os.Open(filepath.Join(expectedPath, "test-driver-invalid-manifest.toml")) + f, err := os.Open(filepath.Join(suite.Dir(), "test-driver-invalid-manifest.toml")) if err != nil { suite.Error(err) } @@ -212,11 +202,11 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { suite.validateOutput("Driver `test-driver-invalid-manifest` uninstalled successfully!\r\n\r\n\r ", "", output) // Ensure we don't nuke the installation directory which is the original (major) issue - suite.DirExists(expectedPath) + suite.DirExists(suite.Dir()) // We do remove the manifest - suite.NoFileExists(filepath.Join(expectedPath, "test-driver-invalid-manifest.toml")) + suite.NoFileExists(filepath.Join(suite.Dir(), "test-driver-invalid-manifest.toml")) // But we don't remove the driver shared folder in this edge case, so we assert // they're still around - suite.FileExists(filepath.Join(expectedPath, "test-driver-invalid-manifest", "libadbc_driver_invalid_manifest.so")) + suite.FileExists(filepath.Join(suite.Dir(), "test-driver-invalid-manifest", "libadbc_driver_invalid_manifest.so")) } From 69eaa04a6c64f09450d344f34d2e48e6f87bf69c Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 11:33:14 -0800 Subject: [PATCH 21/27] Fix not removing symlink to show off this pr --- cmd/dbc/uninstall_test.go | 22 ++++++++++++++++++++++ config/dirs_unixlike.go | 11 +++++++++++ config/driver.go | 10 ++++++++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/cmd/dbc/uninstall_test.go b/cmd/dbc/uninstall_test.go index b1b15e6..ada59fa 100644 --- a/cmd/dbc/uninstall_test.go +++ b/cmd/dbc/uninstall_test.go @@ -210,3 +210,25 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { // they're still around suite.FileExists(filepath.Join(suite.Dir(), "test-driver-invalid-manifest", "libadbc_driver_invalid_manifest.so")) } + +func (suite *SubcommandTestSuite) TestUninstallRemovesSymlink() { + // Install a driver + m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. + GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) + _ = suite.runCmd(m) + suite.driverIsInstalled("test-driver-1", true) + + // Verify symlink is in place in the parent dir and is actually a symlink + manifestPath := filepath.Join(suite.Dir(), "..", "test-driver-1.toml") + suite.FileExists(manifestPath) + info, err := os.Lstat(manifestPath) + suite.NoError(err) + suite.Equal(os.ModeSymlink, info.Mode()&os.ModeSymlink, "Expected test-driver-1.toml to be a symlink") + + // Uninstall the driver + m = UninstallCmd{Driver: "test-driver-1", Level: suite.configLevel}.GetModel() + _ = suite.runCmd(m) + + // Verify symlink is gone + suite.NoFileExists(manifestPath) +} diff --git a/config/dirs_unixlike.go b/config/dirs_unixlike.go index 23e23b6..4a4e9ad 100644 --- a/config/dirs_unixlike.go +++ b/config/dirs_unixlike.go @@ -118,6 +118,17 @@ func UninstallDriver(_ Config, info DriverInfo) error { return fmt.Errorf("error removing manifest %s: %w", manifest, err) } + // Remove the symlink created during installation (one level up from the + // manifest) + // TODO: Remove this when the driver managers are fixed (>=1.8.1). + safeFilePath := filepath.Clean(info.FilePath) + parentDir := filepath.Dir(safeFilePath) + safeDriverID := filepath.Base(info.ID) // Strip any path separators from ID + symlink := filepath.Join(parentDir, safeDriverID+".toml") + if filepath.Dir(symlink) == parentDir { + os.Remove(symlink) + } + if err := UninstallDriverShared(info); err != nil { return fmt.Errorf("failed to delete driver shared object: %w", err) } diff --git a/config/driver.go b/config/driver.go index 0378792..0893d62 100644 --- a/config/driver.go +++ b/config/driver.go @@ -186,8 +186,14 @@ func createDriverManifest(location string, driver DriverInfo) error { // installing. // // TODO: Remove this when the driver managers are fixed (>=1.8.1). - symlink := filepath.Join(location, "..", driver.ID+".toml") - os.Symlink(manifest_path, symlink) + // Security: Clean paths and use Base to prevent path traversal attacks + cleanedLocation := filepath.Clean(location) + parentDir := filepath.Dir(cleanedLocation) + safeDriverID := filepath.Base(driver.ID) // Strip any path separators from ID + symlink := filepath.Join(parentDir, safeDriverID+".toml") + if filepath.Dir(symlink) == parentDir { + os.Symlink(manifest_path, symlink) + } toEncode := tomlDriverInfo{ ManifestVersion: currentManifestVersion, From 139ef61757bfcec275878a0427baddb1665defee Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 11:52:55 -0800 Subject: [PATCH 22/27] Fix symlink behavior on all plats --- cmd/dbc/install_test.go | 20 ++++++++++++++++++++ cmd/dbc/uninstall_test.go | 4 ++++ config/dirs_unixlike.go | 8 +------- config/dirs_windows.go | 3 +++ config/driver.go | 31 +++++++++++++++++++++++-------- 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index b3035c3..4f5b75d 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -17,6 +17,7 @@ package main import ( "os" "path/filepath" + "runtime" "github.com/columnar-tech/dbc/config" ) @@ -248,3 +249,22 @@ func (suite *SubcommandTestSuite) TestInstallGitignorePreserveUserModified() { } suite.Equal(userContent, string(data)) } + +func (suite *SubcommandTestSuite) TestInstallCreatesSymlinks() { + if runtime.GOOS == "Windows" && (suite.configLevel == config.ConfigUser || suite.configLevel == config.ConfigSystem) { + suite.T().Skip("Symlinks aren't created on Windows for User and System config levels") + } + + // Install a driver + m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. + GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) + _ = suite.runCmd(m) + suite.driverIsInstalled("test-driver-1", true) + + // Verify symlink is in place in the parent dir and is actually a symlink + manifestPath := filepath.Join(suite.Dir(), "..", "test-driver-1.toml") + suite.FileExists(manifestPath) + info, err := os.Lstat(manifestPath) + suite.NoError(err) + suite.Equal(os.ModeSymlink, info.Mode()&os.ModeSymlink, "Expected test-driver-1.toml to be a symlink") +} diff --git a/cmd/dbc/uninstall_test.go b/cmd/dbc/uninstall_test.go index ada59fa..ca8174c 100644 --- a/cmd/dbc/uninstall_test.go +++ b/cmd/dbc/uninstall_test.go @@ -212,6 +212,10 @@ func (suite *SubcommandTestSuite) TestUninstallInvalidManifest() { } func (suite *SubcommandTestSuite) TestUninstallRemovesSymlink() { + if runtime.GOOS == "windows" && (suite.configLevel == config.ConfigUser || suite.configLevel == config.ConfigSystem) { + suite.T().Skip("Symlinks aren't created on Windows for User and System config levels") + } + // Install a driver m := InstallCmd{Driver: "test-driver-1", Level: suite.configLevel}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) diff --git a/config/dirs_unixlike.go b/config/dirs_unixlike.go index 4a4e9ad..0b44c87 100644 --- a/config/dirs_unixlike.go +++ b/config/dirs_unixlike.go @@ -121,13 +121,7 @@ func UninstallDriver(_ Config, info DriverInfo) error { // Remove the symlink created during installation (one level up from the // manifest) // TODO: Remove this when the driver managers are fixed (>=1.8.1). - safeFilePath := filepath.Clean(info.FilePath) - parentDir := filepath.Dir(safeFilePath) - safeDriverID := filepath.Base(info.ID) // Strip any path separators from ID - symlink := filepath.Join(parentDir, safeDriverID+".toml") - if filepath.Dir(symlink) == parentDir { - os.Remove(symlink) - } + removeManifestSymlink(info.FilePath, info.ID) if err := UninstallDriverShared(info); err != nil { return fmt.Errorf("failed to delete driver shared object: %w", err) diff --git a/config/dirs_windows.go b/config/dirs_windows.go index edbdcad..93e50d3 100644 --- a/config/dirs_windows.go +++ b/config/dirs_windows.go @@ -345,6 +345,9 @@ func UninstallDriver(cfg Config, info DriverInfo) error { if err := os.Remove(manifest); err != nil { return fmt.Errorf("error removing manifest %s: %w", manifest, err) } + + // TODO: Remove this when the driver managers are fixed (>=1.8.1). + removeManifestSymlink(info.FilePath, info.ID) } return nil diff --git a/config/driver.go b/config/driver.go index 0893d62..6df4f23 100644 --- a/config/driver.go +++ b/config/driver.go @@ -164,6 +164,28 @@ func loadDriverFromManifest(prefix, driverName string) (DriverInfo, error) { return m.DriverInfo, nil } +// Create a symlink to manifestPath in the parent dir +func createManifestSymlink(location, driverID, manifestPath string) { + parentDir := filepath.Dir(filepath.Clean(location)) + safeDriverID := filepath.Base(driverID) + symlink := filepath.Join(parentDir, safeDriverID+".toml") + + if filepath.Dir(symlink) == parentDir { + os.Symlink(manifestPath, symlink) + } +} + +// Remove the symlink to manifestPath in the parent dir +func removeManifestSymlink(filePath, driverID string) { + parentDir := filepath.Dir(filepath.Clean(filePath)) + safeDriverID := filepath.Base(driverID) + symlink := filepath.Join(parentDir, safeDriverID+".toml") + + if filepath.Dir(symlink) == parentDir { + os.Remove(symlink) + } +} + func createDriverManifest(location string, driver DriverInfo) error { if _, err := os.Stat(location); errors.Is(err, fs.ErrNotExist) { if err := os.MkdirAll(location, 0755); err != nil { @@ -186,14 +208,7 @@ func createDriverManifest(location string, driver DriverInfo) error { // installing. // // TODO: Remove this when the driver managers are fixed (>=1.8.1). - // Security: Clean paths and use Base to prevent path traversal attacks - cleanedLocation := filepath.Clean(location) - parentDir := filepath.Dir(cleanedLocation) - safeDriverID := filepath.Base(driver.ID) // Strip any path separators from ID - symlink := filepath.Join(parentDir, safeDriverID+".toml") - if filepath.Dir(symlink) == parentDir { - os.Symlink(manifest_path, symlink) - } + createManifestSymlink(location, driver.ID, manifest_path) toEncode := tomlDriverInfo{ ManifestVersion: currentManifestVersion, From 1512cd573f79ac036efba1d23a32a7c694e9680d Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Fri, 19 Dec 2025 11:56:43 -0800 Subject: [PATCH 23/27] whoops --- cmd/dbc/install_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 4f5b75d..37c66f9 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -251,7 +251,7 @@ func (suite *SubcommandTestSuite) TestInstallGitignorePreserveUserModified() { } func (suite *SubcommandTestSuite) TestInstallCreatesSymlinks() { - if runtime.GOOS == "Windows" && (suite.configLevel == config.ConfigUser || suite.configLevel == config.ConfigSystem) { + if runtime.GOOS == "windows" && (suite.configLevel == config.ConfigUser || suite.configLevel == config.ConfigSystem) { suite.T().Skip("Symlinks aren't created on Windows for User and System config levels") } From b7a32891c7c43b89b06edf4b6ce76564cebae75e Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Tue, 23 Dec 2025 14:55:10 -0800 Subject: [PATCH 24/27] Remove GetLocation wrapper, export ConfigLocation --- cmd/dbc/subcommand_test.go | 2 +- cmd/dbc/subcommand_unix_test.go | 4 ++-- cmd/dbc/subcommand_windows_test.go | 4 ++-- config/config.go | 10 +++------- config/dirs_unixlike.go | 2 +- config/unixlike_test.go | 6 +++--- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index fee3991..4e436e4 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -129,7 +129,7 @@ func (suite *SubcommandTestSuite) Dir() string { if suite.configLevel == config.ConfigEnv { return suite.tempdir } - return config.GetLocation(suite.configLevel) + return suite.configLevel.ConfigLocation() } func (suite *SubcommandTestSuite) runCmdErr(m tea.Model) string { diff --git a/cmd/dbc/subcommand_unix_test.go b/cmd/dbc/subcommand_unix_test.go index b855fbc..0497f85 100644 --- a/cmd/dbc/subcommand_unix_test.go +++ b/cmd/dbc/subcommand_unix_test.go @@ -29,9 +29,9 @@ func (suite *SubcommandTestSuite) TearDownTest() { _, user := os.LookupEnv("DBC_TEST_LEVEL_USER") _, system := os.LookupEnv("DBC_TEST_LEVEL_SYSTEM") if user { - suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigUser))) + suite.Require().NoError(os.RemoveAll(config.ConfigUser.ConfigLocation())) } if system { - suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigSystem))) + suite.Require().NoError(os.RemoveAll(config.ConfigSystem.ConfigLocation())) } } diff --git a/cmd/dbc/subcommand_windows_test.go b/cmd/dbc/subcommand_windows_test.go index 96893f5..826b8d6 100644 --- a/cmd/dbc/subcommand_windows_test.go +++ b/cmd/dbc/subcommand_windows_test.go @@ -34,11 +34,11 @@ func (suite *SubcommandTestSuite) TearDownTest() { if user { suite.Require().NoError(deleteRegistryKeyRecursive(registry.CURRENT_USER, "SOFTWARE\\ADBC\\Drivers")) - suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigUser))) + suite.Require().NoError(os.RemoveAll(config.Get()[config.ConfigUser].Location)) } if system { suite.Require().NoError(deleteRegistryKeyRecursive(registry.LOCAL_MACHINE, "SOFTWARE\\ADBC\\Drivers")) - suite.Require().NoError(os.RemoveAll(config.GetLocation(config.ConfigSystem))) + suite.Require().NoError(os.RemoveAll(config.Get()[config.ConfigSystem].Location)) } } diff --git a/config/config.go b/config/config.go index ce8b8f7..0f5d1b0 100644 --- a/config/config.go +++ b/config/config.go @@ -97,10 +97,6 @@ func (c ConfigLevel) String() string { } } -func GetLocation(lvl ConfigLevel) string { - return lvl.configLocation() -} - func (c *ConfigLevel) UnmarshalText(b []byte) error { switch strings.ToLower(strings.TrimSpace(string(b))) { case "system": @@ -167,7 +163,7 @@ func loadDir(dir string) (map[string]DriverInfo, error) { } func loadConfig(lvl ConfigLevel) Config { - cfg := Config{Level: lvl, Location: lvl.configLocation()} + cfg := Config{Level: lvl, Location: lvl.ConfigLocation()} if cfg.Location == "" { return cfg } @@ -401,9 +397,9 @@ func UninstallDriverShared(info DriverInfo) error { // here first. filesystemLocation := info.FilePath if strings.Contains(info.FilePath, "HKCU\\") { - filesystemLocation = ConfigUser.configLocation() + filesystemLocation = ConfigUser.ConfigLocation() } else if strings.Contains(info.FilePath, "HKLM\\") { - filesystemLocation = ConfigSystem.configLocation() + filesystemLocation = ConfigSystem.ConfigLocation() } extra_folder := fmt.Sprintf("%s_%s_v%s", info.ID, platformTuple, info.Version) diff --git a/config/dirs_unixlike.go b/config/dirs_unixlike.go index 0b44c87..41882af 100644 --- a/config/dirs_unixlike.go +++ b/config/dirs_unixlike.go @@ -63,7 +63,7 @@ func init() { } } -func (c ConfigLevel) configLocation() string { +func (c ConfigLevel) ConfigLocation() string { switch c { case ConfigSystem: return systemConfigDir diff --git a/config/unixlike_test.go b/config/unixlike_test.go index 9301550..f7dcedd 100644 --- a/config/unixlike_test.go +++ b/config/unixlike_test.go @@ -28,9 +28,9 @@ func TestSystemConfigDir(t *testing.T) { os := runtime.GOOS if os == "darwin" { - assert.Equal(t, "/Library/Application Support/ADBC/Drivers", ConfigSystem.configLocation()) + assert.Equal(t, "/Library/Application Support/ADBC/Drivers", ConfigSystem.ConfigLocation()) } else { - assert.Equal(t, "/etc/adbc/drivers", ConfigSystem.configLocation()) + assert.Equal(t, "/etc/adbc/drivers", ConfigSystem.ConfigLocation()) } } @@ -41,6 +41,6 @@ func TestSystemConfigWithEnv(t *testing.T) { prefix = os.Getenv("CONDA_PREFIX") } if prefix != "" { - assert.Equal(t, prefix+"/etc/adbc/drivers", ConfigSystem.configLocation()) + assert.Equal(t, prefix+"/etc/adbc/drivers", ConfigSystem.ConfigLocation()) } } From 643f102ef1483daed5fdcb78f09d621765ac4cff Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Tue, 23 Dec 2025 15:28:36 -0800 Subject: [PATCH 25/27] Use suite.T().Setenv --- cmd/dbc/install_test.go | 32 ++++++++++++------------------ cmd/dbc/subcommand_test.go | 2 +- cmd/dbc/subcommand_unix_test.go | 2 -- cmd/dbc/subcommand_windows_test.go | 2 -- cmd/dbc/sync_test.go | 10 ++++------ config/config_test.go | 16 +++------------ 6 files changed, 21 insertions(+), 43 deletions(-) diff --git a/cmd/dbc/install_test.go b/cmd/dbc/install_test.go index 37c66f9..74eaa9b 100644 --- a/cmd/dbc/install_test.go +++ b/cmd/dbc/install_test.go @@ -92,9 +92,8 @@ func (suite *SubcommandTestSuite) TestReinstallUpdateVersion() { } func (suite *SubcommandTestSuite) TestInstallVenv() { - os.Unsetenv("ADBC_DRIVER_PATH") - os.Setenv("VIRTUAL_ENV", suite.tempdir) - defer os.Unsetenv("VIRTUAL_ENV") + suite.T().Setenv("ADBC_DRIVER_PATH", "") + suite.T().Setenv("VIRTUAL_ENV", suite.tempdir) m := InstallCmd{Driver: "test-driver-1"}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) @@ -109,9 +108,10 @@ func (suite *SubcommandTestSuite) TestInstallEnvironmentPrecedence() { driver_path := filepath.Join(suite.tempdir, "driver_path") venv_path := filepath.Join(suite.tempdir, "venv_path") conda_path := filepath.Join(suite.tempdir, "conda_path") - os.Setenv("ADBC_DRIVER_PATH", driver_path) - os.Setenv("VIRTUAL_ENV", venv_path) - os.Setenv("CONDA_PREFIX", conda_path) + + suite.T().Setenv("ADBC_DRIVER_PATH", driver_path) + suite.T().Setenv("VIRTUAL_ENV", venv_path) + suite.T().Setenv("CONDA_PREFIX", conda_path) m := InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) @@ -121,26 +121,23 @@ func (suite *SubcommandTestSuite) TestInstallEnvironmentPrecedence() { suite.NoFileExists(filepath.Join(venv_path, "test-driver-1.toml")) suite.NoFileExists(filepath.Join(conda_path, "test-driver-1.toml")) - os.Unsetenv("ADBC_DRIVER_PATH") + suite.T().Setenv("ADBC_DRIVER_PATH", "") m = InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(venv_path, "etc", "adbc", "drivers", "test-driver-1.toml")) suite.NoFileExists(filepath.Join(conda_path, "etc", "adbc", "drivers", "test-driver-1.toml")) - os.Unsetenv("VIRTUAL_ENV") + suite.T().Setenv("VIRTUAL_ENV", "") m = InstallCmd{Driver: "test-driver-1", Level: config.ConfigEnv}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) suite.runCmd(m) suite.FileExists(filepath.Join(conda_path, "etc", "adbc", "drivers", "test-driver-1.toml")) - - os.Unsetenv("CONDA_PREFIX") } func (suite *SubcommandTestSuite) TestInstallCondaPrefix() { - os.Unsetenv("ADBC_DRIVER_PATH") - os.Setenv("CONDA_PREFIX", suite.tempdir) - defer os.Unsetenv("CONDA_PREFIX") + suite.T().Setenv("ADBC_DRIVER_PATH", "") + suite.T().Setenv("CONDA_PREFIX", suite.tempdir) m := InstallCmd{Driver: "test-driver-1"}. GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) @@ -176,8 +173,7 @@ func (suite *SubcommandTestSuite) TestInstallDriverNoSignature() { func (suite *SubcommandTestSuite) TestInstallGitignoreDefaultBehavior() { driver_path := filepath.Join(suite.tempdir, "driver_path") ignorePath := filepath.Join(driver_path, ".gitignore") - os.Setenv("ADBC_DRIVER_PATH", driver_path) - defer os.Unsetenv("ADBC_DRIVER_PATH") + suite.T().Setenv("ADBC_DRIVER_PATH", driver_path) suite.NoFileExists(ignorePath) @@ -191,8 +187,7 @@ func (suite *SubcommandTestSuite) TestInstallGitignoreDefaultBehavior() { func (suite *SubcommandTestSuite) TestInstallGitignoreExisingDir() { driver_path := filepath.Join(suite.tempdir, "driver_path") ignorePath := filepath.Join(driver_path, ".gitignore") - os.Setenv("ADBC_DRIVER_PATH", driver_path) - defer os.Unsetenv("ADBC_DRIVER_PATH") + suite.T().Setenv("ADBC_DRIVER_PATH", driver_path) // Create the directory before we install the driver mkdirerr := os.MkdirAll(driver_path, 0o755) @@ -215,8 +210,7 @@ func (suite *SubcommandTestSuite) TestInstallGitignoreExisingDir() { func (suite *SubcommandTestSuite) TestInstallGitignorePreserveUserModified() { driver_path := filepath.Join(suite.tempdir, "driver_path") ignorePath := filepath.Join(driver_path, ".gitignore") - os.Setenv("ADBC_DRIVER_PATH", driver_path) - defer os.Unsetenv("ADBC_DRIVER_PATH") + suite.T().Setenv("ADBC_DRIVER_PATH", driver_path) suite.NoFileExists(ignorePath) diff --git a/cmd/dbc/subcommand_test.go b/cmd/dbc/subcommand_test.go index 4e436e4..692af70 100644 --- a/cmd/dbc/subcommand_test.go +++ b/cmd/dbc/subcommand_test.go @@ -101,7 +101,7 @@ func (suite *SubcommandTestSuite) SetupSuite() { func (suite *SubcommandTestSuite) SetupTest() { suite.tempdir = suite.T().TempDir() - suite.Require().NoError(os.Setenv("ADBC_DRIVER_PATH", suite.tempdir)) + suite.T().Setenv("ADBC_DRIVER_PATH", suite.tempdir) } func (suite *SubcommandTestSuite) TearDownSuite() { diff --git a/cmd/dbc/subcommand_unix_test.go b/cmd/dbc/subcommand_unix_test.go index 0497f85..6e16b34 100644 --- a/cmd/dbc/subcommand_unix_test.go +++ b/cmd/dbc/subcommand_unix_test.go @@ -23,8 +23,6 @@ import ( ) func (suite *SubcommandTestSuite) TearDownTest() { - suite.Require().NoError(os.Unsetenv("ADBC_DRIVER_PATH")) - // Clean up filesystem after each test _, user := os.LookupEnv("DBC_TEST_LEVEL_USER") _, system := os.LookupEnv("DBC_TEST_LEVEL_SYSTEM") diff --git a/cmd/dbc/subcommand_windows_test.go b/cmd/dbc/subcommand_windows_test.go index 826b8d6..bdcecaa 100644 --- a/cmd/dbc/subcommand_windows_test.go +++ b/cmd/dbc/subcommand_windows_test.go @@ -26,8 +26,6 @@ import ( ) func (suite *SubcommandTestSuite) TearDownTest() { - suite.Require().NoError(os.Unsetenv("ADBC_DRIVER_PATH")) - // Clean up the registry and filesystem after each test _, user := os.LookupEnv("DBC_TEST_LEVEL_USER") _, system := os.LookupEnv("DBC_TEST_LEVEL_SYSTEM") diff --git a/cmd/dbc/sync_test.go b/cmd/dbc/sync_test.go index 97eb0e5..54a3b65 100644 --- a/cmd/dbc/sync_test.go +++ b/cmd/dbc/sync_test.go @@ -76,7 +76,7 @@ func (suite *SubcommandTestSuite) TestSyncWithVersion() { } func (suite *SubcommandTestSuite) TestSyncVirtualEnv() { - os.Unsetenv("ADBC_DRIVER_PATH") + suite.T().Setenv("ADBC_DRIVER_PATH", "") m := InitCmd{Path: filepath.Join(suite.tempdir, "dbc.toml")}.GetModel() suite.runCmd(m) @@ -84,8 +84,7 @@ func (suite *SubcommandTestSuite) TestSyncVirtualEnv() { m = AddCmd{Path: filepath.Join(suite.tempdir, "dbc.toml"), Driver: "test-driver-1"}.GetModel() suite.runCmd(m) - os.Setenv("VIRTUAL_ENV", suite.tempdir) - defer os.Unsetenv("VIRTUAL_ENV") + suite.T().Setenv("VIRTUAL_ENV", suite.tempdir) m = SyncCmd{ Path: filepath.Join(suite.tempdir, "dbc.toml"), @@ -102,7 +101,7 @@ func (suite *SubcommandTestSuite) TestSyncVirtualEnv() { } func (suite *SubcommandTestSuite) TestSyncCondaPrefix() { - os.Unsetenv("ADBC_DRIVER_PATH") + suite.T().Setenv("ADBC_DRIVER_PATH", "") m := InitCmd{Path: filepath.Join(suite.tempdir, "dbc.toml")}.GetModel() suite.runCmd(m) @@ -110,8 +109,7 @@ func (suite *SubcommandTestSuite) TestSyncCondaPrefix() { m = AddCmd{Path: filepath.Join(suite.tempdir, "dbc.toml"), Driver: "test-driver-1"}.GetModel() suite.runCmd(m) - os.Setenv("CONDA_PREFIX", suite.tempdir) - defer os.Unsetenv("CONDA_PREFIX") + suite.T().Setenv("CONDA_PREFIX", suite.tempdir) m = SyncCmd{ Path: filepath.Join(suite.tempdir, "dbc.toml"), diff --git a/config/config_test.go b/config/config_test.go index 77c2cd2..5cefb11 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -23,21 +23,11 @@ import ( ) func TestConfigEnvVarHierarchy(t *testing.T) { - // Record old values and reset when done - originalAdbcConfigPath := os.Getenv("ADBC_DRIVER_PATH") - originalVirtualEnv := os.Getenv("VIRTUAL_ENV") - originalCondaPrefix := os.Getenv("CONDA_PREFIX") - defer func() { - os.Setenv("ADBC_DRIVER_PATH", originalAdbcConfigPath) - os.Setenv("VIRTUAL_ENV", originalVirtualEnv) - os.Setenv("CONDA_PREFIX", originalCondaPrefix) - }() - // Test the order is honored (ADBC_DRIVER_PATH before VIRTUAL_ENV before // CONDA_PREFIX) and unset each one (in order) to verify. - os.Setenv("ADBC_DRIVER_PATH", "some_adbc_driver_path") - os.Setenv("VIRTUAL_ENV", "some_virtual_env") - os.Setenv("CONDA_PREFIX", "some_conda_prefix") + t.Setenv("ADBC_DRIVER_PATH", "some_adbc_driver_path") + t.Setenv("VIRTUAL_ENV", "some_virtual_env") + t.Setenv("CONDA_PREFIX", "some_conda_prefix") cfg := loadConfig(ConfigEnv) assert.Equal(t, "some_adbc_driver_path"+string(filepath.ListSeparator)+ From 5957bdf097b49daf23379e145801358b0d96a162 Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Tue, 23 Dec 2025 15:32:29 -0800 Subject: [PATCH 26/27] fix windows --- config/dirs_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/dirs_windows.go b/config/dirs_windows.go index 93e50d3..edbe217 100644 --- a/config/dirs_windows.go +++ b/config/dirs_windows.go @@ -162,7 +162,7 @@ func driverInfoFromKey(k registry.Key, driverName string, lvl ConfigLevel) (di D } func loadRegistryConfig(lvl ConfigLevel) Config { - ret := Config{Level: lvl, Location: lvl.configLocation()} + ret := Config{Level: lvl, Location: lvl.ConfigLocation()} k, err := registry.OpenKey(lvl.key(), regKeyADBC, registry.READ) if err != nil { return ret From 0336048ff5db3c2c94a2b5ba3e2af68908a8685c Mon Sep 17 00:00:00 2001 From: Bryce Mecum Date: Tue, 23 Dec 2025 16:15:37 -0800 Subject: [PATCH 27/27] whoops --- config/dirs_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/dirs_windows.go b/config/dirs_windows.go index edbe217..45bee85 100644 --- a/config/dirs_windows.go +++ b/config/dirs_windows.go @@ -58,7 +58,7 @@ func (c ConfigLevel) rootKeyString() string { } } -func (c ConfigLevel) configLocation() string { +func (c ConfigLevel) ConfigLocation() string { var prefix string switch c { case ConfigSystem: