Skip to content

Commit

Permalink
Remove more side effects from application config testing (#1684)
Browse files Browse the repository at this point in the history
* remove a few side effects from config testing

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* fix xdg config app name prefix

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* account for restoring and protecting xdg state throughout testing

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

---------

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
  • Loading branch information
wagoodman authored Mar 20, 2023
1 parent f11a7b5 commit 100cf10
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 37 deletions.
7 changes: 3 additions & 4 deletions internal/config/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,12 @@ func loadConfig(v *viper.Viper, configPath string) error {
}
}

// 4. look for .<appname>/config.yaml in xdg locations (starting with xdg home config dir, then moving upwards)

// 4. look for <appname>/config.yaml in xdg locations (starting with xdg home config dir, then moving upwards)
v.SetConfigName("config")
configPath = path.Join(xdg.ConfigHome, "."+internal.ApplicationName)
configPath = path.Join(xdg.ConfigHome, internal.ApplicationName)
v.AddConfigPath(configPath)
for _, dir := range xdg.ConfigDirs {
v.AddConfigPath(path.Join(dir, "."+internal.ApplicationName))
v.AddConfigPath(path.Join(dir, internal.ApplicationName))
}
if err = v.ReadInConfig(); err == nil {
v.Set("config", v.ConfigFileUsed())
Expand Down
74 changes: 41 additions & 33 deletions internal/config/application_test.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,43 @@
package config

import (
"fmt"
"os"
"path"
"testing"

"github.com/adrg/xdg"
"github.com/mitchellh/go-homedir"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// TODO: set negative case when config.yaml is no longer a valid option
func TestApplicationConfig(t *testing.T) {
// disable homedir package cache for testing
originalCacheOpt := homedir.DisableCache
homedir.DisableCache = true
t.Cleanup(func() {
homedir.DisableCache = originalCacheOpt
})

// ensure we have no side effects for xdg package for future tests
originalXDG := os.Getenv("XDG_CONFIG_HOME")
t.Cleanup(func() {
// note: we're not using t.Setenv since the effect we're trying to eliminate is within the xdg package
require.NoError(t, os.Setenv("XDG_CONFIG_HOME", originalXDG))
xdg.Reload()
})

// config is picked up at desired configuration paths
// VALID: .syft.yaml, .syft/config.yaml, ~/.syft.yaml, <XDG_CONFIG_HOME>/syft/config.yaml
// DEPRECATED: config.yaml is currently supported by
tests := []struct {
name string
setup func(t *testing.T) string
assertions func(t *testing.T, app *Application)
Cleanup func(t *testing.T)
cleanup func()
}{
{
name: "explicit config",
Expand All @@ -29,92 +47,82 @@ func TestApplicationConfig(t *testing.T) {
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-explicit-config", app.File)
},
Cleanup: func(t *testing.T) {},
},
{
name: "current working directory named config",
setup: func(t *testing.T) string {
err := os.Chdir("./test-fixtures/config-wd-file") // change application cwd to test-fixtures
if err != nil {
t.Fatalf("%s failed to change cwd: %+v", t.Name(), err)
}
require.NoError(t, err)
return ""
},
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-wd-named-config", app.File)
},
Cleanup: func(t *testing.T) {},
},
{
name: "current working directory syft dir config",
setup: func(t *testing.T) string {
err := os.Chdir("./test-fixtures/config-dir-test") // change application cwd to test-fixtures
if err != nil {
t.Fatalf("%s failed to change cwd: %+v", t.Name(), err)
}
require.NoError(t, err)
return ""
},
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-dir-config", app.File)
},
Cleanup: func(t *testing.T) {},
},
{
name: "home directory file config",
setup: func(t *testing.T) string {
// Because Setenv affects the whole process, it cannot be used in parallel tests or
// tests with parallel ancestors: see separate XDG test for consequence of this
t.Setenv("HOME", "./test-fixtures/config-home-test")
err := os.Link("./test-fixtures/config-home-test/config-file/.syft.yaml", "./test-fixtures/config-home-test/.syft.yaml")
if err != nil {
t.Fatalf("%s failed to link home config: %+v", t.Name(), err)
}
t.Setenv("HOME", "./test-fixtures/config-home-test/config-file")
return ""
},
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-home-config", app.File)
},
Cleanup: func(t *testing.T) {
err := os.Remove("./test-fixtures/config-home-test/.syft.yaml") //
if err != nil {
t.Fatalf("%s failed to remove home config link: %+v", t.Name(), err)
}
},
},
{
name: "XDG file config",
setup: func(t *testing.T) string {
wd, err := os.Getwd()
if err != nil {
t.Fatalf("%s: failed to get working directory: %+v", t.Name(), err)
}
require.NoError(t, err)
configDir := path.Join(wd, "./test-fixtures/config-home-test") // set HOME to testdata
t.Setenv("XDG_CONFIG_DIRS", configDir)
// note: this explicitly has multiple XDG paths, make certain we use the first VALID one (not the first one)
t.Setenv("XDG_CONFIG_DIRS", fmt.Sprintf("/another/foo/bar:%s", configDir))
xdg.Reload()
return ""
},
assertions: func(t *testing.T, app *Application) {
assert.Equal(t, "test-home-XDG-config", app.File)
},
Cleanup: func(t *testing.T) {},
cleanup: func() {
require.NoError(t, os.Unsetenv("XDG_CONFIG_DIRS"))
xdg.Reload()
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
defer test.Cleanup(t)
wd, err := os.Getwd()
if err != nil {
t.Fatalf("failed to get working directory: %+v", err)
if test.cleanup != nil {
t.Cleanup(test.cleanup)
}
wd, err := os.Getwd()
require.NoError(t, err)

defer os.Chdir(wd) // reset working directory after test
application := &Application{}
viperInstance := viper.New()

// this will override home in case you are running this test locally and DO have a syft config
// in your home directory... now it will be ignored. Same for XDG_CONFIG_DIRS.
t.Setenv("HOME", "/foo/bar")
t.Setenv("XDG_CONFIG_DIRS", "/foo/bar")
xdg.Reload()

configPath := test.setup(t)
err = application.LoadAllValues(viperInstance, configPath)
if err != nil {
t.Fatalf("failed to load application config: %+v", err)
}
require.NoError(t, err)
test.assertions(t, application)
})
}
Expand Down

0 comments on commit 100cf10

Please sign in to comment.