mirror of
https://github.com/ivuorinen/gibidify.git
synced 2026-02-13 05:49:16 +00:00
feat: many features, check TODO.md
This commit is contained in:
262
utils/paths_test.go
Normal file
262
utils/paths_test.go
Normal file
@@ -0,0 +1,262 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetAbsolutePath(t *testing.T) {
|
||||
// Get current working directory for tests
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get current directory: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
wantPrefix string
|
||||
wantErr bool
|
||||
wantErrMsg string
|
||||
skipWindows bool
|
||||
}{
|
||||
{
|
||||
name: "absolute path unchanged",
|
||||
path: cwd,
|
||||
wantPrefix: cwd,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "relative path current directory",
|
||||
path: ".",
|
||||
wantPrefix: cwd,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "relative path parent directory",
|
||||
path: "..",
|
||||
wantPrefix: filepath.Dir(cwd),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "relative path with file",
|
||||
path: "test.txt",
|
||||
wantPrefix: filepath.Join(cwd, "test.txt"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "relative path with subdirectory",
|
||||
path: "subdir/file.go",
|
||||
wantPrefix: filepath.Join(cwd, "subdir", "file.go"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "empty path",
|
||||
path: "",
|
||||
wantPrefix: cwd,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "path with tilde",
|
||||
path: "~/test",
|
||||
wantPrefix: filepath.Join(cwd, "~", "test"),
|
||||
wantErr: false,
|
||||
skipWindows: false,
|
||||
},
|
||||
{
|
||||
name: "path with multiple separators",
|
||||
path: "path//to///file",
|
||||
wantPrefix: filepath.Join(cwd, "path", "to", "file"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "path with trailing separator",
|
||||
path: "path/",
|
||||
wantPrefix: filepath.Join(cwd, "path"),
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.skipWindows && runtime.GOOS == "windows" {
|
||||
t.Skip("Skipping test on Windows")
|
||||
}
|
||||
|
||||
got, err := GetAbsolutePath(tt.path)
|
||||
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("GetAbsolutePath() error = nil, wantErr %v", tt.wantErr)
|
||||
return
|
||||
}
|
||||
if tt.wantErrMsg != "" && !strings.Contains(err.Error(), tt.wantErrMsg) {
|
||||
t.Errorf("GetAbsolutePath() error = %v, want error containing %v", err, tt.wantErrMsg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("GetAbsolutePath() unexpected error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Clean the expected path for comparison
|
||||
wantClean := filepath.Clean(tt.wantPrefix)
|
||||
gotClean := filepath.Clean(got)
|
||||
|
||||
if gotClean != wantClean {
|
||||
t.Errorf("GetAbsolutePath() = %v, want %v", gotClean, wantClean)
|
||||
}
|
||||
|
||||
// Verify the result is actually absolute
|
||||
if !filepath.IsAbs(got) {
|
||||
t.Errorf("GetAbsolutePath() returned non-absolute path: %v", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAbsolutePathSpecialCases(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("Skipping Unix-specific tests on Windows")
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
setup func() (string, func())
|
||||
path string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "symlink to directory",
|
||||
setup: func() (string, func()) {
|
||||
tmpDir := t.TempDir()
|
||||
target := filepath.Join(tmpDir, "target")
|
||||
link := filepath.Join(tmpDir, "link")
|
||||
|
||||
if err := os.Mkdir(target, 0o755); err != nil {
|
||||
t.Fatalf("Failed to create target directory: %v", err)
|
||||
}
|
||||
if err := os.Symlink(target, link); err != nil {
|
||||
t.Fatalf("Failed to create symlink: %v", err)
|
||||
}
|
||||
|
||||
return link, func() {}
|
||||
},
|
||||
path: "",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "broken symlink",
|
||||
setup: func() (string, func()) {
|
||||
tmpDir := t.TempDir()
|
||||
link := filepath.Join(tmpDir, "broken_link")
|
||||
|
||||
if err := os.Symlink("/nonexistent/path", link); err != nil {
|
||||
t.Fatalf("Failed to create broken symlink: %v", err)
|
||||
}
|
||||
|
||||
return link, func() {}
|
||||
},
|
||||
path: "",
|
||||
wantErr: false, // filepath.Abs still works with broken symlinks
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
path, cleanup := tt.setup()
|
||||
defer cleanup()
|
||||
|
||||
if tt.path == "" {
|
||||
tt.path = path
|
||||
}
|
||||
|
||||
got, err := GetAbsolutePath(tt.path)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetAbsolutePath() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if err == nil && !filepath.IsAbs(got) {
|
||||
t.Errorf("GetAbsolutePath() returned non-absolute path: %v", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAbsolutePathConcurrency(t *testing.T) {
|
||||
// Test that GetAbsolutePath is safe for concurrent use
|
||||
paths := []string{".", "..", "test.go", "subdir/file.txt", "/tmp/test"}
|
||||
done := make(chan bool)
|
||||
|
||||
for _, p := range paths {
|
||||
go func(path string) {
|
||||
_, _ = GetAbsolutePath(path)
|
||||
done <- true
|
||||
}(p)
|
||||
}
|
||||
|
||||
// Wait for all goroutines to complete
|
||||
for range paths {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAbsolutePathErrorFormatting(t *testing.T) {
|
||||
// This test verifies error message formatting
|
||||
// We need to trigger an actual error from filepath.Abs
|
||||
// On Unix systems, we can't easily trigger filepath.Abs errors
|
||||
// so we'll just verify the error wrapping works correctly
|
||||
|
||||
// Create a test that would fail if filepath.Abs returns an error
|
||||
path := "test/path"
|
||||
got, err := GetAbsolutePath(path)
|
||||
if err != nil {
|
||||
// If we somehow get an error, verify it's properly formatted
|
||||
if !strings.Contains(err.Error(), "failed to get absolute path for") {
|
||||
t.Errorf("Error message format incorrect: %v", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), path) {
|
||||
t.Errorf("Error message should contain original path: %v", err)
|
||||
}
|
||||
} else {
|
||||
// Normal case - just verify we got a valid absolute path
|
||||
if !filepath.IsAbs(got) {
|
||||
t.Errorf("Expected absolute path, got: %v", got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkGetAbsolutePath benchmarks the GetAbsolutePath function
|
||||
func BenchmarkGetAbsolutePath(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = GetAbsolutePath("test/path/file.go")
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkGetAbsolutePathAbs benchmarks with already absolute path
|
||||
func BenchmarkGetAbsolutePathAbs(b *testing.B) {
|
||||
absPath := "/home/user/test/file.go"
|
||||
if runtime.GOOS == "windows" {
|
||||
absPath = "C:\\Users\\test\\file.go"
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = GetAbsolutePath(absPath)
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkGetAbsolutePathCurrent benchmarks with current directory
|
||||
func BenchmarkGetAbsolutePathCurrent(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = GetAbsolutePath(".")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user