5d6b8141ec
As of Go 1.16, the same functionality is now provided by package io or package os, and those implementations should be preferred in new code.
244 lines
5.2 KiB
Go
244 lines
5.2 KiB
Go
package configfile
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/rclone/rclone/fs/config"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var configData = `[one]
|
|
type = number1
|
|
fruit = potato
|
|
|
|
[two]
|
|
type = number2
|
|
fruit = apple
|
|
topping = nuts
|
|
|
|
[three]
|
|
type = number3
|
|
fruit = banana
|
|
|
|
`
|
|
|
|
// Fill up a temporary config file with the testdata filename passed in
|
|
func setConfigFile(t *testing.T, data string) func() {
|
|
out, err := os.CreateTemp("", "rclone-configfile-test")
|
|
require.NoError(t, err)
|
|
filePath := out.Name()
|
|
|
|
_, err = out.Write([]byte(data))
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, out.Close())
|
|
|
|
old := config.GetConfigPath()
|
|
assert.NoError(t, config.SetConfigPath(filePath))
|
|
return func() {
|
|
assert.NoError(t, config.SetConfigPath(old))
|
|
_ = os.Remove(filePath)
|
|
}
|
|
}
|
|
|
|
// toUnix converts \r\n to \n in buf
|
|
func toUnix(buf string) string {
|
|
if runtime.GOOS == "windows" {
|
|
return strings.ReplaceAll(buf, "\r\n", "\n")
|
|
}
|
|
return buf
|
|
}
|
|
|
|
func TestConfigFile(t *testing.T) {
|
|
defer setConfigFile(t, configData)()
|
|
data := &Storage{}
|
|
|
|
require.NoError(t, data.Load())
|
|
|
|
t.Run("Read", func(t *testing.T) {
|
|
t.Run("Serialize", func(t *testing.T) {
|
|
buf, err := data.Serialize()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, configData, toUnix(buf))
|
|
})
|
|
t.Run("HasSection", func(t *testing.T) {
|
|
assert.True(t, data.HasSection("one"))
|
|
assert.False(t, data.HasSection("missing"))
|
|
})
|
|
t.Run("GetSectionList", func(t *testing.T) {
|
|
assert.Equal(t, []string{
|
|
"one",
|
|
"two",
|
|
"three",
|
|
}, data.GetSectionList())
|
|
})
|
|
t.Run("GetKeyList", func(t *testing.T) {
|
|
assert.Equal(t, []string{
|
|
"type",
|
|
"fruit",
|
|
"topping",
|
|
}, data.GetKeyList("two"))
|
|
assert.Equal(t, []string(nil), data.GetKeyList("unicorn"))
|
|
})
|
|
t.Run("GetValue", func(t *testing.T) {
|
|
value, ok := data.GetValue("one", "type")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "number1", value)
|
|
value, ok = data.GetValue("three", "fruit")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "banana", value)
|
|
value, ok = data.GetValue("one", "typeX")
|
|
assert.False(t, ok)
|
|
assert.Equal(t, "", value)
|
|
value, ok = data.GetValue("threeX", "fruit")
|
|
assert.False(t, ok)
|
|
assert.Equal(t, "", value)
|
|
})
|
|
})
|
|
|
|
//defer setConfigFile(configData)()
|
|
|
|
t.Run("Write", func(t *testing.T) {
|
|
t.Run("SetValue", func(t *testing.T) {
|
|
data.SetValue("one", "extra", "42")
|
|
data.SetValue("two", "fruit", "acorn")
|
|
|
|
buf, err := data.Serialize()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, `[one]
|
|
type = number1
|
|
fruit = potato
|
|
extra = 42
|
|
|
|
[two]
|
|
type = number2
|
|
fruit = acorn
|
|
topping = nuts
|
|
|
|
[three]
|
|
type = number3
|
|
fruit = banana
|
|
|
|
`, toUnix(buf))
|
|
t.Run("DeleteKey", func(t *testing.T) {
|
|
data.DeleteKey("one", "type")
|
|
data.DeleteKey("two", "missing")
|
|
data.DeleteKey("three", "fruit")
|
|
buf, err := data.Serialize()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, `[one]
|
|
fruit = potato
|
|
extra = 42
|
|
|
|
[two]
|
|
type = number2
|
|
fruit = acorn
|
|
topping = nuts
|
|
|
|
[three]
|
|
type = number3
|
|
|
|
`, toUnix(buf))
|
|
t.Run("DeleteSection", func(t *testing.T) {
|
|
data.DeleteSection("two")
|
|
data.DeleteSection("missing")
|
|
buf, err := data.Serialize()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, `[one]
|
|
fruit = potato
|
|
extra = 42
|
|
|
|
[three]
|
|
type = number3
|
|
|
|
`, toUnix(buf))
|
|
t.Run("Save", func(t *testing.T) {
|
|
require.NoError(t, data.Save())
|
|
buf, err := os.ReadFile(config.GetConfigPath())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, `[one]
|
|
fruit = potato
|
|
extra = 42
|
|
|
|
[three]
|
|
type = number3
|
|
|
|
`, toUnix(string(buf)))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestConfigFileReload(t *testing.T) {
|
|
defer setConfigFile(t, configData)()
|
|
data := &Storage{}
|
|
|
|
require.NoError(t, data.Load())
|
|
|
|
value, ok := data.GetValue("three", "appended")
|
|
assert.False(t, ok)
|
|
assert.Equal(t, "", value)
|
|
|
|
// Now write a new value on the end
|
|
out, err := os.OpenFile(config.GetConfigPath(), os.O_APPEND|os.O_WRONLY, 0777)
|
|
require.NoError(t, err)
|
|
fmt.Fprintln(out, "appended = what magic")
|
|
require.NoError(t, out.Close())
|
|
|
|
// And check we magically reloaded it
|
|
value, ok = data.GetValue("three", "appended")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "what magic", value)
|
|
}
|
|
|
|
func TestConfigFileDoesNotExist(t *testing.T) {
|
|
defer setConfigFile(t, configData)()
|
|
data := &Storage{}
|
|
|
|
require.NoError(t, os.Remove(config.GetConfigPath()))
|
|
|
|
err := data.Load()
|
|
require.Equal(t, config.ErrorConfigFileNotFound, err)
|
|
|
|
// check that using data doesn't crash
|
|
value, ok := data.GetValue("three", "appended")
|
|
assert.False(t, ok)
|
|
assert.Equal(t, "", value)
|
|
}
|
|
|
|
func testConfigFileNoConfig(t *testing.T, configPath string) {
|
|
assert.NoError(t, config.SetConfigPath(configPath))
|
|
data := &Storage{}
|
|
|
|
err := data.Load()
|
|
require.Equal(t, config.ErrorConfigFileNotFound, err)
|
|
|
|
data.SetValue("one", "extra", "42")
|
|
value, ok := data.GetValue("one", "extra")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "42", value)
|
|
|
|
err = data.Save()
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestConfigFileNoConfig(t *testing.T) {
|
|
old := config.GetConfigPath()
|
|
defer func() {
|
|
assert.NoError(t, config.SetConfigPath(old))
|
|
}()
|
|
|
|
t.Run("Empty", func(t *testing.T) {
|
|
testConfigFileNoConfig(t, "")
|
|
})
|
|
t.Run("NotFound", func(t *testing.T) {
|
|
testConfigFileNoConfig(t, "/notfound")
|
|
})
|
|
}
|