2023-12-01 23:47:00 +00:00
|
|
|
package files
|
2023-09-30 14:18:21 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"math/rand"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
"time"
|
2023-12-01 23:47:00 +00:00
|
|
|
|
2024-12-17 00:01:55 +00:00
|
|
|
"github.com/gtsteffaniak/filebrowser/backend/settings"
|
2023-09-30 14:18:21 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func BenchmarkFillIndex(b *testing.B) {
|
2025-01-05 19:05:33 +00:00
|
|
|
Initialize(settings.Source{
|
|
|
|
Name: "test",
|
|
|
|
Path: "/srv",
|
|
|
|
})
|
|
|
|
idx := GetIndex("test")
|
2023-09-30 14:18:21 +00:00
|
|
|
b.ResetTimer()
|
|
|
|
b.ReportAllocs()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2025-01-05 19:05:33 +00:00
|
|
|
idx.createMockData(50, 3) // 1000 dirs, 3 files per dir
|
2023-09-30 14:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-05 19:05:33 +00:00
|
|
|
func (idx *Index) createMockData(numDirs, numFilesPerDir int) {
|
2023-09-30 14:18:21 +00:00
|
|
|
for i := 0; i < numDirs; i++ {
|
2024-11-21 00:15:30 +00:00
|
|
|
dirPath := generateRandomPath(rand.Intn(3) + 1)
|
2024-11-26 17:21:41 +00:00
|
|
|
files := []ItemInfo{} // Slice of FileInfo
|
2024-10-07 22:44:53 +00:00
|
|
|
|
|
|
|
// Simulating files and directories with FileInfo
|
2023-09-30 14:18:21 +00:00
|
|
|
for j := 0; j < numFilesPerDir; j++ {
|
2024-11-26 17:21:41 +00:00
|
|
|
newFile := ItemInfo{
|
2024-10-07 22:44:53 +00:00
|
|
|
Name: "file-" + getRandomTerm() + getRandomExtension(),
|
|
|
|
Size: rand.Int63n(1000), // Random size
|
|
|
|
ModTime: time.Now().Add(-time.Duration(rand.Intn(100)) * time.Hour), // Random mod time
|
2024-11-21 00:15:30 +00:00
|
|
|
Type: "blob",
|
2023-12-01 23:47:00 +00:00
|
|
|
}
|
|
|
|
files = append(files, newFile)
|
2023-09-30 14:18:21 +00:00
|
|
|
}
|
2024-11-21 00:15:30 +00:00
|
|
|
dirInfo := &FileInfo{
|
|
|
|
Path: dirPath,
|
|
|
|
Files: files,
|
2024-10-07 22:44:53 +00:00
|
|
|
}
|
2024-11-21 00:15:30 +00:00
|
|
|
|
2025-01-05 19:05:33 +00:00
|
|
|
idx.UpdateMetadata(dirInfo)
|
2023-09-30 14:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// JSONBytesEqual compares the JSON in two byte slices.
|
|
|
|
func JSONBytesEqual(a, b []byte) (bool, error) {
|
|
|
|
var j, j2 interface{}
|
|
|
|
if err := json.Unmarshal(a, &j); err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
if err := json.Unmarshal(b, &j2); err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
return reflect.DeepEqual(j2, j), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetIndex(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
want *map[string][]string
|
|
|
|
}{
|
|
|
|
// TODO: Add test cases.
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2023-12-01 23:47:00 +00:00
|
|
|
if got := GetIndex("root"); !reflect.DeepEqual(got, tt.want) {
|
2023-09-30 14:18:21 +00:00
|
|
|
t.Errorf("GetIndex() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-11-27 13:30:03 +00:00
|
|
|
|
|
|
|
func TestMakeIndexPath(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
subPath string
|
|
|
|
expected string
|
|
|
|
}{
|
2025-01-05 19:05:33 +00:00
|
|
|
// Linux
|
2024-11-27 13:30:03 +00:00
|
|
|
{"Root path returns slash", "/", "/"},
|
|
|
|
{"Dot-prefixed returns slash", ".", "/"},
|
|
|
|
{"Double-dot prefix ignored", "./", "/"},
|
|
|
|
{"Dot prefix followed by text", "./test", "/test"},
|
|
|
|
{"Dot prefix followed by text", ".test", "/.test"},
|
|
|
|
{"Hidden file at root", "/.test", "/.test"},
|
|
|
|
{"Trailing slash removed", "/test/", "/test"},
|
|
|
|
{"Subpath without root prefix", "/other/test", "/other/test"},
|
|
|
|
{"Complex nested paths", "/nested/path", "/nested/path"},
|
2025-01-13 00:50:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
idx := &Index{Source: settings.Source{Path: "/"}}
|
|
|
|
result := idx.makeIndexPath(tt.subPath)
|
|
|
|
if result != tt.expected {
|
|
|
|
t.Errorf("makeIndexPath(%q)\ngot %q\nwant %q", tt.name, result, tt.expected)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
tests = []struct {
|
|
|
|
name string
|
|
|
|
subPath string
|
|
|
|
expected string
|
|
|
|
}{
|
2025-01-05 19:05:33 +00:00
|
|
|
// Windows
|
|
|
|
{"Mixed slash", "/first\\second", "/first/second"},
|
|
|
|
{"Windows slash", "\\first\\second", "/first/second"},
|
2025-01-13 00:50:22 +00:00
|
|
|
{"Windows full path", "C:\\Users\\testfolder\\nestedfolder", "/testfolder/nestedfolder"},
|
2024-11-27 13:30:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2025-01-13 00:50:22 +00:00
|
|
|
idx := &Index{Source: settings.Source{Path: "C:\\Users"}}
|
2025-01-05 19:05:33 +00:00
|
|
|
result := idx.makeIndexPath(tt.subPath)
|
2024-11-27 13:30:03 +00:00
|
|
|
if result != tt.expected {
|
2025-01-05 19:05:33 +00:00
|
|
|
t.Errorf("makeIndexPath(%q)\ngot %q\nwant %q", tt.name, result, tt.expected)
|
2024-11-27 13:30:03 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2025-01-05 19:05:33 +00:00
|
|
|
|
|
|
|
func TestMakeIndexPathRoot(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
subPath string
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
// Linux
|
|
|
|
{"Root path returns slash", "/rootpath", "/"},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
idx := &Index{Source: settings.Source{Path: "/rootpath", Name: "default"}}
|
|
|
|
result := idx.makeIndexPath(tt.subPath)
|
|
|
|
if result != tt.expected {
|
|
|
|
t.Errorf("makeIndexPath(%q)\ngot %q\nwant %q", tt.name, result, tt.expected)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkCheckIndexExclude(b *testing.B) {
|
|
|
|
tests := []struct {
|
|
|
|
isDir bool
|
|
|
|
isHidden bool
|
|
|
|
fullPath string
|
|
|
|
}{
|
|
|
|
{false, false, "/test/.test"},
|
|
|
|
{true, false, "/test/.test"},
|
|
|
|
{true, true, "/test/.test"},
|
|
|
|
{false, false, "/test/filepath"},
|
|
|
|
{false, true, "/test/filepath"},
|
|
|
|
{true, true, "/test/filepath"},
|
|
|
|
}
|
|
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
b.ReportAllocs()
|
|
|
|
idx := Index{
|
|
|
|
Source: settings.Source{
|
|
|
|
Name: "files",
|
|
|
|
Config: settings.IndexConfig{
|
|
|
|
IgnoreHidden: true,
|
|
|
|
Exclude: settings.IndexFilter{
|
|
|
|
Files: []string{"test", "filepath", ".test", ".filepath", "test", "filepath", ".test", ".filepath"},
|
|
|
|
Folders: []string{"test", "filepath", ".test", ".filepath", "test", "filepath", ".test", ".filepath"},
|
|
|
|
FileEndsWith: []string{".zip", ".tar", ".jpeg"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
for _, v := range tests {
|
|
|
|
idx.shouldSkip(v.isDir, v.isHidden, v.fullPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
func BenchmarkCheckIndexConditionsInclude(b *testing.B) {
|
|
|
|
tests := []struct {
|
|
|
|
isDir bool
|
|
|
|
isHidden bool
|
|
|
|
fullPath string
|
|
|
|
}{
|
|
|
|
{false, false, "/test/.test"},
|
|
|
|
{true, false, "/test/.test"},
|
|
|
|
{true, true, "/test/.test"},
|
|
|
|
{false, false, "/test/filepath"},
|
|
|
|
{false, true, "/test/filepath"},
|
|
|
|
{true, true, "/test/filepath"},
|
|
|
|
}
|
|
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
b.ReportAllocs()
|
|
|
|
idx2 := Index{
|
|
|
|
Source: settings.Source{
|
|
|
|
Name: "files",
|
|
|
|
Config: settings.IndexConfig{
|
|
|
|
IgnoreHidden: true,
|
|
|
|
Include: settings.IndexFilter{
|
|
|
|
Files: []string{"test", "filepath", ".test", ".filepath", "test", "filepath", ".test", ".filepath"},
|
|
|
|
Folders: []string{"test", "filepath", ".test", ".filepath", "test", "filepath", ".test", ".filepath"},
|
|
|
|
FileEndsWith: []string{".zip", ".tar", ".jpeg"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
for _, v := range tests {
|
|
|
|
idx2.shouldSkip(v.isDir, v.isHidden, v.fullPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|