mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-02-01 22:47:40 +00:00
333 lines
8.2 KiB
Go
333 lines
8.2 KiB
Go
// Vikunja is a to-do list application to facilitate your life.
|
|
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package db
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"testing"
|
|
|
|
"code.vikunja.io/api/pkg/config"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestResolveDatabasePath(t *testing.T) {
|
|
// Save original config values
|
|
originalRootpath := config.ServiceRootpath.GetString()
|
|
defer config.ServiceRootpath.Set(originalRootpath)
|
|
|
|
t.Run("with explicitly configured rootpath", func(t *testing.T) {
|
|
// Set a rootpath that is different from the executable location
|
|
config.ServiceRootpath.Set("/custom/path")
|
|
|
|
result := resolveDatabasePath("vikunja.db")
|
|
expected := filepath.Join("/custom/path", "vikunja.db")
|
|
|
|
assert.Equal(t, expected, result)
|
|
})
|
|
|
|
t.Run("with default rootpath uses user data directory", func(t *testing.T) {
|
|
// Get the actual executable path and set rootpath to it
|
|
execPath, err := os.Executable()
|
|
require.NoError(t, err)
|
|
config.ServiceRootpath.Set(filepath.Dir(execPath))
|
|
|
|
result := resolveDatabasePath("vikunja.db")
|
|
|
|
// Result should contain the platform-specific user data directory
|
|
// and not be in the executable directory
|
|
assert.NotEqual(t, filepath.Join(filepath.Dir(execPath), "vikunja.db"), result)
|
|
assert.Contains(t, result, "vikunja.db")
|
|
|
|
// Verify it's using a platform-appropriate path
|
|
switch runtime.GOOS {
|
|
case "windows":
|
|
// Should be in %LOCALAPPDATA%\Vikunja or %USERPROFILE%\AppData\Local\Vikunja
|
|
assert.Contains(t, result, "Vikunja")
|
|
case "darwin":
|
|
// Should be in ~/Library/Application Support/Vikunja
|
|
assert.Contains(t, result, "Library")
|
|
assert.Contains(t, result, "Application Support")
|
|
default:
|
|
// Should be in ~/.local/share/vikunja or $XDG_DATA_HOME/vikunja
|
|
assert.NotEqual(t,
|
|
filepath.Dir(result),
|
|
filepath.Dir(execPath),
|
|
"Database should not be in executable directory",
|
|
)
|
|
}
|
|
})
|
|
|
|
t.Run("with subdirectory path", func(t *testing.T) {
|
|
config.ServiceRootpath.Set("/custom/path")
|
|
|
|
result := resolveDatabasePath("data/vikunja.db")
|
|
expected := filepath.Join("/custom/path", "data", "vikunja.db")
|
|
|
|
assert.Equal(t, expected, result)
|
|
})
|
|
}
|
|
|
|
func TestGetUserDataDir(t *testing.T) {
|
|
|
|
test := func() string {
|
|
dataDir, err := getUserDataDir()
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, dataDir)
|
|
|
|
// Verify the directory was created
|
|
info, err := os.Stat(dataDir)
|
|
require.NoError(t, err)
|
|
assert.True(t, info.IsDir())
|
|
|
|
return dataDir
|
|
}
|
|
|
|
// Verify platform-specific paths
|
|
switch runtime.GOOS {
|
|
case "windows":
|
|
dataDir := test()
|
|
assert.Contains(t, dataDir, "Vikunja")
|
|
case "darwin":
|
|
dataDir := test()
|
|
assert.Contains(t, dataDir, "Library")
|
|
assert.Contains(t, dataDir, "Application Support")
|
|
assert.Contains(t, dataDir, "Vikunja")
|
|
default:
|
|
originalXDGDataHome := os.Getenv("XDG_DATA_HOME")
|
|
defer func() {
|
|
if originalXDGDataHome != "" {
|
|
os.Setenv("XDG_DATA_HOME", originalXDGDataHome)
|
|
} else {
|
|
os.Unsetenv("XDG_DATA_HOME")
|
|
}
|
|
}()
|
|
|
|
t.Run("with XDG_DATA_HOME", func(t *testing.T) {
|
|
os.Setenv("XDG_DATA_HOME", "/tmp")
|
|
dataDir := test()
|
|
assert.Contains(t, dataDir, filepath.Join("/tmp", "vikunja"))
|
|
})
|
|
|
|
t.Run("without XDG_DATA_HOME", func(t *testing.T) {
|
|
os.Unsetenv("XDG_DATA_HOME")
|
|
dataDir := test()
|
|
assert.Contains(t, dataDir, "vikunja")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsSystemDirectory(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
expected bool
|
|
}{
|
|
// Windows system directories
|
|
{
|
|
name: "Windows System32",
|
|
path: "C:\\Windows\\System32\\vikunja.db",
|
|
expected: runtime.GOOS == "windows",
|
|
},
|
|
{
|
|
name: "Windows SysWOW64",
|
|
path: "C:\\Windows\\SysWOW64\\vikunja.db",
|
|
expected: runtime.GOOS == "windows",
|
|
},
|
|
{
|
|
name: "Windows root",
|
|
path: "C:\\Windows\\vikunja.db",
|
|
expected: runtime.GOOS == "windows",
|
|
},
|
|
{
|
|
name: "Windows System32 lowercase",
|
|
path: "c:\\windows\\system32\\vikunja.db",
|
|
expected: runtime.GOOS == "windows",
|
|
},
|
|
// Unix-like system directories
|
|
{
|
|
name: "/bin",
|
|
path: "/bin/vikunja.db",
|
|
expected: runtime.GOOS != "windows",
|
|
},
|
|
{
|
|
name: "/sbin",
|
|
path: "/sbin/vikunja.db",
|
|
expected: runtime.GOOS != "windows",
|
|
},
|
|
{
|
|
name: "/usr/bin",
|
|
path: "/usr/bin/vikunja.db",
|
|
expected: runtime.GOOS != "windows",
|
|
},
|
|
{
|
|
name: "/etc",
|
|
path: "/etc/vikunja.db",
|
|
expected: runtime.GOOS != "windows",
|
|
},
|
|
// Non-system directories
|
|
{
|
|
name: "user home directory (Unix)",
|
|
path: "/home/user/vikunja.db",
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "user profile directory (Windows)",
|
|
path: "C:\\Users\\user\\vikunja.db",
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "custom directory",
|
|
path: "/opt/vikunja/vikunja.db",
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "relative path",
|
|
path: "./vikunja.db",
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := isSystemDirectory(tt.path)
|
|
assert.Equal(t, tt.expected, result,
|
|
"Expected isSystemDirectory(%s) to be %v on %s",
|
|
tt.path, tt.expected, runtime.GOOS)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsSystemDirectory_EdgeCases(t *testing.T) {
|
|
if runtime.GOOS == "windows" {
|
|
t.Run("false positives - paths containing 'windows' but not system directories", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
}{
|
|
{
|
|
name: "custom app with windows in path",
|
|
path: "C:\\myapp\\windows\\data\\vikunja.db",
|
|
},
|
|
{
|
|
name: "windows directory on non-C drive",
|
|
path: "D:\\windows\\vikunja.db",
|
|
},
|
|
{
|
|
name: "user directory named windows",
|
|
path: "C:\\Users\\windows\\vikunja.db",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert.False(t, isSystemDirectory(tt.path))
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("safe Windows subdirectories", func(t *testing.T) {
|
|
assert.False(t, isSystemDirectory("C:\\Windows\\Temp\\vikunja.db"))
|
|
})
|
|
|
|
t.Run("actual Windows system directories", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
}{
|
|
{
|
|
name: "Windows root",
|
|
path: "C:\\Windows\\vikunja.db",
|
|
},
|
|
{
|
|
name: "Windows root lowercase",
|
|
path: "c:\\windows\\vikunja.db",
|
|
},
|
|
{
|
|
name: "System32",
|
|
path: "C:\\Windows\\System32\\vikunja.db",
|
|
},
|
|
{
|
|
name: "System32 uppercase",
|
|
path: "C:\\WINDOWS\\SYSTEM32\\vikunja.db",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert.True(t, isSystemDirectory(tt.path))
|
|
})
|
|
}
|
|
})
|
|
} else {
|
|
t.Run("false positives - paths containing system dir names", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
}{
|
|
{
|
|
name: "/home/bin not same as /bin",
|
|
path: "/home/bin/vikunja.db",
|
|
},
|
|
{
|
|
name: "/opt/sbin not same as /sbin",
|
|
path: "/opt/sbin/vikunja.db",
|
|
},
|
|
{
|
|
name: "/usr/local/bin is safe",
|
|
path: "/usr/local/bin/vikunja.db",
|
|
},
|
|
{
|
|
name: "/binaries not same as /bin",
|
|
path: "/binaries/vikunja.db",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert.False(t, isSystemDirectory(tt.path))
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("actual Unix system directories", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
}{
|
|
{
|
|
name: "/bin",
|
|
path: "/bin/vikunja.db",
|
|
},
|
|
{
|
|
name: "/etc",
|
|
path: "/etc/vikunja.db",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert.True(t, isSystemDirectory(tt.path))
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|