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:
parent
9dba6db676
commit
8f6659a2ec
|
@ -419,6 +419,13 @@ var exprFuncs = []exprCustomFunc{
|
||||||
new(func() (string, error)),
|
new(func() (string, error)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "FloatApproxEqual",
|
||||||
|
function: FloatApproxEqual,
|
||||||
|
signature: []interface{}{
|
||||||
|
new(func(float64, float64) bool),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//go 1.20 "CutPrefix": strings.CutPrefix,
|
//go 1.20 "CutPrefix": strings.CutPrefix,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
@ -54,6 +55,16 @@ var exprFunctionOptions []expr.Option
|
||||||
var keyValuePattern = regexp.MustCompile(`(?P<key>[^=\s]+)=(?:"(?P<quoted_value>[^"\\]*(?:\\.[^"\\]*)*)"|(?P<value>[^=\s]+)|\s*)`)
|
var keyValuePattern = regexp.MustCompile(`(?P<key>[^=\s]+)=(?:"(?P<quoted_value>[^"\\]*(?:\\.[^"\\]*)*)"|(?P<value>[^=\s]+)|\s*)`)
|
||||||
|
|
||||||
func GetExprOptions(ctx map[string]interface{}) []expr.Option {
|
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 := []expr.Option{}
|
||||||
ret = append(ret, exprFunctionOptions...)
|
ret = append(ret, exprFunctionOptions...)
|
||||||
ret = append(ret, expr.Env(ctx))
|
ret = append(ret, expr.Env(ctx))
|
||||||
|
@ -66,15 +77,6 @@ func Init(databaseClient *database.Client) error {
|
||||||
dataFileRe2 = make(map[string][]*re2.Regexp)
|
dataFileRe2 = make(map[string][]*re2.Regexp)
|
||||||
dbClient = databaseClient
|
dbClient = databaseClient
|
||||||
|
|
||||||
exprFunctionOptions = []expr.Option{}
|
|
||||||
for _, function := range exprFuncs {
|
|
||||||
exprFunctionOptions = append(exprFunctionOptions,
|
|
||||||
expr.Function(function.name,
|
|
||||||
function.function,
|
|
||||||
function.signature...,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,6 +591,16 @@ func Match(params ...any) (any, error) {
|
||||||
return matched, nil
|
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) {
|
func B64Decode(params ...any) (any, error) {
|
||||||
encoded := params[0].(string)
|
encoded := params[0].(string)
|
||||||
decoded, err := base64.StdEncoding.DecodeString(encoded)
|
decoded, err := base64.StdEncoding.DecodeString(encoded)
|
||||||
|
|
|
@ -103,7 +103,6 @@ func (p *ParserAssert) AssertFile(testFile string) error {
|
||||||
p.NbAssert += 1
|
p.NbAssert += 1
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Debugf("%s is FALSE", scanner.Text())
|
log.Debugf("%s is FALSE", scanner.Text())
|
||||||
//fmt.SPrintf(" %s '%s'\n", emoji.RedSquare, scanner.Text())
|
|
||||||
failedAssert := &AssertFail{
|
failedAssert := &AssertFail{
|
||||||
File: p.File,
|
File: p.File,
|
||||||
Line: nbLine,
|
Line: nbLine,
|
||||||
|
@ -112,10 +111,13 @@ func (p *ParserAssert) AssertFile(testFile string) error {
|
||||||
}
|
}
|
||||||
variableRE := regexp.MustCompile(`(?P<variable>[^ =]+) == .*`)
|
variableRE := regexp.MustCompile(`(?P<variable>[^ =]+) == .*`)
|
||||||
match := variableRE.FindStringSubmatch(scanner.Text())
|
match := variableRE.FindStringSubmatch(scanner.Text())
|
||||||
|
variable := ""
|
||||||
if len(match) == 0 {
|
if len(match) == 0 {
|
||||||
log.Infof("Couldn't get variable of line '%s'", scanner.Text())
|
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)
|
result, err := p.EvalExpression(variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("unable to evaluate variable '%s': %s", variable, err)
|
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
|
failedAssert.Debug[variable] = result
|
||||||
p.Fails = append(p.Fails, *failedAssert)
|
p.Fails = append(p.Fails, *failedAssert)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
//fmt.Printf(" %s '%s'\n", emoji.GreenSquare, scanner.Text())
|
//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}
|
env := map[string]interface{}{"results": *p.TestData}
|
||||||
|
|
||||||
if runtimeFilter, err = expr.Compile(expression, exprhelpers.GetExprOptions(env)...); err != nil {
|
if runtimeFilter, err = expr.Compile(expression, exprhelpers.GetExprOptions(env)...); err != nil {
|
||||||
|
log.Errorf("failed to compile '%s' : %s", expression, err)
|
||||||
return output, err
|
return output, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//dump opcode in trace level
|
//dump opcode in trace level
|
||||||
log.Tracef("%s", runtimeFilter.Disassemble())
|
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 {
|
if err != nil {
|
||||||
log.Warningf("running : %s", expression)
|
log.Warningf("running : %s", expression)
|
||||||
log.Warningf("runtime error : %s", err)
|
log.Warningf("runtime error : %s", err)
|
||||||
|
@ -251,8 +255,8 @@ func (p *ParserAssert) AutoGenParserAssert() string {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
base := fmt.Sprintf(`results["%s"]["%s"][%d].Evt.Unmarshaled["%s"]`, stage, parser, pidx, ekey)
|
base := fmt.Sprintf(`results["%s"]["%s"][%d].Evt.Unmarshaled["%s"]`, stage, parser, pidx, ekey)
|
||||||
for _, line := range p.buildUnmarshaledAssert("", eval) {
|
for _, line := range p.buildUnmarshaledAssert(base, eval) {
|
||||||
ret += base + line
|
ret += line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret += fmt.Sprintf(`results["%s"]["%s"][%d].Evt.Whitelisted == %t`+"\n", stage, parser, pidx, result.Evt.Whitelisted)
|
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:
|
case int:
|
||||||
ret = append(ret, fmt.Sprintf(`%s == %d`+"\n", ekey, val))
|
ret = append(ret, fmt.Sprintf(`%s == %d`+"\n", ekey, val))
|
||||||
case float64:
|
case float64:
|
||||||
ret = append(ret, fmt.Sprintf(`%s == %f`+"\n", ekey, val))
|
ret = append(ret, fmt.Sprintf(`FloatApproxEqual(%s, %f)`+"\n",
|
||||||
|
ekey, val))
|
||||||
default:
|
default:
|
||||||
log.Warningf("unknown type '%T' for key '%s'", val, ekey)
|
log.Warningf("unknown type '%T' for key '%s'", val, ekey)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue