Skip to content

Commit

Permalink
max, min and contains funcs.
Browse files Browse the repository at this point in the history
  • Loading branch information
cam-stitt committed Dec 4, 2017
1 parent 09f6507 commit dc62a54
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 10 deletions.
23 changes: 13 additions & 10 deletions interpolation/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@ import (

// CoreFunctions are the custom funtions for interpolation
var CoreFunctions = map[string]ast.Function{
"lower": interpolationFuncLower(),
"upper": interpolationFuncUpper(),
"env": interpolationFuncEnv(),
"join": interpolationFuncJoin(),
"has": interpolationFuncHas(),
"map": interpolationFuncMap(),
"keys": interpolationFuncKeys(),
"list": interpolationFuncList(),
"concat": interpolationFuncConcat(),
"replace": interpolationFuncReplace(),
"lower": interpolationFuncLower(),
"upper": interpolationFuncUpper(),
"env": interpolationFuncEnv(),
"join": interpolationFuncJoin(),
"has": interpolationFuncHas(),
"map": interpolationFuncMap(),
"keys": interpolationFuncKeys(),
"list": interpolationFuncList(),
"concat": interpolationFuncConcat(),
"replace": interpolationFuncReplace(),
"max": interpolationFuncMax(),
"min": interpolationFuncMin(),
"contains": interpolationFuncContains(),
}

// interpolationFuncEnv will extract a variable out of the env
Expand Down
48 changes: 48 additions & 0 deletions interpolation/math.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package interpolation

import (
"errors"
"math"

"github.com/hashicorp/hil/ast"
)

// interpolationFuncMax returns the largest value in a series of floats
func interpolationFuncMax() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{},
ReturnType: ast.TypeFloat,
Variadic: true,
VariadicType: ast.TypeFloat,
Callback: func(inputs []interface{}) (interface{}, error) {
if len(inputs) < 2 {
return nil, errors.New("max function requires at least 2 inputs")
}
max := inputs[0].(float64)
for _, input := range inputs[1:] {
max = math.Max(max, input.(float64))
}
return max, nil
},
}
}

// interpolationFuncMin returns the smallest value in a series of floats
func interpolationFuncMin() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{},
ReturnType: ast.TypeFloat,
Variadic: true,
VariadicType: ast.TypeFloat,
Callback: func(inputs []interface{}) (interface{}, error) {
if len(inputs) < 2 {
return nil, errors.New("min function requires at least 2 inputs")
}
min := inputs[0].(float64)
for _, input := range inputs[1:] {
min = math.Min(min, input.(float64))
}
return min, nil
},
}
}
61 changes: 61 additions & 0 deletions interpolation/math_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package interpolation

import "testing"

func TestInterpolationFuncMax(t *testing.T) {
testCases := []functionTestCase{
{
description: "Should find the max value",
text: `${max(0, 2)}`,
expectation: "2",
},
{
description: "One input should fail",
text: `${max(4)}`,
expectation: "",
evalError: true,
},
{
description: "Long list finds max",
text: `${max(100, 30, 450, 1, 25)}`,
expectation: "450",
},
}

maxTestFunc := testInterpolationFunc(keyFuncs{"max": interpolationFuncMax})

for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
maxTestFunc(t, tc)
})
}
}

func TestInterpolationFuncMin(t *testing.T) {
testCases := []functionTestCase{
{
description: "Should find the min value",
text: `${min(140, 250)}`,
expectation: "140",
},
{
description: "One input should fail",
text: `${min(4)}`,
expectation: "",
evalError: true,
},
{
description: "Long list finds min",
text: `${min(100, 30, 450, 1, 25)}`,
expectation: "1",
},
}

minTestFunc := testInterpolationFunc(keyFuncs{"min": interpolationFuncMin})

for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
minTestFunc(t, tc)
})
}
}
13 changes: 13 additions & 0 deletions interpolation/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,16 @@ func interpolationFuncReplace() ast.Function {
},
}
}

// interpolationFuncContains will check if a string contains the portion provided
func interpolationFuncContains() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeString, ast.TypeString},
ReturnType: ast.TypeBool,
Callback: func(inputs []interface{}) (interface{}, error) {
val := inputs[0].(string)
portion := inputs[1].(string)
return strings.Contains(val, portion), nil
},
}
}
23 changes: 23 additions & 0 deletions interpolation/strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,26 @@ func TestInterpolationFuncReplace(t *testing.T) {
})
}
}

func TestInterpolationFuncContains(t *testing.T) {
testCases := []functionTestCase{
{
description: "String does contain portion",
text: `${contains("hello", "ell")}`,
expectation: "true",
},
{
description: "String does not contain portion",
text: `${contains("hello", "foo")}`,
expectation: "false",
},
}

containsTestFunc := testInterpolationFunc(keyFuncs{"contains": interpolationFuncContains})

for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
containsTestFunc(t, tc)
})
}
}

0 comments on commit dc62a54

Please sign in to comment.