test: improve coverage across package

This commit is contained in:
2026-05-01 14:09:10 +05:30
parent e1c68ec7d0
commit e3f1f5046a
18 changed files with 2652 additions and 6 deletions

View File

@@ -26,11 +26,14 @@ import (
// ExprRule is the external representation of an expression rule.
type ExprRule struct {
Name string `yaml:"name"`
Action string `yaml:"action"`
Log bool `yaml:"log"`
Modifier ModifierEntry `yaml:"modifier"`
Expr string `yaml:"expr"`
Name string `yaml:"name"`
Action string `yaml:"action"`
Log bool `yaml:"log"`
Modifier ModifierEntry `yaml:"modifier"`
Expr string `yaml:"expr"`
StartTime string `yaml:"start_time"`
StopTime string `yaml:"stop_time"`
Weekdays []string `yaml:"weekdays"`
}
type ModifierEntry struct {
@@ -56,6 +59,10 @@ type compiledExprRule struct {
ModInstance modifier.Instance
Program *vm.Program
GeoSiteConditions []string
StartTimeSecs int // seconds since midnight, -1 if unset
StopTimeSecs int // seconds since midnight, -1 if unset
Weekdays []time.Weekday
WeekdaysNegated bool
}
var _ Ruleset = (*exprRuleset)(nil)
@@ -73,10 +80,13 @@ func (r *exprRuleset) Analyzers(info StreamInfo) []analyzer.Analyzer {
func (r *exprRuleset) Match(info StreamInfo) MatchResult {
env := streamInfoToExprEnv(info)
now := time.Now()
for _, rule := range r.Rules {
if !matchTime(now, rule.StartTimeSecs, rule.StopTimeSecs, rule.Weekdays, rule.WeekdaysNegated) {
continue
}
v, err := vm.Run(rule.Program, env)
if err != nil {
// Log the error and continue to the next rule.
r.Logger.MatchError(info, rule.Name, err)
continue
}
@@ -163,12 +173,34 @@ func CompileExprRules(rules []ExprRule, ans []analyzer.Analyzer, mods []modifier
depAnMap[name] = a
}
}
startSecs := -1
if rule.StartTime != "" {
startSecs, err = parseTimeOfDay(rule.StartTime)
if err != nil {
return nil, fmt.Errorf("rule %q has invalid start_time: %w", rule.Name, err)
}
}
stopSecs := -1
if rule.StopTime != "" {
stopSecs, err = parseTimeOfDay(rule.StopTime)
if err != nil {
return nil, fmt.Errorf("rule %q has invalid stop_time: %w", rule.Name, err)
}
}
weekdays, weekdaysNegated, err := parseWeekdays(rule.Weekdays)
if err != nil {
return nil, fmt.Errorf("rule %q has invalid weekdays: %w", rule.Name, err)
}
cr := compiledExprRule{
Name: rule.Name,
Action: action,
Log: rule.Log,
Program: program,
GeoSiteConditions: extractGeoSiteConditions(rule.Expr),
StartTimeSecs: startSecs,
StopTimeSecs: stopSecs,
Weekdays: weekdays,
WeekdaysNegated: weekdaysNegated,
}
if action != nil && *action == ActionModify {
mod, ok := fullModMap[rule.Modifier.Name]
@@ -391,6 +423,87 @@ func buildFunctionMap(config *BuiltinConfig) (map[string]*Function, *geo.GeoMatc
}, geoMatcher
}
func matchTime(now time.Time, startSecs, stopSecs int, weekdays []time.Weekday, negated bool) bool {
if startSecs >= 0 || stopSecs >= 0 {
currentSecs := now.Hour()*3600 + now.Minute()*60 + now.Second()
if startSecs >= 0 && stopSecs >= 0 {
if startSecs <= stopSecs {
if currentSecs < startSecs || currentSecs > stopSecs {
return false
}
} else {
if currentSecs < startSecs && currentSecs > stopSecs {
return false
}
}
} else if startSecs >= 0 {
if currentSecs < startSecs {
return false
}
} else if currentSecs > stopSecs {
return false
}
}
if len(weekdays) > 0 {
current := now.Weekday()
found := false
for _, d := range weekdays {
if current == d {
found = true
break
}
}
if negated == found {
return false
}
}
return true
}
func parseTimeOfDay(s string) (int, error) {
t, err := time.Parse("15:04:05", s)
if err != nil {
return -1, fmt.Errorf("invalid time %q (expected hh:mm:ss)", s)
}
return t.Hour()*3600 + t.Minute()*60 + t.Second(), nil
}
func parseWeekdays(days []string) ([]time.Weekday, bool, error) {
if len(days) == 0 {
return nil, false, nil
}
negated := false
parsed := make([]time.Weekday, 0, len(days))
for i, d := range days {
d = strings.TrimSpace(d)
if i == 0 && strings.HasPrefix(d, "!") {
negated = true
d = strings.TrimSpace(strings.TrimPrefix(d, "!"))
}
var wd time.Weekday
switch strings.ToLower(d) {
case "sun", "sunday":
wd = time.Sunday
case "mon", "monday":
wd = time.Monday
case "tue", "tues", "tuesday":
wd = time.Tuesday
case "wed", "wednesday":
wd = time.Wednesday
case "thu", "thur", "thurs", "thursday":
wd = time.Thursday
case "fri", "friday":
wd = time.Friday
case "sat", "saturday":
wd = time.Saturday
default:
return nil, false, fmt.Errorf("invalid weekday %q", d)
}
parsed = append(parsed, wd)
}
return parsed, negated, nil
}
const rulesetLogMetaKey = "_ruleset"
func addGeoSiteLogMetadata(info StreamInfo, gm *geo.GeoMatcher, conditions []string) StreamInfo {