package main import ( "os" "path/filepath" "testing" ) // Profiles and definitions are the tool's own files, and a binary installed with // `go install` sits in $GOPATH/bin where neither of them exists. They need a // per-user directory, and they need the same one on Linux, macOS and Windows, // which is what os.UserConfigDir answers and a hardcoded ~/.config does not. func TestDataDirectoryPrefersTheExecutableDirectory(t *testing.T) { userDir := t.TempDir() t.Cleanup(stubUserConfigDir(t, userDir)) exeDir := t.TempDir() if err := os.MkdirAll(filepath.Join(exeDir, "definitions"), 0o755); err != nil { t.Fatal(err) } cwd := t.TempDir() if err := os.MkdirAll(filepath.Join(cwd, "definitions"), 0o755); err != nil { t.Fatal(err) } got := resolveDataDir(exeDir, cwd, "definitions") if want := filepath.Join(exeDir, "definitions"); got != want { t.Errorf("resolveDataDir() = %q, want %q: the directory holding the binary wins", got, want) } } func TestDataDirectoryFallsBackToTheWorkingDirectory(t *testing.T) { userDir := t.TempDir() t.Cleanup(stubUserConfigDir(t, userDir)) exeDir := t.TempDir() // no definitions/ beside the binary cwd := t.TempDir() if err := os.MkdirAll(filepath.Join(cwd, "definitions"), 0o755); err != nil { t.Fatal(err) } got := resolveDataDir(exeDir, cwd, "definitions") if want := filepath.Join(cwd, "definitions"); got != want { t.Errorf("resolveDataDir() = %q, want %q: a repository checkout wins over the user directory", got, want) } } func TestDataDirectoryFallsBackToTheUserDirectory(t *testing.T) { userDir := t.TempDir() t.Cleanup(stubUserConfigDir(t, userDir)) got := resolveDataDir(t.TempDir(), t.TempDir(), "definitions") if want := filepath.Join(userDir, "qmk-rgb-tool", "definitions"); got != want { t.Errorf("resolveDataDir() = %q, want %q", got, want) } } // When nothing exists yet, the directory a fetch or a save creates is the user's, // not one beside a binary in $GOPATH/bin that nobody owns and that a reinstall // would replace. func TestDataDirectoryIsCreatedUnderTheUserDirectory(t *testing.T) { userDir := t.TempDir() t.Cleanup(stubUserConfigDir(t, userDir)) got := resolveDataDir(t.TempDir(), t.TempDir(), "profiles") if want := filepath.Join(userDir, "qmk-rgb-tool", "profiles"); got != want { t.Errorf("resolveDataDir() = %q, want %q", got, want) } } // Both directories resolve the same way, or a user who installed the binary // globally finds definitions and not profiles. func TestProfilesAndDefinitionsUseTheSameOrder(t *testing.T) { userDir := t.TempDir() t.Cleanup(stubUserConfigDir(t, userDir)) t.Cleanup(definitionFlagRestore(t)) t.Cleanup(func() { profilesDirOverride = "" }) exeDir := t.TempDir() t.Cleanup(stubExecutableDir(t, exeDir)) t.Cleanup(stubWorkingDir(t, t.TempDir())) for _, name := range []string{"definitions", "profiles"} { if err := os.MkdirAll(filepath.Join(exeDir, name), 0o755); err != nil { t.Fatal(err) } } t.Cleanup(func() { for _, name := range []string{"definitions", "profiles"} { _ = os.RemoveAll(filepath.Join(exeDir, name)) } }) if got, want := definitionsPath(), filepath.Join(exeDir, "definitions"); got != want { t.Errorf("definitionsPath() = %q, want %q", got, want) } if got, want := profilesPath(), filepath.Join(exeDir, "profiles"); got != want { t.Errorf("profilesPath() = %q, want %q", got, want) } } // The user directory is reported so the commands can say where a file came from. func TestDataDirectoryIsReportedForTheUser(t *testing.T) { userDir := t.TempDir() t.Cleanup(stubUserConfigDir(t, userDir)) got := definitionsPath() if got == "" { t.Fatal("definitionsPath() = \"\", want a path") } if !filepath.IsAbs(got) { t.Errorf("definitionsPath() = %q, want an absolute path so it can be printed", got) } } // stubUserConfigDir points the platform's configuration directory at a temp one. func stubUserConfigDir(t *testing.T, dir string) func() { t.Helper() original := userConfigDir userConfigDir = func() (string, error) { return dir, nil } return func() { userConfigDir = original } } func stubExecutableDir(t *testing.T, dir string) func() { t.Helper() original := executableDir executableDir = func() string { return dir } return func() { executableDir = original } } func stubWorkingDir(t *testing.T, dir string) func() { t.Helper() original := workingDir workingDir = func() (string, error) { return dir, nil } return func() { workingDir = original } }