From 641b9f3ee4133352fef6cfab43e4f85e3de4e8eb Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Sun, 11 Oct 2015 15:57:06 -0400 Subject: [PATCH] scheduler: support lexical ordering constraints --- scheduler/feasible.go | 29 ++++++++++++++++++++++-- scheduler/feasible_test.go | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/scheduler/feasible.go b/scheduler/feasible.go index 5ecfbedab..7482a953d 100644 --- a/scheduler/feasible.go +++ b/scheduler/feasible.go @@ -250,8 +250,7 @@ func checkConstraint(operand string, lVal, rVal interface{}) bool { case "!=", "not": return !reflect.DeepEqual(lVal, rVal) case "<", "<=", ">", ">=": - // TODO: Implement - return false + return checkLexicalOrder(operand, lVal, rVal) case "version": return checkVersionConstraint(lVal, rVal) case "regexp": @@ -261,6 +260,32 @@ func checkConstraint(operand string, lVal, rVal interface{}) bool { } } +// checkLexicalOrder is used to check for lexical ordering +func checkLexicalOrder(op string, lVal, rVal interface{}) bool { + // Ensure the values are strings + lStr, ok := lVal.(string) + if !ok { + return false + } + rStr, ok := rVal.(string) + if !ok { + return false + } + + switch op { + case "<": + return lStr < rStr + case "<=": + return lStr <= rStr + case ">": + return lStr > rStr + case ">=": + return lStr >= rStr + default: + return false + } +} + // checkVersionConstraint is used to compare a version on the // left hand side with a set of constraints on the right hand side func checkVersionConstraint(lVal, rVal interface{}) bool { diff --git a/scheduler/feasible_test.go b/scheduler/feasible_test.go index 8ee3c6dc5..a69b4c8ce 100644 --- a/scheduler/feasible_test.go +++ b/scheduler/feasible_test.go @@ -254,6 +254,11 @@ func TestCheckConstraint(t *testing.T) { lVal: "foobarbaz", rVal: "[\\w]+", result: true, }, + { + op: "<", + lVal: "foo", rVal: "bar", + result: false, + }, } for _, tc := range cases { @@ -263,6 +268,46 @@ func TestCheckConstraint(t *testing.T) { } } +func TestCheckLexicalOrder(t *testing.T) { + type tcase struct { + op string + lVal, rVal interface{} + result bool + } + cases := []tcase{ + { + op: "<", + lVal: "bar", rVal: "foo", + result: true, + }, + { + op: "<=", + lVal: "foo", rVal: "foo", + result: true, + }, + { + op: ">", + lVal: "bar", rVal: "foo", + result: false, + }, + { + op: ">=", + lVal: "bar", rVal: "bar", + result: true, + }, + { + op: ">", + lVal: 1, rVal: "foo", + result: false, + }, + } + for _, tc := range cases { + if res := checkLexicalOrder(tc.op, tc.lVal, tc.rVal); res != tc.result { + t.Fatalf("TC: %#v, Result: %v", tc, res) + } + } +} + func TestCheckVersionConstraint(t *testing.T) { type tcase struct { lVal, rVal interface{}