Skip to content

Commit

Permalink
add corner test for computed type changing
Browse files Browse the repository at this point in the history
  • Loading branch information
austinvalle committed Mar 25, 2024
1 parent e77375d commit d8822b7
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 0 deletions.
104 changes: 104 additions & 0 deletions internal/framework5provider/dynamic_edge_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package framework

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var _ resource.Resource = DynamicEdgeResource{}

func NewDynamicEdgeResource() resource.Resource {
return &DynamicEdgeResource{}
}

// DynamicEdgeResource is for testing specific scenarios for dynamic schema types.
type DynamicEdgeResource struct{}

func (r DynamicEdgeResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_dynamic_edge"
}

func (r DynamicEdgeResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"required_dynamic": schema.DynamicAttribute{
Required: true,
},
// This computed dynamic attribute changes type during refresh
"computed_dynamic_type_changes": schema.DynamicAttribute{
Computed: true,
},
// id attribute is required for acceptance testing.
"id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
},
}
}

func (r DynamicEdgeResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data DynamicEdgeResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Created as a boolean type
data.ComputedDynamicTypeChanges = types.DynamicValue(types.BoolValue(true))

data.Id = types.StringValue("test")

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r DynamicEdgeResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data DynamicEdgeResourceModel

resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Refreshed to a string type
data.ComputedDynamicTypeChanges = types.DynamicValue(types.StringValue("it's a string!"))

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r DynamicEdgeResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data DynamicEdgeResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Updated to a number type
data.ComputedDynamicTypeChanges = types.DynamicValue(types.Int64Value(200))

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r DynamicEdgeResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}

type DynamicEdgeResourceModel struct {
RequiredDynamic types.Dynamic `tfsdk:"required_dynamic"`
ComputedDynamicTypeChanges types.Dynamic `tfsdk:"computed_dynamic_type_changes"`
Id types.String `tfsdk:"id"`
}
49 changes: 49 additions & 0 deletions internal/framework5provider/dynamic_edge_resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package framework

import (
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)

// TODO: The computed dynamic value type should be allowed to change, bug will be fixed with:
// - https://github.com/hashicorp/terraform-plugin-framework/issues/969
func TestDynamicEdge_computed_type_changes(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"framework": providerserver.NewProtocol5WithError(New()),
},
Steps: []resource.TestStep{
{
Config: `resource "framework_dynamic_edge" "test" {
required_dynamic = "value1"
}`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue("framework_dynamic_edge.test", tfjsonpath.New("required_dynamic"), knownvalue.StringExact("value1")),
// Created as a boolean
statecheck.ExpectKnownValue("framework_dynamic_edge.test", tfjsonpath.New("computed_dynamic_type_changes"), knownvalue.Bool(true)),
},
},
{
Config: `resource "framework_dynamic_edge" "test" {
required_dynamic = "new value"
}`,
// ConfigStateChecks: []statecheck.StateCheck{
// statecheck.ExpectKnownValue("framework_dynamic_edge.test", tfjsonpath.New("required_dynamic"), knownvalue.StringExact("new value")),
// // After update, it's a number!
// statecheck.ExpectKnownValue("framework_dynamic_edge.test", tfjsonpath.New("computed_dynamic_type_changes"), knownvalue.Int64Exact(200)),
// },
ExpectError: regexp.MustCompile(`unexpected new value: .computed_dynamic_type_changes: wrong final value type:\nstring required.`),
},
},
})
}
1 change: 1 addition & 0 deletions internal/framework5provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func (p *testProvider) Resources(_ context.Context) []func() resource.Resource {
return []func() resource.Resource{
NewSchemaResource,
NewDynamicSchemaResource,
NewDynamicEdgeResource,
NewTimeoutsResource,
NewUserResource,
NewFloat64PrecisionResource,
Expand Down
104 changes: 104 additions & 0 deletions internal/framework6provider/dynamic_edge_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package framework

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var _ resource.Resource = DynamicEdgeResource{}

func NewDynamicEdgeResource() resource.Resource {
return &DynamicEdgeResource{}
}

// DynamicEdgeResource is for testing specific scenarios for dynamic schema types.
type DynamicEdgeResource struct{}

func (r DynamicEdgeResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_dynamic_edge"
}

func (r DynamicEdgeResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"required_dynamic": schema.DynamicAttribute{
Required: true,
},
// This computed dynamic attribute changes type during refresh
"computed_dynamic_type_changes": schema.DynamicAttribute{
Computed: true,
},
// id attribute is required for acceptance testing.
"id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
},
}
}

func (r DynamicEdgeResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data DynamicEdgeResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Created as a boolean type
data.ComputedDynamicTypeChanges = types.DynamicValue(types.BoolValue(true))

data.Id = types.StringValue("test")

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r DynamicEdgeResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data DynamicEdgeResourceModel

resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Refreshed to a string type
data.ComputedDynamicTypeChanges = types.DynamicValue(types.StringValue("it's a string!"))

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r DynamicEdgeResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data DynamicEdgeResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Updated to a number type
data.ComputedDynamicTypeChanges = types.DynamicValue(types.Int64Value(200))

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r DynamicEdgeResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}

type DynamicEdgeResourceModel struct {
RequiredDynamic types.Dynamic `tfsdk:"required_dynamic"`
ComputedDynamicTypeChanges types.Dynamic `tfsdk:"computed_dynamic_type_changes"`
Id types.String `tfsdk:"id"`
}
49 changes: 49 additions & 0 deletions internal/framework6provider/dynamic_edge_resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package framework

import (
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)

// TODO: The computed dynamic value type should be allowed to change, bug will be fixed with:
// - https://github.com/hashicorp/terraform-plugin-framework/issues/969
func TestDynamicEdge_computed_type_changes(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
"framework": providerserver.NewProtocol6WithError(New()),
},
Steps: []resource.TestStep{
{
Config: `resource "framework_dynamic_edge" "test" {
required_dynamic = "value1"
}`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue("framework_dynamic_edge.test", tfjsonpath.New("required_dynamic"), knownvalue.StringExact("value1")),
// Created as a boolean
statecheck.ExpectKnownValue("framework_dynamic_edge.test", tfjsonpath.New("computed_dynamic_type_changes"), knownvalue.Bool(true)),
},
},
{
Config: `resource "framework_dynamic_edge" "test" {
required_dynamic = "new value"
}`,
// ConfigStateChecks: []statecheck.StateCheck{
// statecheck.ExpectKnownValue("framework_dynamic_edge.test", tfjsonpath.New("required_dynamic"), knownvalue.StringExact("new value")),
// // After update, it's a number!
// statecheck.ExpectKnownValue("framework_dynamic_edge.test", tfjsonpath.New("computed_dynamic_type_changes"), knownvalue.Int64Exact(200)),
// },
ExpectError: regexp.MustCompile(`unexpected new value: .computed_dynamic_type_changes: wrong final value type:\nstring required.`),
},
},
})
}
1 change: 1 addition & 0 deletions internal/framework6provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func (p *testProvider) Configure(ctx context.Context, req provider.ConfigureRequ
func (p *testProvider) Resources(_ context.Context) []func() resource.Resource {
return []func() resource.Resource{
NewSchemaResource,
NewDynamicEdgeResource,
NewTimeoutsResource,
NewUserResource,
NewFloat64PrecisionResource,
Expand Down

0 comments on commit d8822b7

Please sign in to comment.