mirror of
https://github.com/caddyserver/caddy.git
synced 2025-11-11 00:56:56 -05:00
222 lines
5.3 KiB
Go
222 lines
5.3 KiB
Go
// Copyright 2015 Matthew Holt and The Caddy Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//go:build !windows
|
|
|
|
package caddy
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestFastAbs(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
checkFunc func(result string, err error) error
|
|
}{
|
|
{
|
|
name: "absolute path",
|
|
input: "/usr/local/bin",
|
|
checkFunc: func(result string, err error) error {
|
|
if err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
if result != "/usr/local/bin" {
|
|
t.Errorf("expected /usr/local/bin, got %s", result)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
name: "absolute path with dots",
|
|
input: "/usr/local/../bin",
|
|
checkFunc: func(result string, err error) error {
|
|
if err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
if result != "/usr/bin" {
|
|
t.Errorf("expected /usr/bin, got %s", result)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
name: "relative path",
|
|
input: "relative/path",
|
|
checkFunc: func(result string, err error) error {
|
|
if err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
if !filepath.IsAbs(result) {
|
|
t.Errorf("expected absolute path, got %s", result)
|
|
}
|
|
if !strings.HasSuffix(result, "relative/path") {
|
|
t.Errorf("expected path to end with 'relative/path', got %s", result)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
name: "dot",
|
|
input: ".",
|
|
checkFunc: func(result string, err error) error {
|
|
if err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
if !filepath.IsAbs(result) {
|
|
t.Errorf("expected absolute path, got %s", result)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
name: "dot dot",
|
|
input: "..",
|
|
checkFunc: func(result string, err error) error {
|
|
if err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
if !filepath.IsAbs(result) {
|
|
t.Errorf("expected absolute path, got %s", result)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
name: "empty string",
|
|
input: "",
|
|
checkFunc: func(result string, err error) error {
|
|
if err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
// Empty string should resolve to current directory
|
|
if !filepath.IsAbs(result) {
|
|
t.Errorf("expected absolute path, got %s", result)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
name: "complex relative path",
|
|
input: "./foo/../bar/./baz",
|
|
checkFunc: func(result string, err error) error {
|
|
if err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
if !filepath.IsAbs(result) {
|
|
t.Errorf("expected absolute path, got %s", result)
|
|
}
|
|
if !strings.HasSuffix(result, "bar/baz") {
|
|
t.Errorf("expected path to end with 'bar/baz', got %s", result)
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result, err := FastAbs(tt.input)
|
|
tt.checkFunc(result, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestFastAbsVsFilepathAbs compares FastAbs with filepath.Abs to ensure consistent behavior
|
|
func TestFastAbsVsFilepathAbs(t *testing.T) {
|
|
// Skip if working directory cannot be determined
|
|
if wderr != nil {
|
|
t.Skip("working directory error, skipping comparison test")
|
|
}
|
|
|
|
testPaths := []string{
|
|
".",
|
|
"..",
|
|
"foo",
|
|
"foo/bar",
|
|
"./foo",
|
|
"../foo",
|
|
"/absolute/path",
|
|
"/usr/local/bin",
|
|
}
|
|
|
|
for _, path := range testPaths {
|
|
t.Run(path, func(t *testing.T) {
|
|
fast, fastErr := FastAbs(path)
|
|
std, stdErr := filepath.Abs(path)
|
|
|
|
// Both should succeed or fail together
|
|
if (fastErr != nil) != (stdErr != nil) {
|
|
t.Errorf("error mismatch: FastAbs=%v, filepath.Abs=%v", fastErr, stdErr)
|
|
}
|
|
|
|
// If both succeed, results should be the same
|
|
if fastErr == nil && stdErr == nil && fast != std {
|
|
t.Errorf("result mismatch for %q: FastAbs=%s, filepath.Abs=%s", path, fast, std)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestFastAbsErrorHandling tests error handling when working directory is unavailable
|
|
func TestFastAbsErrorHandling(t *testing.T) {
|
|
// This tests the cached wderr behavior
|
|
if wderr != nil {
|
|
// Test that FastAbs properly returns the cached error for relative paths
|
|
_, err := FastAbs("relative/path")
|
|
if err == nil {
|
|
t.Error("expected error for relative path when working directory is unavailable")
|
|
}
|
|
if err != wderr {
|
|
t.Errorf("expected cached wderr, got different error: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkFastAbs benchmarks FastAbs
|
|
func BenchmarkFastAbs(b *testing.B) {
|
|
paths := []string{
|
|
"relative/path",
|
|
"/absolute/path",
|
|
".",
|
|
"..",
|
|
"./foo/bar",
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
FastAbs(paths[i%len(paths)])
|
|
}
|
|
}
|
|
|
|
// BenchmarkFastAbsVsStdLib compares performance of FastAbs vs filepath.Abs
|
|
func BenchmarkFastAbsVsStdLib(b *testing.B) {
|
|
path := "relative/path/to/file"
|
|
|
|
b.Run("FastAbs", func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
FastAbs(path)
|
|
}
|
|
})
|
|
|
|
b.Run("filepath.Abs", func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
filepath.Abs(path)
|
|
}
|
|
})
|
|
}
|