1
0
mirror of https://github.com/Jguer/yay.git synced 2026-02-20 15:21:18 +01:00
yay/pkg/settings/ini_test.go
Jo 3e3d5aa111
feat(ini): support ini config (#2774)
* support ini config

* support user ini config

* Update pkg/settings/ini.go

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-30 16:07:24 +01:00

363 lines
9.3 KiB
Go

package settings
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestConfigurationLoadINI(t *testing.T) {
t.Parallel()
t.Run("load nonexistent file returns nil", func(t *testing.T) {
t.Parallel()
cfg := DefaultConfig("test")
err := cfg.loadINI("/nonexistent/path/yay.conf")
assert.NoError(t, err)
})
t.Run("load valid INI file", func(t *testing.T) {
t.Parallel()
content := `# System-wide yay configuration
[options]
AurUrl = https://custom.aur.org
BuildDir = /var/cache/yay
Editor = vim
Devel = true
SudoLoop = yes
RequestSplitN = 200
BottomUp = false
; This is also a comment
CleanAfter = 1
`
tmpDir := t.TempDir()
iniPath := filepath.Join(tmpDir, "yay.conf")
require.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))
cfg := DefaultConfig("test")
err := cfg.loadINI(iniPath)
require.NoError(t, err)
assert.Equal(t, "https://custom.aur.org", cfg.AURURL)
assert.Equal(t, "/var/cache/yay", cfg.BuildDir)
assert.Equal(t, "vim", cfg.Editor)
assert.True(t, cfg.Devel)
assert.True(t, cfg.SudoLoop)
assert.Equal(t, 200, cfg.RequestSplitN)
assert.False(t, cfg.BottomUp)
assert.True(t, cfg.CleanAfter)
})
t.Run("load INI file with all option types", func(t *testing.T) {
t.Parallel()
content := `
# String options
AurUrl = https://aur.example.com
AurRpcUrl = https://aur.example.com/rpc
BuildDir = /tmp/build
Editor = nvim
EditorFlags = -p
MakepkgBin = /usr/bin/makepkg
MakepkgConf = /etc/makepkg.conf
PacmanBin = /usr/bin/pacman
PacmanConf = /etc/pacman.conf
GitBin = /usr/bin/git
GpgBin = /usr/bin/gpg
GpgFlags = --keyserver-options
MFlags = -s
SortBy = votes
SearchBy = name
GitFlags = --depth=1
RemoveMake = yes
SudoBin = doas
SudoFlags = -n
ReDownload = all
AnswerClean = All
AnswerDiff = None
AnswerEdit = None
AnswerUpgrade = None
ReBuild = all
# Integer options
RequestSplitN = 100
CompletionInterval = 3
MaxConcurrentDownloads = 4
# Boolean options
BottomUp = true
SudoLoop = false
TimeUpdate = yes
Devel = no
CleanAfter = true
KeepSrc = false
Provides = true
PgpFetch = false
CleanMenu = yes
DiffMenu = no
EditMenu = true
CombinedUpgrade = false
UseAsk = true
BatchInstall = false
SingleLineResults = true
SeparateSources = false
Debug = no
Rpc = yes
DoubleConfirm = false
`
tmpDir := t.TempDir()
iniPath := filepath.Join(tmpDir, "yay.conf")
require.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))
cfg := DefaultConfig("test")
err := cfg.loadINI(iniPath)
require.NoError(t, err)
// String options
assert.Equal(t, "https://aur.example.com", cfg.AURURL)
assert.Equal(t, "https://aur.example.com/rpc", cfg.AURRPCURL)
assert.Equal(t, "/tmp/build", cfg.BuildDir)
assert.Equal(t, "nvim", cfg.Editor)
assert.Equal(t, "-p", cfg.EditorFlags)
assert.Equal(t, "/usr/bin/makepkg", cfg.MakepkgBin)
assert.Equal(t, "/etc/makepkg.conf", cfg.MakepkgConf)
assert.Equal(t, "/usr/bin/pacman", cfg.PacmanBin)
assert.Equal(t, "/etc/pacman.conf", cfg.PacmanConf)
assert.Equal(t, "/usr/bin/git", cfg.GitBin)
assert.Equal(t, "/usr/bin/gpg", cfg.GpgBin)
assert.Equal(t, "--keyserver-options", cfg.GpgFlags)
assert.Equal(t, "-s", cfg.MFlags)
assert.Equal(t, "votes", cfg.SortBy)
assert.Equal(t, "name", cfg.SearchBy)
assert.Equal(t, "--depth=1", cfg.GitFlags)
assert.Equal(t, "yes", cfg.RemoveMake)
assert.Equal(t, "doas", cfg.SudoBin)
assert.Equal(t, "-n", cfg.SudoFlags)
assert.Equal(t, "all", cfg.ReDownload)
assert.Equal(t, "All", cfg.AnswerClean)
assert.Equal(t, "None", cfg.AnswerDiff)
assert.Equal(t, "None", cfg.AnswerEdit)
assert.Equal(t, "None", cfg.AnswerUpgrade)
assert.Equal(t, "all", string(cfg.ReBuild))
// Integer options
assert.Equal(t, 100, cfg.RequestSplitN)
assert.Equal(t, 3, cfg.CompletionInterval)
assert.Equal(t, 4, cfg.MaxConcurrentDownloads)
// Boolean options
assert.True(t, cfg.BottomUp)
assert.False(t, cfg.SudoLoop)
assert.True(t, cfg.TimeUpdate)
assert.False(t, cfg.Devel)
assert.True(t, cfg.CleanAfter)
assert.False(t, cfg.KeepSrc)
assert.True(t, cfg.Provides)
assert.False(t, cfg.PGPFetch)
assert.True(t, cfg.CleanMenu)
assert.False(t, cfg.DiffMenu)
assert.True(t, cfg.EditMenu)
assert.False(t, cfg.CombinedUpgrade)
assert.True(t, cfg.UseAsk)
assert.False(t, cfg.BatchInstall)
assert.True(t, cfg.SingleLineResults)
assert.False(t, cfg.SeparateSources)
assert.False(t, cfg.Debug)
assert.True(t, cfg.UseRPC)
assert.False(t, cfg.DoubleConfirm)
})
t.Run("load INI without section header", func(t *testing.T) {
t.Parallel()
content := `# Config without section header
AurUrl = https://custom.aur.org
Devel = true
RequestSplitN = 250
`
tmpDir := t.TempDir()
iniPath := filepath.Join(tmpDir, "yay.conf")
require.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))
cfg := DefaultConfig("test")
err := cfg.loadINI(iniPath)
require.NoError(t, err)
assert.Equal(t, "https://custom.aur.org", cfg.AURURL)
assert.True(t, cfg.Devel)
assert.Equal(t, 250, cfg.RequestSplitN)
})
t.Run("load INI with boolean keys (no value)", func(t *testing.T) {
t.Parallel()
content := `# Boolean keys without values are treated as true
Devel
SudoLoop
CleanAfter
`
tmpDir := t.TempDir()
iniPath := filepath.Join(tmpDir, "yay.conf")
require.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))
cfg := DefaultConfig("test")
cfg.Devel = false
cfg.SudoLoop = false
cfg.CleanAfter = false
err := cfg.loadINI(iniPath)
require.NoError(t, err)
assert.True(t, cfg.Devel)
assert.True(t, cfg.SudoLoop)
assert.True(t, cfg.CleanAfter)
})
t.Run("unknown options are ignored", func(t *testing.T) {
t.Parallel()
content := `AurUrl = https://custom.aur.org
unknownoption = somevalue
anotherunknown = 123
`
tmpDir := t.TempDir()
iniPath := filepath.Join(tmpDir, "yay.conf")
require.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))
cfg := DefaultConfig("test")
err := cfg.loadINI(iniPath)
require.NoError(t, err)
assert.Equal(t, "https://custom.aur.org", cfg.AURURL)
})
}
func TestSystemConfigPath(t *testing.T) {
t.Parallel()
assert.Equal(t, "/etc/yay.conf", SystemConfigPath)
}
func TestConfigurationSaveINI(t *testing.T) {
t.Parallel()
t.Run("save and reload config", func(t *testing.T) {
t.Parallel()
cfg := DefaultConfig("test")
cfg.AURURL = "https://custom.aur.org"
cfg.BuildDir = "/custom/build"
cfg.Editor = "nvim"
cfg.Devel = true
cfg.SudoLoop = true
cfg.RequestSplitN = 150
cfg.BottomUp = true
cfg.CleanAfter = false
tmpDir := t.TempDir()
iniPath := filepath.Join(tmpDir, "yay.conf")
err := cfg.SaveINI(iniPath)
require.NoError(t, err)
// Verify file was created
_, err = os.Stat(iniPath)
require.NoError(t, err)
// Load into new config and verify values
cfg2 := DefaultConfig("test")
err = cfg2.loadINI(iniPath)
require.NoError(t, err)
assert.Equal(t, "https://custom.aur.org", cfg2.AURURL)
assert.Equal(t, "/custom/build", cfg2.BuildDir)
assert.Equal(t, "nvim", cfg2.Editor)
assert.True(t, cfg2.Devel)
assert.True(t, cfg2.SudoLoop)
assert.Equal(t, 150, cfg2.RequestSplitN)
assert.True(t, cfg2.BottomUp)
assert.False(t, cfg2.CleanAfter)
})
t.Run("save creates directory if not exists", func(t *testing.T) {
t.Parallel()
cfg := DefaultConfig("test")
cfg.AURURL = "https://test.aur.org"
tmpDir := t.TempDir()
nestedPath := filepath.Join(tmpDir, "nested", "dir", "yay.conf")
err := cfg.SaveINI(nestedPath)
require.NoError(t, err)
// Verify file was created
_, err = os.Stat(nestedPath)
require.NoError(t, err)
})
t.Run("roundtrip preserves all field types", func(t *testing.T) {
t.Parallel()
cfg := DefaultConfig("test")
// String fields
cfg.AURURL = "https://roundtrip.aur.org"
cfg.AURRPCURL = "https://roundtrip.aur.org/rpc"
cfg.BuildDir = "/roundtrip/build"
cfg.Editor = "emacs"
cfg.EditorFlags = "-nw"
cfg.SudoBin = "doas"
cfg.SudoFlags = "-n"
cfg.ReDownload = "all"
cfg.ReBuild = "tree"
// Integer fields
cfg.RequestSplitN = 75
cfg.CompletionInterval = 5
cfg.MaxConcurrentDownloads = 8
// Boolean fields
cfg.BottomUp = true
cfg.SudoLoop = false
cfg.Devel = true
cfg.CleanAfter = false
cfg.UseRPC = true
cfg.BatchInstall = true
tmpDir := t.TempDir()
iniPath := filepath.Join(tmpDir, "yay.conf")
err := cfg.SaveINI(iniPath)
require.NoError(t, err)
cfg2 := DefaultConfig("test")
err = cfg2.loadINI(iniPath)
require.NoError(t, err)
// Verify all fields
assert.Equal(t, cfg.AURURL, cfg2.AURURL)
assert.Equal(t, cfg.AURRPCURL, cfg2.AURRPCURL)
assert.Equal(t, cfg.BuildDir, cfg2.BuildDir)
assert.Equal(t, cfg.Editor, cfg2.Editor)
assert.Equal(t, cfg.EditorFlags, cfg2.EditorFlags)
assert.Equal(t, cfg.SudoBin, cfg2.SudoBin)
assert.Equal(t, cfg.SudoFlags, cfg2.SudoFlags)
assert.Equal(t, cfg.ReDownload, cfg2.ReDownload)
assert.Equal(t, cfg.ReBuild, cfg2.ReBuild)
assert.Equal(t, cfg.RequestSplitN, cfg2.RequestSplitN)
assert.Equal(t, cfg.CompletionInterval, cfg2.CompletionInterval)
assert.Equal(t, cfg.MaxConcurrentDownloads, cfg2.MaxConcurrentDownloads)
assert.Equal(t, cfg.BottomUp, cfg2.BottomUp)
assert.Equal(t, cfg.SudoLoop, cfg2.SudoLoop)
assert.Equal(t, cfg.Devel, cfg2.Devel)
assert.Equal(t, cfg.CleanAfter, cfg2.CleanAfter)
assert.Equal(t, cfg.UseRPC, cfg2.UseRPC)
assert.Equal(t, cfg.BatchInstall, cfg2.BatchInstall)
})
}