-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathlow_file_test.go
More file actions
155 lines (127 loc) · 4.06 KB
/
Copy pathlow_file_test.go
File metadata and controls
155 lines (127 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// low_file_test.go: Testing Argus Low File Count Handling
//
// Copyright (c) 2025 AGILira - A. Giordano
// Series: an AGILira fragment
// SPDX-License-Identifier: MPL-2.0
package argus
import (
"fmt"
"os"
"path/filepath"
"sync/atomic"
"testing"
"time"
)
// Test optimized handling for low file counts (1-2 files)
func TestBoreasLite_LowFileCount(b *testing.T) {
tempDir, err := os.MkdirTemp("", "low_file_test")
if err != nil {
b.Fatal(err)
}
defer func() {
if err := os.RemoveAll(tempDir); err != nil {
b.Logf("Failed to remove tempDir: %v", err)
}
}()
config := Config{
PollInterval: 20 * time.Millisecond, // Polling more frequently for test
CacheTTL: 10 * time.Millisecond,
MaxWatchedFiles: 10,
}
b.Logf("=== TESTING OPTIMIZED 1-2 FILE SCENARIOS ===")
// Test 1: Single file (most common scenario)
b.Run("Single_File", func(b *testing.T) {
testLowFileCount(b, tempDir, config, 1)
})
// Test 2: Two files (second most common case)
b.Run("Two_Files", func(b *testing.T) {
testLowFileCount(b, tempDir, config, 2)
})
}
func testLowFileCount(t *testing.T, tempDir string, config Config, fileCount int) {
watcher := New(config)
defer func() {
if err := watcher.Stop(); err != nil {
t.Logf("Failed to stop watcher: %v", err)
}
}()
var eventCount atomic.Int64
filePaths := make([]string, fileCount)
callback := func(event ChangeEvent) {
eventCount.Add(1)
t.Logf("Event: %s", filepath.Base(event.Path))
}
// Create and register files
for i := 0; i < fileCount; i++ {
filePath := filepath.Join(tempDir, fmt.Sprintf("config_%d.json", i))
filePaths[i] = filePath
// Create file
content := fmt.Sprintf(`{"id": %d, "value": "initial"}`, i)
if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
t.Fatalf("Failed to create file %s: %v", filePath, err)
}
// Register with watcher
if err := watcher.Watch(filePath, callback); err != nil {
t.Fatalf("Failed to watch file %s: %v", filePath, err)
}
}
if err := watcher.Start(); err != nil {
t.Fatalf("Failed to start watcher: %v", err)
}
time.Sleep(50 * time.Millisecond) // Stabilization
// Measure latency for single changes
iterations := 10
totalDuration := time.Duration(0)
for iter := 0; iter < iterations; iter++ {
initialCount := eventCount.Load()
startTime := time.Now()
// Modify all files rapidly (simulate real-world scenario)
for i, filePath := range filePaths {
content := fmt.Sprintf(`{"id": %d, "value": "modified_%d_%d"}`, i, iter, time.Now().UnixNano())
if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
t.Fatal(err)
}
}
// Wait for all events to arrive
timeout := 200 * time.Millisecond
waitStart := time.Now()
for time.Since(waitStart) < timeout {
if eventCount.Load() >= initialCount+int64(fileCount) {
break
}
time.Sleep(1 * time.Millisecond)
}
iterDuration := time.Since(startTime)
totalDuration += iterDuration
if eventCount.Load() < initialCount+int64(fileCount) {
t.Errorf("Iteration %d: Missing events. Expected %d, got %d",
iter, fileCount, eventCount.Load()-initialCount)
}
}
avgLatency := totalDuration / time.Duration(iterations)
totalEvents := eventCount.Load()
// BoreasLite stats
var stats map[string]int64
if watcher.eventRing != nil {
stats = watcher.eventRing.Stats()
}
t.Logf("=== %d FILE(S) PERFORMANCE RESULTS ===", fileCount)
t.Logf("Total events: %d", totalEvents)
t.Logf("Average latency per iteration: %v", avgLatency)
t.Logf("Latency per event: %v", avgLatency/time.Duration(fileCount))
if stats != nil {
t.Logf("BoreasLite: processed=%d, dropped=%d",
stats["items_processed"], stats["items_dropped"])
if stats["items_dropped"] > 0 {
t.Errorf("Events dropped: %d", stats["items_dropped"])
}
}
// For 1-2 files, we should have very low latency
maxExpectedLatency := 50 * time.Millisecond
if avgLatency > maxExpectedLatency {
t.Logf("WARNING: High latency %v for %d files (expected <%v)",
avgLatency, fileCount, maxExpectedLatency)
} else {
t.Logf("✅ Excellent latency %v for %d files", avgLatency, fileCount)
}
}