mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
Signed-off-by: Christian Mesh <christianmesh1@gmail.com> Signed-off-by: Andrei Ciobanu <andrei.ciobanu@opentofu.org> Co-authored-by: Andrei Ciobanu <andrei.ciobanu@opentofu.org>
157 lines
4.4 KiB
Go
157 lines
4.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 plans
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/go-test/deep"
|
|
"github.com/opentofu/opentofu/internal/configs"
|
|
"github.com/zclconf/go-cty/cty"
|
|
ctymsgpack "github.com/zclconf/go-cty/cty/msgpack"
|
|
|
|
"github.com/opentofu/opentofu/internal/addrs"
|
|
)
|
|
|
|
func TestProviderAddrs(t *testing.T) {
|
|
|
|
plan := &Plan{
|
|
VariableValues: map[string]DynamicValue{},
|
|
Changes: &Changes{
|
|
Resources: []*ResourceInstanceChangeSrc{
|
|
{
|
|
Addr: addrs.Resource{
|
|
Mode: addrs.ManagedResourceMode,
|
|
Type: "test_thing",
|
|
Name: "woot",
|
|
}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
|
|
ProviderAddr: addrs.AbsProviderConfig{
|
|
Module: addrs.RootModule,
|
|
Provider: addrs.NewDefaultProvider("test"),
|
|
},
|
|
},
|
|
{
|
|
Addr: addrs.Resource{
|
|
Mode: addrs.ManagedResourceMode,
|
|
Type: "test_thing",
|
|
Name: "woot",
|
|
}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
|
|
DeposedKey: "foodface",
|
|
ProviderAddr: addrs.AbsProviderConfig{
|
|
Module: addrs.RootModule,
|
|
Provider: addrs.NewDefaultProvider("test"),
|
|
},
|
|
},
|
|
{
|
|
Addr: addrs.Resource{
|
|
Mode: addrs.ManagedResourceMode,
|
|
Type: "test_thing",
|
|
Name: "what",
|
|
}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
|
|
ProviderAddr: addrs.AbsProviderConfig{
|
|
Module: addrs.RootModule.Child("foo"),
|
|
Provider: addrs.NewDefaultProvider("test"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
got := plan.ProviderAddrs()
|
|
want := []addrs.AbsProviderConfig{
|
|
addrs.AbsProviderConfig{
|
|
Module: addrs.RootModule.Child("foo"),
|
|
Provider: addrs.NewDefaultProvider("test"),
|
|
},
|
|
addrs.AbsProviderConfig{
|
|
Module: addrs.RootModule,
|
|
Provider: addrs.NewDefaultProvider("test"),
|
|
},
|
|
}
|
|
|
|
for _, problem := range deep.Equal(got, want) {
|
|
t.Error(problem)
|
|
}
|
|
}
|
|
|
|
// Module outputs should not effect the result of Empty
|
|
func TestModuleOutputChangesEmpty(t *testing.T) {
|
|
changes := &Changes{
|
|
Outputs: []*OutputChangeSrc{
|
|
{
|
|
Addr: addrs.AbsOutputValue{
|
|
Module: addrs.RootModuleInstance.Child("child", addrs.NoKey),
|
|
OutputValue: addrs.OutputValue{
|
|
Name: "output",
|
|
},
|
|
},
|
|
ChangeSrc: ChangeSrc{
|
|
Action: Update,
|
|
Before: []byte("a"),
|
|
After: []byte("b"),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
if !changes.Empty() {
|
|
t.Fatal("plan has no visible changes")
|
|
}
|
|
}
|
|
|
|
// TestVariableMapper checks that the mapper is decoding types correctly from the plan
|
|
func TestVariableMapper(t *testing.T) {
|
|
val1 := cty.StringVal("string value")
|
|
val2 := cty.ObjectVal(map[string]cty.Value{"foo": cty.StringVal("bar")})
|
|
val3 := cty.MapVal(map[string]cty.Value{
|
|
"inner": cty.SetVal([]cty.Value{cty.StringVal("baz")}),
|
|
})
|
|
val4 := cty.ListVal([]cty.Value{cty.BoolVal(false)})
|
|
val5 := cty.SetVal([]cty.Value{
|
|
cty.ObjectVal(
|
|
map[string]cty.Value{
|
|
"inner": cty.ObjectVal(map[string]cty.Value{"foo": cty.NumberIntVal(25)}),
|
|
},
|
|
),
|
|
})
|
|
p := Plan{VariableValues: map[string]DynamicValue{
|
|
"raw_string": encodeDynamicValueWithType(t, val1, cty.DynamicPseudoType),
|
|
"object_of_strings": encodeDynamicValueWithType(t, val2, cty.DynamicPseudoType),
|
|
"map_of_sets_of_strings": encodeDynamicValueWithType(t, val3, cty.DynamicPseudoType),
|
|
"list_of_bools": encodeDynamicValueWithType(t, val4, cty.DynamicPseudoType),
|
|
"set_of_obj_of_obj_of_number": encodeDynamicValueWithType(t, val5, cty.DynamicPseudoType),
|
|
}}
|
|
|
|
vm := p.VariableMapper()
|
|
|
|
cases := map[string]cty.Value{
|
|
"raw_string": val1,
|
|
"object_of_strings": val2,
|
|
"map_of_sets_of_strings": val3,
|
|
"list_of_bools": val4,
|
|
"set_of_obj_of_obj_of_number": val5,
|
|
}
|
|
for varName, wantVal := range cases {
|
|
t.Run(varName, func(t *testing.T) {
|
|
val, diag := vm(&configs.Variable{Name: varName})
|
|
if diag.HasErrors() {
|
|
t.Fatalf("unexpected diagnostics from the variable mapper: %s", diag)
|
|
}
|
|
if !val.RawEquals(wantVal) {
|
|
t.Fatalf("returned value is not equal with the expected one.\n\twant:%s\n\tgot:%s\n", wantVal, val)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func encodeDynamicValueWithType(t *testing.T, value cty.Value, ty cty.Type) []byte {
|
|
data, err := ctymsgpack.Marshal(value, ty)
|
|
if err != nil {
|
|
t.Fatalf("failed to marshal JSON: %s", err)
|
|
}
|
|
return data
|
|
}
|