blob: a4dc1f5f529f819732d06ef76d89bc42aba34a96 [file] [log] [blame] [edit]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package providers
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/zclconf/go-cty/cty"
// set the correct global logger for tests
_ "github.com/hashicorp/terraform/internal/logging"
)
func TestFunctionCache(t *testing.T) {
testAddr := addrs.NewDefaultProvider("test")
type testCall struct {
provider addrs.Provider
name string
args []cty.Value
result cty.Value
}
tests := []struct {
first, second testCall
expectErr bool
}{
{
first: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.True,
},
second: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.True,
},
},
{
first: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.True,
},
second: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.False,
},
// result changed from true => false
expectErr: true,
},
{
first: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.UnknownVal(cty.Bool),
},
second: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.False,
},
// result changed from unknown => false
expectErr: true,
},
{
first: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.True,
},
second: testCall{
provider: addrs.NewDefaultProvider("fake"),
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.False,
},
// OK because provider changed
},
{
first: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.True,
},
second: testCall{
provider: testAddr,
name: "func",
args: []cty.Value{cty.StringVal("ok")},
result: cty.False,
},
// OK because function name changed
},
{
first: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok")},
result: cty.True,
},
second: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.StringVal("ok"), cty.StringVal("ok")},
result: cty.False,
},
// OK because args changed
},
{
first: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.ObjectVal(map[string]cty.Value{
"attr": cty.NumberIntVal(1),
})},
result: cty.True,
},
second: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.ObjectVal(map[string]cty.Value{
"attr": cty.NumberIntVal(2),
})},
result: cty.False,
},
// OK because args changed
},
{
first: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.UnknownVal(cty.Object(map[string]cty.Type{
"attr": cty.Number,
}))},
result: cty.UnknownVal(cty.Bool),
},
second: testCall{
provider: testAddr,
name: "fun",
args: []cty.Value{cty.ObjectVal(map[string]cty.Value{
"attr": cty.NumberIntVal(2),
})},
result: cty.False,
},
// OK because args changed from unknown to known
},
}
for i, test := range tests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
results := NewFunctionResultsTable(nil)
err := results.checkPrior(test.first.provider, test.first.name, test.first.args, test.first.result)
if err != nil {
t.Fatal("error on first call!", err)
}
err = results.checkPrior(test.second.provider, test.second.name, test.second.args, test.second.result)
if err != nil && !test.expectErr {
t.Fatal(err)
}
// reload the data to ensure we validate identically
newResults := NewFunctionResultsTable(results.GetHashes())
originalErr := err != nil
reloadedErr := newResults.checkPrior(test.second.provider, test.second.name, test.second.args, test.second.result) != nil
if originalErr != reloadedErr {
t.Fatalf("original check returned err:%t, reloaded check returned err:%t", originalErr, reloadedErr)
}
})
}
}