Skip to content

Commit

Permalink
Adding "if" function to tick (influxdata#745)
Browse files Browse the repository at this point in the history
  • Loading branch information
yosiat authored and Nathaniel Cook committed Aug 2, 2016
1 parent 14a8e49 commit bedf3a8
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ stream
Also allows for grouping by measurement.
The breaking change is that the group ID format has changed to allow for the measurement name.
- [#759](https://github.com/influxdata/kapacitor/pull/759): Add mechanism for token based subscription auth.
- [#745](https://github.com/influxdata/kapacitor/pull/745): Add if function for tick script, for example: `if("value" > 6, 1, 2)`.

### Bugfixes

Expand Down
34 changes: 34 additions & 0 deletions tick/stateful/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"math"
"reflect"
"strconv"
"time"

Expand Down Expand Up @@ -87,6 +88,9 @@ func init() {

// Humanize functions
statelessFuncs["humanBytes"] = &humanBytes{}

// Conditionals
statelessFuncs["if"] = &ifFunc{}
}

// Return set of built-in Funcs
Expand Down Expand Up @@ -624,3 +628,33 @@ func (*humanBytes) Call(args ...interface{}) (v interface{}, err error) {
}
return
}

type ifFunc struct {
}

func (*ifFunc) Reset() {

}

func (*ifFunc) Call(args ...interface{}) (interface{}, error) {
if len(args) != 3 {
return nil, errors.New("if expects exactly three arguments")
}

var condition bool
var isBool bool

if condition, isBool = args[0].(bool); !isBool {
return nil, fmt.Errorf("first argument to if must be a condition with type of bool - got %T", args[0])
}

if reflect.TypeOf(args[1]) != reflect.TypeOf(args[2]) {
return nil, fmt.Errorf("Different return types are not supported - second argument is %T and third argument is %T", args[1], args[2])
}

if condition {
return args[1], nil
}

return args[2], nil
}
61 changes: 61 additions & 0 deletions tick/stateful/functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ func Test_String(t *testing.T) {
t.Errorf("unexpected error from call to string() got %s exp %s", got, expErr)
}
}

func Test_Duration(t *testing.T) {
f := &duration{}

Expand Down Expand Up @@ -485,3 +486,63 @@ func Test_Duration(t *testing.T) {
}
}
}

func Test_If(t *testing.T) {
f := &ifFunc{}

testCases := []struct {
args []interface{}
exp interface{}
err error
}{
// Error cases
{
args: []interface{}{true},
err: errors.New("if expects exactly three arguments"),
},
{
args: []interface{}{true, 6},
err: errors.New("if expects exactly three arguments"),
},
{
args: []interface{}{12, 6, false},
err: errors.New("first argument to if must be a condition with type of bool - got int"),
},

// Simple if
{
args: []interface{}{true, 1, 2},
exp: 1,
},
{
args: []interface{}{false, 1, 2},
exp: 2,
},

// multiple types
{
args: []interface{}{false, 1, "1"},
err: errors.New("Different return types are not supported - second argument is int and third argument is string"),
},
}

for _, tc := range testCases {
result, err := f.Call(tc.args...)
if tc.err != nil {
if err == nil {
t.Errorf("expected error from if(%v)\ngot: nil\nexp: exp %s", tc.args, tc.err)
} else if got, exp := err.Error(), tc.err.Error(); got != exp {
t.Errorf("unexpected error from if(%v)\ngot: %s\nexp: %s", tc.args, got, exp)
}
continue
} else if err != nil {
t.Errorf("unexpected error from if(%v) %s", tc.args, err)
continue
}

if result != tc.exp {
t.Errorf("unexpected result from if(%v)\ngot: %+v\nexp: %+v", tc.args, result, tc.exp)
}

}
}

0 comments on commit bedf3a8

Please sign in to comment.