blob: 62826e0bca8ee981cc670076bbe5920348e56d2c [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package mocking
import (
"math/rand"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/internal/configs/configschema"
)
var (
normalAttributes = map[string]*configschema.Attribute{
"id": {
Type: cty.String,
},
"value": {
Type: cty.String,
},
}
computedAttributes = map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Computed: true,
},
"value": {
Type: cty.String,
},
}
normalBlock = configschema.Block{
Attributes: normalAttributes,
}
computedBlock = configschema.Block{
Attributes: computedAttributes,
}
)
func TestComputedValuesForDataSource(t *testing.T) {
tcs := map[string]struct {
target cty.Value
with cty.Value
schema *configschema.Block
expected cty.Value
expectedFailures []string
}{
"nil_target_no_unknowns": {
target: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("kj87eb9"),
"value": cty.StringVal("Hello, world!"),
}),
with: cty.NilVal,
schema: &normalBlock,
expected: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("kj87eb9"),
"value": cty.StringVal("Hello, world!"),
}),
},
"empty_target_no_unknowns": {
target: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("kj87eb9"),
"value": cty.StringVal("Hello, world!"),
}),
with: cty.EmptyObjectVal,
schema: &normalBlock,
expected: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("kj87eb9"),
"value": cty.StringVal("Hello, world!"),
}),
},
"basic_computed_attribute_preset": {
target: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("kj87eb9"),
"value": cty.StringVal("Hello, world!"),
}),
with: cty.NilVal,
schema: &computedBlock,
expected: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("kj87eb9"),
"value": cty.StringVal("Hello, world!"),
}),
},
"basic_computed_attribute_random": {
target: cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("Hello, world!"),
}),
with: cty.NilVal,
schema: &computedBlock,
expected: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("Hello, world!"),
}),
},
"basic_computed_attribute_supplied": {
target: cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("Hello, world!"),
}),
with: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
schema: &computedBlock,
expected: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("Hello, world!"),
}),
},
"nested_single_block_preset": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("Hello, world!"),
}),
}),
with: cty.NilVal,
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingSingle,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("Hello, world!"),
}),
}),
},
"nested_single_block_supplied": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("Hello, world!"),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingSingle,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("Hello, world!"),
}),
}),
},
"nested_list_block_preset": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.NilVal,
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingList,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("amyllmyg"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_list_block_supplied": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingList,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_set_block_preset": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.NilVal,
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingSet,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("amyllmyg"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_set_block_supplied": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingSet,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_map_block_preset": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
"two": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.NilVal,
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingMap,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("one"),
}),
"two": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("amyllmyg"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_map_block_supplied": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
"two": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingMap,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("one"),
}),
"two": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_single_attribute": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("Hello, world!"),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingSingle,
},
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("Hello, world!"),
}),
}),
},
"nested_single_attribute_generated": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.NullVal(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
})),
}),
with: cty.NilVal,
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingSingle,
},
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("amyllmyg"),
}),
}),
},
"nested_single_attribute_computed": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.NullVal(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
})),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("hello"),
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingSingle,
},
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("hello"),
"value": cty.StringVal("ssnk9qhr"),
}),
}),
},
"nested_list_attribute": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingList,
},
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_list_attribute_generated": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.NullVal(cty.List(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
}))),
}),
with: cty.NilVal,
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingList,
},
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ListValEmpty(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
})),
}),
},
"nested_list_attribute_computed": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.NullVal(cty.List(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
}))),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingList,
},
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ListValEmpty(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
})),
}),
},
"nested_set_attribute": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingSet,
},
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("one"),
}),
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_set_attribute_generated": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
}))),
}),
with: cty.NilVal,
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingSet,
},
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.SetValEmpty(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
})),
}),
},
"nested_set_attribute_computed": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
}))),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingSet,
},
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.SetValEmpty(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
})),
}),
},
"nested_map_attribute": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
"two": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("two"),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingMap,
},
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("one"),
}),
"two": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
"value": cty.StringVal("two"),
}),
}),
}),
},
"nested_map_attribute_generated": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.NullVal(cty.Map(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
}))),
}),
with: cty.NilVal,
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingMap,
},
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.MapValEmpty(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
})),
}),
},
"nested_map_attribute_computed": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.NullVal(cty.Map(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
}))),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("myvalue"),
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingMap,
},
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.MapValEmpty(cty.Object(map[string]cty.Type{
"id": cty.String,
"value": cty.String,
})),
}),
},
"invalid_replacement_path": {
target: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("kj87eb9"),
"value": cty.StringVal("Hello, world!"),
}),
with: cty.StringVal("Hello, world!"),
schema: &normalBlock,
expected: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("kj87eb9"),
"value": cty.StringVal("Hello, world!"),
}),
expectedFailures: []string{
"The requested replacement value must be an object type, but was string.",
},
},
"invalid_replacement_path_nested": {
target: cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.StringVal("Hello, world!"),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested_object": {
NestedType: &configschema.Object{
Attributes: map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Computed: true,
},
},
Nesting: configschema.NestingSet,
},
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
}),
}),
}),
expectedFailures: []string{
"Terraform expected an object type for attribute \".nested_object[...]\" defined within the mocked data at :0,0-0, but found string.",
},
},
"invalid_replacement_path_nested_block": {
target: cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.StringVal("Hello, world!"),
}),
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"nested_object": {
Block: configschema.Block{
Attributes: map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Computed: true,
},
},
},
Nesting: configschema.NestingSet,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
}),
}),
}),
expectedFailures: []string{
"Terraform expected an object type for attribute \".nested_object[...]\" defined within the mocked data at :0,0-0, but found string.",
},
},
"invalid_replacement_type": {
target: cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("Hello, world!"),
}),
with: cty.ObjectVal(map[string]cty.Value{
"id": cty.ListValEmpty(cty.String),
}),
schema: &computedBlock,
expected: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("Hello, world!"),
}),
expectedFailures: []string{
"Terraform could not compute a value for the target type string with the mocked data defined at :0,0-0 with the attribute \".id\": string required.",
},
},
"invalid_replacement_type_nested": {
target: cty.ObjectVal(map[string]cty.Value{
"nested": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"nested": cty.ObjectVal(map[string]cty.Value{
"id": cty.EmptyObjectVal,
}),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"nested": {
NestedType: &configschema.Object{
Attributes: computedAttributes,
Nesting: configschema.NestingMap,
},
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"nested": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("one"),
}),
}),
}),
expectedFailures: []string{
`Terraform could not compute a value for the target type string with the mocked data defined at :0,0-0 with the attribute ".nested[\"one\"].id": string required.`,
},
},
"invalid_replacement_type_nested_block": {
target: cty.ObjectVal(map[string]cty.Value{
"block": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.NullVal(cty.String),
"value": cty.StringVal("one"),
}),
}),
}),
with: cty.ObjectVal(map[string]cty.Value{
"block": cty.ObjectVal(map[string]cty.Value{
"id": cty.EmptyObjectVal,
}),
}),
schema: &configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block": {
Block: computedBlock,
Nesting: configschema.NestingList,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"block": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("ssnk9qhr"),
"value": cty.StringVal("one"),
}),
}),
}),
expectedFailures: []string{
"Terraform could not compute a value for the target type string with the mocked data defined at :0,0-0 with the attribute \".block[0].id\": string required.",
},
},
"dynamic_attribute_unset": {
target: cty.ObjectVal(map[string]cty.Value{
"dynamic_attribute": cty.NullVal(cty.DynamicPseudoType),
}),
with: cty.EmptyObjectVal,
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"dynamic_attribute": {
Type: cty.DynamicPseudoType,
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"dynamic_attribute": cty.NullVal(cty.DynamicPseudoType),
}),
},
"dynamic_attribute_set": {
target: cty.ObjectVal(map[string]cty.Value{
"dynamic_attribute": cty.NullVal(cty.DynamicPseudoType),
}),
with: cty.ObjectVal(map[string]cty.Value{
"dynamic_attribute": cty.StringVal("Hello, world!"),
}),
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"dynamic_attribute": {
Type: cty.DynamicPseudoType,
Computed: true,
},
},
},
expected: cty.ObjectVal(map[string]cty.Value{
"dynamic_attribute": cty.StringVal("Hello, world!"),
}),
},
}
for name, tc := range tcs {
t.Run(name, func(t *testing.T) {
// We'll just make sure that any random strings are deterministic.
testRand = rand.New(rand.NewSource(0))
defer func() {
testRand = nil
}()
actual, diags := ComputedValuesForDataSource(tc.target, &MockedData{
Value: tc.with,
}, tc.schema)
var actualFailures []string
for _, diag := range diags {
actualFailures = append(actualFailures, diag.Description().Detail)
}
if diff := cmp.Diff(tc.expectedFailures, actualFailures); len(diff) > 0 {
t.Errorf("unexpected failures\nexpected:\n%s\nactual:\n%s\ndiff:\n%s", tc.expectedFailures, actualFailures, diff)
}
if actual.Equals(tc.expected).False() {
t.Errorf("\nexpected: (%s)\nactual: (%s)", tc.expected.GoString(), actual.GoString())
}
})
}
}