Skip to content

Commit

Permalink
Fix to Choice parsing.
Browse files Browse the repository at this point in the history
Fix to String() methods.
Added logs for some Equals() methods
All test pass.
  • Loading branch information
redjack96 committed Aug 28, 2024
1 parent 09e190b commit 3e9b189
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 113 deletions.
97 changes: 72 additions & 25 deletions internal/asl/choice_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package asl
import (
"fmt"
"github.com/grussorusso/serverledge/internal/types"
"reflect"
"strconv"
"strings"
)
Expand All @@ -12,7 +13,7 @@ type RuleType int
const (
BooleanExpr = iota
DataTestExpr
TestExpr
// TestExpr
)

type ChoiceRule interface {
Expand Down Expand Up @@ -49,10 +50,10 @@ func (b *BooleanExpression) Equals(cmp types.Comparable) bool {
}

func (b *BooleanExpression) String() string {
return "\t\t\t\t\t" + b.Formula.GetFormulaType() + ": {\n" +
return "\n\t\t\t\t" + b.Formula.GetFormulaType() + ": {" +
b.Formula.String() +
"\n\t\t\t\t\tNext: " + b.Next +
"\n\t\t\t\t\t}"
"\n\t\t\t\t}"
}

func (b *BooleanExpression) GetRuleType() RuleType {
Expand Down Expand Up @@ -102,25 +103,25 @@ func (t *TestExpression) Validate(stateNames []string) error {
}

func (t *TestExpression) String() string {
str := "\n\t\t\t\t{"
str := "\t\t\t\t\t\t{\n"

if t.Variable != "" {
str += fmt.Sprintf("\n\t\t\t\t\tVariable: %s\n", t.Variable)
str += fmt.Sprintf("\t\t\t\t\t\t\tVariable: %s\n", t.Variable)
}
if t.ComparisonOperator != nil {
str += t.ComparisonOperator.String()
}
return str + "\n\t\t\t\t}"
}

func (t *TestExpression) GetRuleType() RuleType {
return TestExpr
return str + "\n\t\t\t\t\t\t}"
}

func (t *TestExpression) Equals(cmp types.Comparable) bool {
d2 := cmp.(*TestExpression)
return t.Variable == d2.Variable &&
t.ComparisonOperator.Equals(d2.ComparisonOperator)
t2, ok := cmp.(*TestExpression)
if !ok {
fmt.Printf("t1: %v\nt2: %v\n", t, t2)
return false
}
return t.Variable == t2.Variable &&
t.ComparisonOperator.Equals(t2.ComparisonOperator)
}

func ParseTestExpr(jsonRule []byte) (*TestExpression, error) {
Expand All @@ -129,7 +130,8 @@ func ParseTestExpr(jsonRule []byte) (*TestExpression, error) {
return nil, err
}

comparisonOperator := ComparisonOperator{}
tempComparisonOperator := ComparisonOperator{}
var compOp *ComparisonOperator = nil
for i, comparator := range PossibleComparators {
comparatorValue, errComp := JsonExtractString(jsonRule, string(comparator))
if errComp != nil {
Expand All @@ -139,37 +141,42 @@ func ParseTestExpr(jsonRule []byte) (*TestExpression, error) {
continue
}
// comparator kind field
comparisonOperator.Kind = comparator
tempComparisonOperator.Kind = comparator
comparatorString := string(comparator)
// comparator datatype and operand fields
if strings.HasPrefix(comparatorString, "String") {
comparisonOperator.DataType = StringComparator
comparisonOperator.Operand = comparatorValue
tempComparisonOperator.DataType = StringComparator
tempComparisonOperator.Operand = comparatorValue
} else if strings.HasPrefix(comparatorString, "Numeric") {
comparisonOperator.DataType = NumericComparator
comparisonOperator.Operand, err = strconv.Atoi(comparatorValue)
tempComparisonOperator.DataType = NumericComparator
tempComparisonOperator.Operand, err = strconv.Atoi(comparatorValue)
if err != nil {
return nil, fmt.Errorf("failed to convert to int the value %s: %v", comparatorValue, err)
}
} else if strings.HasPrefix(comparatorString, "Timestamp") {
comparisonOperator.DataType = TimestampComparator
comparisonOperator.Operand = comparatorValue
tempComparisonOperator.DataType = TimestampComparator
tempComparisonOperator.Operand = comparatorValue
} else if strings.HasPrefix(comparatorString, "Boolean") || strings.HasPrefix(comparatorString, "Is") {
comparisonOperator.DataType = BooleanComparator
comparisonOperator.Operand, err = strconv.ParseBool(comparatorValue)
tempComparisonOperator.DataType = BooleanComparator
tempComparisonOperator.Operand, err = strconv.ParseBool(comparatorValue)
if err != nil {
return nil, fmt.Errorf("failed to convert to bool the value %s: %v", comparatorValue, err)
}
} else {
return nil, fmt.Errorf("invalid comparator: %s", comparator)
}
compOp, err = NewComparisonOperator(tempComparisonOperator.Kind, tempComparisonOperator.DataType, tempComparisonOperator.Operand)
if err != nil {
return nil, fmt.Errorf("something went wrong with comparison operator: %v", err)
}

// we have found a valid comparator, so we exit the for loop
break
}

return &TestExpression{
Variable: variable,
ComparisonOperator: &comparisonOperator,
ComparisonOperator: compOp,
}, nil
}

Expand Down Expand Up @@ -231,11 +238,51 @@ type ComparisonOperator struct {
Operand interface{}
}

func NewComparisonOperator(comparatorInstance ComparisonOperatorKind, comparatorType ComparisonOperatorDataType, operand interface{}) (*ComparisonOperator, error) {
opType := reflect.TypeOf(operand).Kind()
switch comparatorType {
case StringComparator:
if opType != reflect.String {
return nil, fmt.Errorf("invalid string comparison operator for value %v with type: %T", operand, operand)
}
break
case NumericComparator:
if !(opType == reflect.Int || opType == reflect.Int8 || opType == reflect.Int16 || opType == reflect.Int32 || opType == reflect.Int64 ||
opType == reflect.Uint || opType == reflect.Uint8 || opType == reflect.Uint16 || opType == reflect.Uint32 || opType == reflect.Uint64 ||
opType == reflect.Float32 || opType == reflect.Float64) {
return nil, fmt.Errorf("invalid numeric comparison operator for value %v with type: %T", operand, operand)
}
break
case TimestampComparator:
if opType != reflect.String {
return nil, fmt.Errorf("invalid timestamp comparison operator for value %v with type: %T", operand, operand)
}
break
case BooleanComparator:
if opType != reflect.Bool {
return nil, fmt.Errorf("invalid boolean comparison operator for value %v with type: %T", operand, operand)
}
break
default:
return nil, fmt.Errorf("invalid comparison operator %v", comparatorType)
}

return &ComparisonOperator{
Kind: comparatorInstance,
DataType: comparatorType,
Operand: operand,
}, nil
}

func (co *ComparisonOperator) String() string {
return fmt.Sprintf("\t\t\t\t\t%s: %v\n", co.Kind, co.Operand)
return fmt.Sprintf("\t\t\t\t\t\t\t%s: %v", co.Kind, co.Operand)
}

func (co *ComparisonOperator) Equals(co2 *ComparisonOperator) bool {
if reflect.TypeOf(co.Operand) != reflect.TypeOf(co2.Operand) {
fmt.Printf("Operand type differs: expected %v, but found %v\n", reflect.TypeOf(co.Operand), reflect.TypeOf(co2.Operand))
return false
}
return co.Kind == co2.Kind && co.DataType == co2.DataType && co.Operand == co2.Operand
}

Expand Down
56 changes: 28 additions & 28 deletions internal/asl/formula.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Formula interface {
}

type AndFormula struct {
And []ChoiceRule
And []*TestExpression
}

func (a *AndFormula) Equals(cmp types.Comparable) bool {
Expand All @@ -23,28 +23,36 @@ func (a *AndFormula) Equals(cmp types.Comparable) bool {
}
for i, choiceRule := range a.And {
if !choiceRule.Equals(otherAnd.And[i]) {
fmt.Printf("And1: %v\n And2: %v\n", choiceRule, otherAnd.And[i])
return false
}
}

return true
}

func (a *AndFormula) String() string {
str := "\t\t\t\t\t\tAnd: ["

for i, choiceRule := range a.And {
str += "\n\t\t\t\t\t\t\t" + choiceRule.String()
if i != len(a.And)-1 {
str += ","
func printTestExpression(expressions []*TestExpression) string {
str := "\t\t\t\t\t\n\t\t\t\t\t["
exprLenMinusOne := len(expressions) - 1
for i, choiceRule := range expressions {
if i == 0 {
str += "\n"
}
str += choiceRule.String()
if i != exprLenMinusOne {
str += ",\n"
} else {
str += "\n"
}
}

str += "]"

str += "\t\t\t\t\t]"
return str
}

func (a *AndFormula) String() string {
return printTestExpression(a.And)
}

func (a *AndFormula) GetFormulaType() string {
return "And"
}
Expand All @@ -54,7 +62,7 @@ func ParseAnd(jsonBytes []byte) (*AndFormula, error) {
if err != nil {
return nil, fmt.Errorf("failed to parse and formula: %v", err)
}
andArray := make([]ChoiceRule, 0)
andArray := make([]*TestExpression, 0)
_, err = jsonparser.ArrayEach(andJson, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
rule, err := ParseTestExpr(value)
if err != nil {
Expand All @@ -70,15 +78,15 @@ func ParseAnd(jsonBytes []byte) (*AndFormula, error) {
}

type OrFormula struct {
Or []ChoiceRule
Or []*TestExpression
}

func ParseOr(jsonBytes []byte) (*OrFormula, error) {
orRule, err := JsonExtract(jsonBytes, "Or")
if err != nil {
return nil, fmt.Errorf("failed to parse Or formula: %v", err)
}
orArray := make([]ChoiceRule, 0)
orArray := make([]*TestExpression, 0)
_, err = jsonparser.ArrayEach(orRule, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
rule, err := ParseTestExpr(orRule)
if err != nil {
Expand Down Expand Up @@ -108,26 +116,15 @@ func (o *OrFormula) Equals(cmp types.Comparable) bool {
}

func (o *OrFormula) String() string {
str := "\t\t\t\t\t\tOr: ["

for i, choiceRule := range o.Or {
str += "\n\t\t\t\t\t\t\t" + choiceRule.String()
if i != len(o.Or)-1 {
str += ","
}
}

str += "]"

return str
return printTestExpression(o.Or)
}

func (o *OrFormula) GetFormulaType() string {
return "Or"
}

type NotFormula struct {
Not ChoiceRule
Not *TestExpression
}

func ParseNot(jsonBytes []byte) (*NotFormula, error) {
Expand All @@ -151,7 +148,10 @@ func (n *NotFormula) Equals(cmp types.Comparable) bool {
}

func (n *NotFormula) String() string {
return fmt.Sprintf("\t\t\t\t\t\tNot: %s", n.Not.String())
return fmt.Sprintf(
"\n\t\t\t\t\tVariable: %s\n"+
"\t\t\t\t\t%s: %s",
n.Not.Variable, n.Not.ComparisonOperator.Kind, n.Not.ComparisonOperator.Operand)
}

func (n *NotFormula) GetFormulaType() string {
Expand Down
3 changes: 2 additions & 1 deletion internal/asl/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ type HasResources interface {
GetResources() []string
}

type Parseable interface {
type Parsable interface {
fmt.Stringer
ParseFrom(jsonData []byte) (State, error)
}

Expand Down
27 changes: 19 additions & 8 deletions internal/asl/state_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (sm *StateMachine) Validate(stateNames []string) error {
return nil
}

func emptyParsableFromType(t StateType) Parseable {
func emptyParsableFromType(t StateType) Parsable {
switch t {
case Task:
return NewEmptyTask()
Expand Down Expand Up @@ -125,20 +125,30 @@ func parseStates(statesData string) (map[string]State, error) {
return states, nil
}

func (sm *StateMachine) String() string {

func (sm *StateMachine) getStateString() string {
statesString := "["
for key, state := range sm.States {
statesString += "\n\t\t" + key + ":" + state.String()
statesString += "\n\t\t" + key + ": " + state.String()
}
if len(sm.States) > 0 {
statesString += "\n\t]\n"
statesString += "\n\t]"
} else {
statesString += "]\n" // this will show brackets like this: []
statesString += "]" // this will show brackets like this: []
}
return statesString
}

func (sm *StateMachine) String() string {

return fmt.Sprintf("{\n\tName: %s\n\tComment: %s\n\tStartAt: %s\n\tVersion: %s\n\tStates: %s\n}",
sm.Name, sm.Comment, sm.StartAt, sm.Version, statesString)
return fmt.Sprintf("{\n"+
"\tName: %s\n"+
"\tComment: %s\n"+
"\tStartAt: %s\n"+
"\tVersion: %s\n"+
"\tStates: "+
"%s\n"+
"}",
sm.Name, sm.Comment, sm.StartAt, sm.Version, sm.getStateString())
}

// GetFunctionNames retrieves all functions defined in the StateMachine, and duplicates are allowed
Expand Down Expand Up @@ -199,6 +209,7 @@ func (sm *StateMachine) Equals(comparer types.Comparable) bool {
// checks if all states are equal
for k := range sm.States {
if !sm.States[k].Equals(sm2.States[k]) {
fmt.Printf("sm.States[k]: %v\n sm2.States[k]: %v\n", sm.States[k], sm2.States[k])
return false
}
}
Expand Down
6 changes: 5 additions & 1 deletion internal/asl/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,11 @@ func (t *TaskState) IsEndState() bool {
}

func (t *TaskState) Equals(cmp types.Comparable) bool {
t2 := cmp.(*TaskState)
t2, ok := cmp.(*TaskState)
if !ok {
fmt.Printf("t1: %v\nt2: %v\n", t, cmp)
return false
}
return t.Type == t2.Type &&
t.Resource == t2.Resource &&
t.Next == t2.Next &&
Expand Down
Loading

0 comments on commit 3e9b189

Please sign in to comment.