fix the float comparison by using Abs(a,b) < 1e-6 approach (IEEE 754). Move the initializiation of expr helpers (#2492)

This commit is contained in:
Thibault "bui" Koechlin 2023-09-28 17:22:00 +02:00 committed by GitHub
parent 9dba6db676
commit 8f6659a2ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 15 deletions

View file

@ -419,6 +419,13 @@ var exprFuncs = []exprCustomFunc{
new(func() (string, error)),
},
},
{
name: "FloatApproxEqual",
function: FloatApproxEqual,
signature: []interface{}{
new(func(float64, float64) bool),
},
},
}
//go 1.20 "CutPrefix": strings.CutPrefix,

View file

@ -4,6 +4,7 @@ import (
"bufio"
"encoding/base64"
"fmt"
"math"
"net"
"net/url"
"os"
@ -54,6 +55,16 @@ var exprFunctionOptions []expr.Option
var keyValuePattern = regexp.MustCompile(`(?P<key>[^=\s]+)=(?:"(?P<quoted_value>[^"\\]*(?:\\.[^"\\]*)*)"|(?P<value>[^=\s]+)|\s*)`)
func GetExprOptions(ctx map[string]interface{}) []expr.Option {
if len(exprFunctionOptions) == 0 {
exprFunctionOptions = []expr.Option{}
for _, function := range exprFuncs {
exprFunctionOptions = append(exprFunctionOptions,
expr.Function(function.name,
function.function,
function.signature...,
))
}
}
ret := []expr.Option{}
ret = append(ret, exprFunctionOptions...)
ret = append(ret, expr.Env(ctx))
@ -66,15 +77,6 @@ func Init(databaseClient *database.Client) error {
dataFileRe2 = make(map[string][]*re2.Regexp)
dbClient = databaseClient
exprFunctionOptions = []expr.Option{}
for _, function := range exprFuncs {
exprFunctionOptions = append(exprFunctionOptions,
expr.Function(function.name,
function.function,
function.signature...,
))
}
return nil
}
@ -589,6 +591,16 @@ func Match(params ...any) (any, error) {
return matched, nil
}
func FloatApproxEqual(params ...any) (any, error) {
float1 := params[0].(float64)
float2 := params[1].(float64)
if math.Abs(float1-float2) < 1e-6 {
return true, nil
}
return false, nil
}
func B64Decode(params ...any) (any, error) {
encoded := params[0].(string)
decoded, err := base64.StdEncoding.DecodeString(encoded)

View file

@ -103,7 +103,6 @@ func (p *ParserAssert) AssertFile(testFile string) error {
p.NbAssert += 1
if !ok {
log.Debugf("%s is FALSE", scanner.Text())
//fmt.SPrintf(" %s '%s'\n", emoji.RedSquare, scanner.Text())
failedAssert := &AssertFail{
File: p.File,
Line: nbLine,
@ -112,10 +111,13 @@ func (p *ParserAssert) AssertFile(testFile string) error {
}
variableRE := regexp.MustCompile(`(?P<variable>[^ =]+) == .*`)
match := variableRE.FindStringSubmatch(scanner.Text())
variable := ""
if len(match) == 0 {
log.Infof("Couldn't get variable of line '%s'", scanner.Text())
variable = scanner.Text()
} else {
variable = match[1]
}
variable := match[1]
result, err := p.EvalExpression(variable)
if err != nil {
log.Errorf("unable to evaluate variable '%s': %s", variable, err)
@ -123,6 +125,7 @@ func (p *ParserAssert) AssertFile(testFile string) error {
}
failedAssert.Debug[variable] = result
p.Fails = append(p.Fails, *failedAssert)
continue
}
//fmt.Printf(" %s '%s'\n", emoji.GreenSquare, scanner.Text())
@ -154,13 +157,14 @@ func (p *ParserAssert) RunExpression(expression string) (interface{}, error) {
env := map[string]interface{}{"results": *p.TestData}
if runtimeFilter, err = expr.Compile(expression, exprhelpers.GetExprOptions(env)...); err != nil {
log.Errorf("failed to compile '%s' : %s", expression, err)
return output, err
}
//dump opcode in trace level
log.Tracef("%s", runtimeFilter.Disassemble())
output, err = expr.Run(runtimeFilter, map[string]interface{}{"results": *p.TestData})
output, err = expr.Run(runtimeFilter, env)
if err != nil {
log.Warningf("running : %s", expression)
log.Warningf("runtime error : %s", err)
@ -251,8 +255,8 @@ func (p *ParserAssert) AutoGenParserAssert() string {
continue
}
base := fmt.Sprintf(`results["%s"]["%s"][%d].Evt.Unmarshaled["%s"]`, stage, parser, pidx, ekey)
for _, line := range p.buildUnmarshaledAssert("", eval) {
ret += base + line
for _, line := range p.buildUnmarshaledAssert(base, eval) {
ret += line
}
}
ret += fmt.Sprintf(`results["%s"]["%s"][%d].Evt.Whitelisted == %t`+"\n", stage, parser, pidx, result.Evt.Whitelisted)
@ -284,7 +288,8 @@ func (p *ParserAssert) buildUnmarshaledAssert(ekey string, eval interface{}) []s
case int:
ret = append(ret, fmt.Sprintf(`%s == %d`+"\n", ekey, val))
case float64:
ret = append(ret, fmt.Sprintf(`%s == %f`+"\n", ekey, val))
ret = append(ret, fmt.Sprintf(`FloatApproxEqual(%s, %f)`+"\n",
ekey, val))
default:
log.Warningf("unknown type '%T' for key '%s'", val, ekey)
}