Skip to content

Commit

Permalink
truth table test for all bool expressions
Browse files Browse the repository at this point in the history
Just to put them all in one place, generate a table of all possible 2
and 3 part boolean expressions. Where the order operations matters for
the result, a parenthesized version is also added for reference.
  • Loading branch information
jbardin committed Dec 2, 2024
1 parent 7947f74 commit 144fdb5
Showing 1 changed file with 173 additions and 0 deletions.
173 changes: 173 additions & 0 deletions hclsyntax/expression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2914,3 +2914,176 @@ func TestParseExpression_incompleteFunctionCall(t *testing.T) {
})
}
}

func TestAllBoolExpressions(t *testing.T) {
inputs := map[string]cty.Value{
// truth table for all boolean expressions
"true && true": cty.True,
"true || true": cty.True,
"true && false": cty.False,
"true || false": cty.True,
"true && unknown": cty.DynamicVal,
"true || unknown": cty.True,
"false && true": cty.False,
"false || true": cty.True,
"false && false": cty.False,
"false || false": cty.False,
"false && unknown": cty.False,
"false || unknown": cty.DynamicVal,
"unknown && true": cty.DynamicVal,
"unknown || true": cty.True,
"unknown && false": cty.False,
"unknown || false": cty.DynamicVal,
"unknown && unknown": cty.DynamicVal,
"unknown || unknown": cty.DynamicVal,

// Truth table for all possible combinations of 3 part boolean
// expressions. Also added equivalent parenthesized versions for when
// the operator precedense affects the result.
"true && true && true": cty.True,
"true || true && true": cty.True,
"true || true || true": cty.True,
"true && true || true": cty.True,
"true && true && false": cty.False,
"true || true && false": cty.True,
"true || true || false": cty.True,
"true && true || false": cty.True,
"true && true && unknown": cty.DynamicVal,
"true || true && unknown": cty.True,
"true || true || unknown": cty.True,
"true && true || unknown": cty.True,
"true && false && true": cty.False,
"true || false && true": cty.True,
"true || false || true": cty.True,
"true && false || true": cty.True,
"true && false && false": cty.False,
"true || false && false": cty.True,
"true || false || false": cty.True,
"true && false || false": cty.False,
"true && false && unknown": cty.False,
"true || false && unknown": cty.True,
"true || false || unknown": cty.True,
"true && false || unknown": cty.DynamicVal,
"true && unknown && true": cty.DynamicVal,
"true || unknown && true": cty.True,
"true || unknown || true": cty.True,
"true && unknown || true": cty.True,
"true && unknown && false": cty.False,
"true || unknown && false": cty.True,
"true || unknown || false": cty.True,
"true && unknown || false": cty.DynamicVal,
"true && unknown && unknown": cty.DynamicVal,
"true || unknown && unknown": cty.True,
"true || unknown || unknown": cty.True,
"true && unknown || unknown": cty.DynamicVal,
"false && true && true": cty.False,
"false || true && true": cty.True,
"false || true || true": cty.True,
"false && true || true": cty.True,
"(false && true) || true": cty.True,
"false && true && false": cty.False,
"false || true && false": cty.False,
"false || true || false": cty.True,
"false && true || false": cty.False,
"false && true && unknown": cty.False,
"false || true && unknown": cty.DynamicVal,
"false || true || unknown": cty.True,
"false && true || unknown": cty.DynamicVal,
"(false && true) || unknown": cty.DynamicVal,
"false && false && true": cty.False,
"false || false && true": cty.False,
"false || false || true": cty.True,
"false && false || true": cty.True,
"false && false && false": cty.False,
"false || false && false": cty.False,
"false || false || false": cty.False,
"false && false || false": cty.False,
"false && false && unknown": cty.False,
"false || false && unknown": cty.False,
"false || false || unknown": cty.DynamicVal,
"false && false || unknown": cty.DynamicVal,
"(false && false) || unknown": cty.DynamicVal,
"false && unknown && true": cty.False,
"false || unknown && true": cty.DynamicVal,
"false || unknown || true": cty.True,
"false && unknown || true": cty.True,
"(false && unknown) || true": cty.True,
"false && unknown && false": cty.False,
"false || unknown && false": cty.False,
"false || unknown || false": cty.DynamicVal,
"false && unknown || false": cty.False,
"false && unknown && unknown": cty.False,
"false || unknown && unknown": cty.DynamicVal,
"false || unknown || unknown": cty.DynamicVal,
"false && unknown || unknown": cty.DynamicVal,
"(false && unknown) || unknown": cty.DynamicVal,
"unknown && true && true": cty.DynamicVal,
"unknown || true && true": cty.True,
"unknown || true || true": cty.True,
"unknown && true || true": cty.True,
"unknown && true && false": cty.False,
"unknown || true && false": cty.DynamicVal,
"unknown || (true && false)": cty.DynamicVal,
"unknown || true || false": cty.True,
"unknown && true || false": cty.DynamicVal,
"unknown && true && unknown": cty.DynamicVal,
"unknown || true && unknown": cty.DynamicVal,
"unknown || true || unknown": cty.True,
"unknown && true || unknown": cty.DynamicVal,
"unknown && false && true": cty.False,
"unknown || false && true": cty.DynamicVal,
"unknown || false || true": cty.True,
"unknown && false || true": cty.True,
"(unknown && false) || true": cty.True,
"unknown && false && false": cty.False,
"unknown || false && false": cty.DynamicVal,
"unknown || false || false": cty.DynamicVal,
"unknown && false || false": cty.False,
"unknown && false && unknown": cty.False,
"unknown || false && unknown": cty.DynamicVal,
"unknown || false || unknown": cty.DynamicVal,
"unknown && false || unknown": cty.DynamicVal,
"unknown && unknown && true": cty.DynamicVal,
"unknown || unknown && true": cty.DynamicVal,
"unknown || unknown || true": cty.True,
"unknown && unknown || true": cty.True,
"unknown && unknown && false": cty.False,
"unknown || unknown && false": cty.DynamicVal,
"unknown || unknown || false": cty.DynamicVal,
"unknown && unknown || false": cty.DynamicVal,
"unknown && unknown && unknown": cty.DynamicVal,
"unknown || unknown && unknown": cty.DynamicVal,
"unknown || unknown || unknown": cty.DynamicVal,
"unknown && unknown || unknown": cty.DynamicVal,
}

for input, want := range inputs {
t.Run(input, func(t *testing.T) {
ctx := &hcl.EvalContext{
Variables: map[string]cty.Value{
"unknown": cty.UnknownVal(cty.DynamicPseudoType),
},
}
expr, diags := ParseExpression([]byte(input), "", hcl.Pos{Line: 1, Column: 1, Byte: 0})
if diags.HasErrors() {
t.Fatal(diags.Error())
}
got, diags := expr.Value(ctx)
if diags.HasErrors() {
t.Fatal(diags.Error())
}

if got.IsKnown() != want.IsKnown() {
t.Fatalf("%q resulted in %#v, wanted %#v\n", input, got, want)
}
if !got.IsKnown() {
// covered in known comparison
return
}

if got.Equals(want).False() {
t.Fatalf("%q resulted in %#v, wanted %#v\n", input, got, want)
}
})
}
}

0 comments on commit 144fdb5

Please sign in to comment.