mirror of
https://github.com/ivuorinen/gibidify.git
synced 2026-01-26 03:24:05 +00:00
263 lines
6.2 KiB
Go
263 lines
6.2 KiB
Go
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(".")
|
|
}
|
|
}
|