Skip to content

Commit

Permalink
Implemented ALL comparison operators [testing needed]
Browse files Browse the repository at this point in the history
  • Loading branch information
redjack96 committed Sep 3, 2024
1 parent 252096d commit d30cac9
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 3 deletions.
13 changes: 10 additions & 3 deletions internal/fc/asl.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,22 +213,29 @@ func buildTestExpr(t *asl.TestExpression) (Condition, error) {
case "BooleanEqualsPath":
condition = NewEqParamCondition(param1, param2)
case "TimestampEquals":
condition = NewEqParamCondition(param1, param2)
case "TimestampEqualsPath":
condition = NewEqParamCondition(param1, param2)
case "TimestampLessThan":
condition = NewSmallerParamCondition(param1, param2)
case "TimestampLessThanPath":
condition = NewSmallerParamCondition(param1, param2)
case "TimestampGreaterThan":
condition = NewGreaterParamCondition(param1, param2)
case "TimestampGreaterThanPath":
condition = NewGreaterParamCondition(param1, param2)
case "TimestampLessThanEquals":
condition = NewOr(NewSmallerParamCondition(param1, param2), NewEqParamCondition(param1, param2))
case "TimestampLessThanEqualsPath":
condition = NewOr(NewSmallerParamCondition(param1, param2), NewEqParamCondition(param1, param2))
case "TimestampGreaterThanEquals":
condition = NewOr(NewGreaterParamCondition(param1, param2), NewEqParamCondition(param1, param2))
case "TimestampGreaterThanEqualsPath":
return NewConstCondition(false), fmt.Errorf("not implemented")
condition = NewOr(NewGreaterParamCondition(param1, param2), NewEqParamCondition(param1, param2))
case "IsNull":
condition = NewIsNullParamCondition(param1)
break
case "IsPresent":
condition = NewIsPresentParamCondition(param1)
break
case "IsNumeric":
condition = NewIsNumericParamCondition(param1)
case "IsString":
Expand Down
52 changes: 52 additions & 0 deletions internal/fc/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ func (c Condition) Test(input map[string]interface{}) (bool, error) {
if err != nil {
return false, err
}

// Try to parse the first value as a timestamp
firstTimestamp, isTimestamp := parseRFC3339(ops[0])
if isTimestamp {
for i := 1; i < len(ops); i++ {
currentTimestamp, isCurrentTimestamp := parseRFC3339(ops[i])
if !isCurrentTimestamp {
return false, nil
}
if !firstTimestamp.Equal(currentTimestamp) {
return false, nil
}
}
return true, nil
}

for i := 0; i < len(ops)-1; i++ {
if ops[i] != ops[i+1] {
return false, nil
Expand Down Expand Up @@ -240,6 +256,18 @@ func (c Condition) Test(input map[string]interface{}) (bool, error) {
if err != nil {
return false, err
}

// Try parsing the inputs as timestamps first
time1, isTime1 := parseRFC3339(ops[0])
time2, isTime2 := parseRFC3339(ops[1])
if isTime1 && isTime2 {
return time1.After(time2), nil
}
// if only one of the parameters is a timestamp, we know the result is false
if isTime1 || isTime2 {
return false, nil
}

// try converting operands to float
f := function.Float{}
float1, err1 := f.Convert(ops[0])
Expand Down Expand Up @@ -273,6 +301,18 @@ func (c Condition) Test(input map[string]interface{}) (bool, error) {
if err != nil {
return false, err
}

// Try parsing the inputs as timestamps first
time1, isTime1 := parseRFC3339(ops[0])
time2, isTime2 := parseRFC3339(ops[1])
if isTime1 && isTime2 {
return time1.Before(time2), nil
}
// if only one of the parameters is a timestamp, we know the result is false
if isTime1 || isTime2 {
return false, nil
}

// try converting operands to float
f := function.Float{}
float1, err1 := f.Convert(ops[0])
Expand Down Expand Up @@ -765,3 +805,15 @@ func (rcb *RootConditionBuilder) Not(cond Condition) *ConditionBuilder {
func (cb *ConditionBuilder) Build() Condition {
return cb.p.Root
}

func parseRFC3339(value interface{}) (time.Time, bool) {
str, ok := value.(string)
if !ok {
return time.Time{}, false
}
t, err := time.Parse(time.RFC3339, str)
if err != nil {
return time.Time{}, false
}
return t, true
}
72 changes: 72 additions & 0 deletions internal/test/condition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,78 @@ func TestBooleanEquals(t *testing.T) {
}
}

func TestTimestampEqualsSmallerGreater(t *testing.T) {
//conditions := []string{
// "eq",
// "smaller",
// "greater",
// "smallerEq",
// "greaterEq",
// "diff",
//}
tests := []struct {
param1 *fc.ParamOrValue
param2 *fc.ParamOrValue
operation string
expectedResult bool
}{
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "eq", true},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "smaller", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "greater", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "smallerEq", true},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "greaterEq", true},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "diff", false},

// Timestamp 1 is earlier than Timestamp 2
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T15:07:42Z"), "eq", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T15:07:42Z"), "smaller", true},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T15:07:42Z"), "greater", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T15:07:42Z"), "smallerEq", true},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T15:07:42Z"), "greaterEq", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03T15:07:42Z"), "diff", true},

// Timestamp 1 is later than Timestamp 2
{fc.NewValue("2024-09-03T15:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "eq", false},
{fc.NewValue("2024-09-03T15:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "smaller", false},
{fc.NewValue("2024-09-03T15:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "greater", true},
{fc.NewValue("2024-09-03T15:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "smallerEq", false},
{fc.NewValue("2024-09-03T15:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "greaterEq", true},
{fc.NewValue("2024-09-03T15:07:42Z"), fc.NewValue("2024-09-03T14:07:42Z"), "diff", true},

// Invalid timestamp formats
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03 14:07:42"), "eq", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03 14:07:42"), "smaller", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03 14:07:42"), "greater", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03 14:07:42"), "smallerEq", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03 14:07:42"), "greaterEq", false},
{fc.NewValue("2024-09-03T14:07:42Z"), fc.NewValue("2024-09-03 14:07:42"), "diff", true},
}

for i, test := range tests {
var cond fc.Condition
switch test.operation {
case "eq":
cond = fc.NewEqParamCondition(test.param1, test.param2)
case "smaller":
cond = fc.NewSmallerParamCondition(test.param1, test.param2)
case "greater":
cond = fc.NewGreaterParamCondition(test.param1, test.param2)
case "smallerEq":
cond = fc.NewOr(fc.NewSmallerParamCondition(test.param1, test.param2), fc.NewEqParamCondition(test.param1, test.param2))
case "greaterEq":
cond = fc.NewOr(fc.NewGreaterParamCondition(test.param1, test.param2), fc.NewEqParamCondition(test.param1, test.param2))
case "diff":
cond = fc.NewDiffParamCondition(test.param1, test.param2)
default:
utils.AssertFalseMsg(t, true, "fail: non existent operation")
}

ok, err := cond.Test(map[string]interface{}{})
utils.AssertNil(t, err)
utils.AssertEqualsMsg(t, test.expectedResult, ok, fmt.Sprintf("test %d: %v %s %v", i+1, test.param1.GetOperand(), test.operation, test.param2.GetOperand()))
}
}

func TestIsNullIsPresent(t *testing.T) {
tests := []struct {
value interface{}
Expand Down

0 comments on commit d30cac9

Please sign in to comment.