Skip to content

Commit

Permalink
added "and" & "or" logic operators
Browse files Browse the repository at this point in the history
  • Loading branch information
mantidtech committed Jun 6, 2021
1 parent 87dd584 commit 2dc308c
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 2 deletions.
2 changes: 1 addition & 1 deletion functions/functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func helperNewTemplate(t *testing.T, tpl string) *template.Template {
// TestAll provides unit test coverage for All()
func TestAll(t *testing.T) {
fn := All(nil)
assert.Len(t, fn, 56, "weakly ensuring functions haven't been added/removed without updating tests")
assert.Len(t, fn, 58, "weakly ensuring functions haven't been added/removed without updating tests")
}

// TestCombineFunctionLists provides unit test coverage for CombineFunctionLists
Expand Down
25 changes: 25 additions & 0 deletions functions/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
// LogicFunctions perform logical operations
func LogicFunctions() template.FuncMap {
return template.FuncMap{
"and": And,
"isZero": IsZero,
"or": Or,
"when": When,
"whenEmpty": WhenEmpty,
}
Expand Down Expand Up @@ -46,3 +48,26 @@ func IsZero(val interface{}) bool {
}
return v.IsZero()
}

// And returns the value of the last expression if all expressions evaluate to non-zero, or empty string otherwise
func And(expr ...interface{}) interface{} {
if len(expr) == 0 {
return ""
}
for _, e := range expr {
if IsZero(e) {
return ""
}
}
return expr[len(expr)-1]
}

// Or returns the first expression that evaluates to non-zero, or empty string if none do
func Or(expr ...interface{}) interface{} {
for _, e := range expr {
if !IsZero(e) {
return e
}
}
return ""
}
202 changes: 201 additions & 1 deletion functions/logic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// TestLogicFunctions provides unit test coverage for LogicFunctions
func TestLogicFunctions(t *testing.T) {
fn := LogicFunctions()
assert.Len(t, fn, 3, "weakly ensuring functions haven't been added/removed without updating tests")
assert.Len(t, fn, 5, "weakly ensuring functions haven't been added/removed without updating tests")
}

// TestWhen provides unit test coverage for When()
Expand Down Expand Up @@ -332,3 +332,203 @@ func TestIsZero(t *testing.T) {
})
}
}

// TestAnd provides unit test coverage for And()
func TestAnd(t *testing.T) {
type Args struct {
A interface{}
B interface{}
C interface{}
D interface{}
}

tests := []struct {
name string
template string
args Args
want string
wantErr bool
}{
{
name: "no args",
template: `{{ and }}`,
args: Args{},
want: "",
},
{
name: "bool false",
template: `{{ and .A }}`,
args: Args{
A: false,
},
want: "",
},
{
name: "bool true",
template: `{{ and .A }}`,
args: Args{
A: true,
},
want: "true",
},
{
name: "int 9",
template: `{{ and .A }}`,
args: Args{
A: 9,
},
want: "9",
},
{
name: "2 empty args",
template: `{{ and .A .B }}`,
args: Args{
A: "",
B: 0,
},
want: "",
},
{
name: "3 true args",
template: `{{ and .A .B .C }}`,
args: Args{
A: 2,
B: 3,
C: "X",
},
want: "X",
},
{
name: "3 args, 1 false",
template: `{{ and .A .B .C }}`,
args: Args{
A: 2,
B: 0,
C: "X",
},
want: "",
},
}

for _, st := range tests {
tt := st
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var got bytes.Buffer

tpl := helperNewTemplate(t, tt.template)
err := tpl.ExecuteTemplate(&got, testTemplateName, tt.args)
if tt.wantErr {
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got.String())
})
}
}

// TestOr provides unit test coverage for Or()
func TestOr(t *testing.T) {
type Args struct {
A interface{}
B interface{}
C interface{}
D interface{}
}

tests := []struct {
name string
template string
args Args
want string
wantErr bool
}{
{
name: "no args",
template: `{{ or }}`,
args: Args{},
want: "",
},
{
name: "bool false",
template: `{{ or .A }}`,
args: Args{
A: false,
},
want: "",
},
{
name: "bool true",
template: `{{ or .A }}`,
args: Args{
A: true,
},
want: "true",
},
{
name: "int 9",
template: `{{ or .A }}`,
args: Args{
A: 9,
},
want: "9",
},
{
name: "2 empty args",
template: `{{ or .A .B }}`,
args: Args{
A: "",
B: 0,
},
want: "",
},
{
name: "3 true args",
template: `{{ or .A .B .C }}`,
args: Args{
A: 2,
B: 3,
C: "X",
},
want: "2",
},
{
name: "3 args, first false",
template: `{{ or .A .B .C }}`,
args: Args{
A: 0,
B: 2,
C: "X",
},
want: "2",
},
{
name: "3 args, middle false",
template: `{{ or .A .B .C }}`,
args: Args{
A: 2,
B: 0,
C: "X",
},
want: "2",
},
}

for _, st := range tests {
tt := st
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var got bytes.Buffer

tpl := helperNewTemplate(t, tt.template)
err := tpl.ExecuteTemplate(&got, testTemplateName, tt.args)
if tt.wantErr {
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got.String())
})
}
}

0 comments on commit 2dc308c

Please sign in to comment.