test: add comprehensive tests to improve coverage
- observability: added tests for LogLevel.String(), Warn(), Warnf(), Infof(), Debugf(), Error(), WithFields(), and concurrent access patterns - file: added tests for Reopen(), Close(), empty/whitespace paths, validateFilePath allowed/rejected paths, concurrent writes, Flush(), and marshal errors - config: added tests for TimeWindowConfig.GetDuration(), CorrelationConfig getters, validation scenarios (no inputs, no outputs, duplicate sockets, ClickHouse validation), and LogConfig.GetLevel() Coverage improvements: - observability: 57.7% → 79.5% - file: 68.6% → 78.6% - config: 69.8% → 97.7% - total: 68.6% → 74.4% Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@ -588,3 +588,353 @@ correlation:
|
||||
t.Error("expected outputs.stdout.enabled to be true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeWindowConfig_GetDuration(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
config TimeWindowConfig
|
||||
expected time.Duration
|
||||
}{
|
||||
{
|
||||
name: "seconds",
|
||||
config: TimeWindowConfig{Value: 5, Unit: "s"},
|
||||
expected: 5 * time.Second,
|
||||
},
|
||||
{
|
||||
name: "milliseconds",
|
||||
config: TimeWindowConfig{Value: 500, Unit: "ms"},
|
||||
expected: 500 * time.Millisecond,
|
||||
},
|
||||
{
|
||||
name: "default on zero value",
|
||||
config: TimeWindowConfig{Value: 0, Unit: "s"},
|
||||
expected: 1 * time.Second,
|
||||
},
|
||||
{
|
||||
name: "unknown unit defaults to seconds",
|
||||
config: TimeWindowConfig{Value: 5, Unit: "unknown"},
|
||||
expected: 5 * time.Second,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.config.GetDuration()
|
||||
if result != tt.expected {
|
||||
t.Errorf("expected %v, got %v", tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetTimeWindow(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
TimeWindow: TimeWindowConfig{Value: 2, Unit: "s"},
|
||||
}
|
||||
|
||||
result := cfg.GetTimeWindow()
|
||||
if result != 2*time.Second {
|
||||
t.Errorf("expected 2s, got %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetTimeWindow_Default(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
TimeWindow: TimeWindowConfig{Value: 0, Unit: "s"},
|
||||
}
|
||||
|
||||
result := cfg.GetTimeWindow()
|
||||
if result != 1*time.Second {
|
||||
t.Errorf("expected default 1s, got %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetMatchingMode(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
config CorrelationConfig
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "one_to_many",
|
||||
config: CorrelationConfig{Matching: MatchingConfig{Mode: "one_to_many"}},
|
||||
expected: "one_to_many",
|
||||
},
|
||||
{
|
||||
name: "one_to_one",
|
||||
config: CorrelationConfig{Matching: MatchingConfig{Mode: "one_to_one"}},
|
||||
expected: "one_to_one",
|
||||
},
|
||||
{
|
||||
name: "default empty",
|
||||
config: CorrelationConfig{Matching: MatchingConfig{Mode: ""}},
|
||||
expected: "one_to_many",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.config.GetMatchingMode()
|
||||
if result != tt.expected {
|
||||
t.Errorf("expected %s, got %s", tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetApacheAlwaysEmit(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
OrphanPolicy: OrphanPolicyConfig{ApacheAlwaysEmit: true},
|
||||
}
|
||||
|
||||
if !cfg.GetApacheAlwaysEmit() {
|
||||
t.Error("expected true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetApacheAlwaysEmit_Deprecated(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
EmitOrphans: true, // deprecated field
|
||||
}
|
||||
|
||||
if !cfg.GetApacheAlwaysEmit() {
|
||||
t.Error("expected true from deprecated field")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetNetworkTTLS(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
TTL: TTLConfig{NetworkTTLS: 60},
|
||||
}
|
||||
|
||||
result := cfg.GetNetworkTTLS()
|
||||
if result != 60 {
|
||||
t.Errorf("expected 60, got %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetNetworkTTLS_Default(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
TTL: TTLConfig{NetworkTTLS: 0},
|
||||
}
|
||||
|
||||
result := cfg.GetNetworkTTLS()
|
||||
if result != 30 {
|
||||
t.Errorf("expected default 30, got %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetMaxHTTPBufferSize(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
Buffers: BuffersConfig{MaxHTTPItems: 5000},
|
||||
}
|
||||
|
||||
result := cfg.GetMaxHTTPBufferSize()
|
||||
if result != 5000 {
|
||||
t.Errorf("expected 5000, got %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetMaxHTTPBufferSize_Default(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
Buffers: BuffersConfig{MaxHTTPItems: 0},
|
||||
}
|
||||
|
||||
result := cfg.GetMaxHTTPBufferSize()
|
||||
if result != 10000 {
|
||||
t.Errorf("expected default 10000, got %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetMaxNetworkBufferSize(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
Buffers: BuffersConfig{MaxNetworkItems: 15000},
|
||||
}
|
||||
|
||||
result := cfg.GetMaxNetworkBufferSize()
|
||||
if result != 15000 {
|
||||
t.Errorf("expected 15000, got %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrelationConfig_GetMaxNetworkBufferSize_Default(t *testing.T) {
|
||||
cfg := CorrelationConfig{
|
||||
Buffers: BuffersConfig{MaxNetworkItems: 0},
|
||||
}
|
||||
|
||||
result := cfg.GetMaxNetworkBufferSize()
|
||||
if result != 20000 {
|
||||
t.Errorf("expected default 20000, got %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnixSocketConfig_GetSocketPermissions_Invalid(t *testing.T) {
|
||||
cfg := UnixSocketConfig{
|
||||
SocketPermissions: "invalid",
|
||||
}
|
||||
|
||||
result := cfg.GetSocketPermissions()
|
||||
if result != 0666 {
|
||||
t.Errorf("expected default 0666 for invalid value, got %o", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_Validation(t *testing.T) {
|
||||
// Test config with no inputs
|
||||
content := `
|
||||
outputs:
|
||||
file:
|
||||
path: /var/log/test.log
|
||||
|
||||
correlation:
|
||||
time_window_s: 1
|
||||
`
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yml")
|
||||
if err := os.WriteFile(configPath, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write config: %v", err)
|
||||
}
|
||||
|
||||
_, err := Load(configPath)
|
||||
if err == nil {
|
||||
t.Error("expected error for config with no inputs")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_Validation_NoOutputs(t *testing.T) {
|
||||
// Test config with no outputs
|
||||
content := `
|
||||
inputs:
|
||||
unix_sockets:
|
||||
- name: http
|
||||
path: /var/run/logcorrelator/http.socket
|
||||
|
||||
correlation:
|
||||
time_window_s: 1
|
||||
`
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yml")
|
||||
if err := os.WriteFile(configPath, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write config: %v", err)
|
||||
}
|
||||
|
||||
_, err := Load(configPath)
|
||||
if err == nil {
|
||||
t.Error("expected error for config with no outputs")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_Validation_DuplicateSocketNames(t *testing.T) {
|
||||
content := `
|
||||
inputs:
|
||||
unix_sockets:
|
||||
- name: http
|
||||
path: /var/run/logcorrelator/http.socket
|
||||
- name: http
|
||||
path: /var/run/logcorrelator/other.socket
|
||||
|
||||
outputs:
|
||||
file:
|
||||
path: /var/log/test.log
|
||||
|
||||
correlation:
|
||||
time_window_s: 1
|
||||
`
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yml")
|
||||
if err := os.WriteFile(configPath, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write config: %v", err)
|
||||
}
|
||||
|
||||
_, err := Load(configPath)
|
||||
if err == nil {
|
||||
t.Error("expected error for duplicate socket names")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_Validation_DuplicateSocketPaths(t *testing.T) {
|
||||
content := `
|
||||
inputs:
|
||||
unix_sockets:
|
||||
- name: http
|
||||
path: /var/run/logcorrelator/http.socket
|
||||
- name: network
|
||||
path: /var/run/logcorrelator/http.socket
|
||||
|
||||
outputs:
|
||||
file:
|
||||
path: /var/log/test.log
|
||||
|
||||
correlation:
|
||||
time_window_s: 1
|
||||
`
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yml")
|
||||
if err := os.WriteFile(configPath, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write config: %v", err)
|
||||
}
|
||||
|
||||
_, err := Load(configPath)
|
||||
if err == nil {
|
||||
t.Error("expected error for duplicate socket paths")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_Validation_ClickHouseEnabled(t *testing.T) {
|
||||
content := `
|
||||
inputs:
|
||||
unix_sockets:
|
||||
- name: http
|
||||
path: /var/run/logcorrelator/http.socket
|
||||
|
||||
outputs:
|
||||
clickhouse:
|
||||
enabled: true
|
||||
|
||||
correlation:
|
||||
time_window_s: 1
|
||||
`
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yml")
|
||||
if err := os.WriteFile(configPath, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write config: %v", err)
|
||||
}
|
||||
|
||||
_, err := Load(configPath)
|
||||
if err == nil {
|
||||
t.Error("expected error for ClickHouse enabled without DSN")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_Validation_ClickHouseEnabled_NoTable(t *testing.T) {
|
||||
content := `
|
||||
inputs:
|
||||
unix_sockets:
|
||||
- name: http
|
||||
path: /var/run/logcorrelator/http.socket
|
||||
|
||||
outputs:
|
||||
clickhouse:
|
||||
enabled: true
|
||||
dsn: clickhouse://localhost:9000/db
|
||||
|
||||
correlation:
|
||||
time_window_s: 1
|
||||
`
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, "config.yml")
|
||||
if err := os.WriteFile(configPath, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write config: %v", err)
|
||||
}
|
||||
|
||||
_, err := Load(configPath)
|
||||
if err == nil {
|
||||
t.Error("expected error for ClickHouse enabled without table")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user