mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
103 lines
3.4 KiB
Go
103 lines
3.4 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package lang
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
|
|
|
"github.com/opentofu/opentofu/internal/addrs"
|
|
)
|
|
|
|
func TestReferencesInExpr(t *testing.T) {
|
|
// Note for developers, this list is non-exhaustive right now
|
|
// and there are many more expression types. This test is mainly to ensure that provider
|
|
// defined function references are returned from references with parentheses
|
|
// to resolve issue opentofu/opentofu#3401
|
|
tests := map[string]struct {
|
|
exprSrc string
|
|
wantFuncRefs []string // List of expected provider function references
|
|
}{
|
|
"no functions": {
|
|
exprSrc: `"literal"`,
|
|
wantFuncRefs: nil,
|
|
},
|
|
"provider function without parentheses": {
|
|
exprSrc: `provider::testing::echo("hello")`,
|
|
wantFuncRefs: []string{"provider::testing::echo"},
|
|
},
|
|
"provider function with parentheses": {
|
|
exprSrc: `(provider::testing::echo("hello"))`,
|
|
wantFuncRefs: []string{"provider::testing::echo"},
|
|
},
|
|
"provider function in binary expression": {
|
|
exprSrc: `(provider::testing::add(1, 2)) + 3`,
|
|
wantFuncRefs: []string{"provider::testing::add"},
|
|
},
|
|
"nested parentheses": {
|
|
exprSrc: `((provider::testing::echo("hello")))`,
|
|
wantFuncRefs: []string{"provider::testing::echo"},
|
|
},
|
|
"provider function in conditional true": {
|
|
exprSrc: `true ? provider::testing::echo("yes") : "no"`,
|
|
wantFuncRefs: []string{"provider::testing::echo"},
|
|
},
|
|
"provider function in conditional false": {
|
|
exprSrc: `false ? "yes" : provider::testing::echo("no")`,
|
|
wantFuncRefs: []string{"provider::testing::echo"},
|
|
},
|
|
"provider function in conditional condition": {
|
|
exprSrc: `provider::testing::is_true() ? "yes" : "no"`,
|
|
wantFuncRefs: []string{"provider::testing::is_true"},
|
|
},
|
|
"multiple provider functions": {
|
|
exprSrc: `(provider::testing::add(1, 2)) + (provider::testing::mul(3, 4))`,
|
|
wantFuncRefs: []string{"provider::testing::add", "provider::testing::mul"},
|
|
},
|
|
"provider function with alias": {
|
|
exprSrc: `(provider::testing::custom::echo("hello"))`,
|
|
wantFuncRefs: []string{"provider::testing::custom::echo"},
|
|
},
|
|
"core function not included": {
|
|
exprSrc: `(core::max(1, 2))`,
|
|
wantFuncRefs: nil, // core functions are not provider functions
|
|
},
|
|
"builtin function not included": {
|
|
exprSrc: `(length([1, 2, 3]))`,
|
|
wantFuncRefs: nil, // builtin functions are not provider functions
|
|
},
|
|
}
|
|
|
|
for name, test := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
expr, diags := hclsyntax.ParseExpression([]byte(test.exprSrc), "test.tf", hcl.Pos{Line: 1, Column: 1})
|
|
if diags.HasErrors() {
|
|
t.Fatalf("Failed to parse expression: %s", diags.Error())
|
|
}
|
|
|
|
refs, refDiags := ReferencesInExpr(addrs.ParseRef, expr)
|
|
if refDiags.HasErrors() {
|
|
t.Errorf("Unexpected diagnostics: %s", refDiags.Err())
|
|
}
|
|
|
|
// Extract provider function references
|
|
var gotFuncRefs []string
|
|
for _, ref := range refs {
|
|
if provFunc, ok := ref.Subject.(addrs.ProviderFunction); ok {
|
|
gotFuncRefs = append(gotFuncRefs, provFunc.String())
|
|
}
|
|
}
|
|
|
|
if diff := cmp.Diff(test.wantFuncRefs, gotFuncRefs); diff != "" {
|
|
t.Errorf("Wrong provider function references (-want +got):\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|