Skip to content

Commit

Permalink
Use framework testprovider files for setup of test using ProtoV5Provi…
Browse files Browse the repository at this point in the history
…derFactories (#16)
  • Loading branch information
bendbennett committed Jan 12, 2023
1 parent 4cac99e commit 021c2e8
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 5 deletions.
4 changes: 2 additions & 2 deletions helper/resource/testing_new.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,12 +424,12 @@ func diagnosticFound(wd *plugintest.WorkingDir, r *regexp.Regexp, severity tfjso
txt := scanner.Text()

if json.Unmarshal([]byte(txt), &outer) == nil {
jsonOutput = append(jsonOutput, txt)

if outer.Diagnostic.Severity == "" {
continue
}

jsonOutput = append(jsonOutput, txt)

if !r.MatchString(outer.Diagnostic.Summary) && !r.MatchString(outer.Diagnostic.Detail) {
continue
}
Expand Down
40 changes: 38 additions & 2 deletions helper/resource/testing_new_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
package resource

import (
"bufio"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"

tfjson "github.com/hashicorp/terraform-json"
"github.com/mitchellh/go-testing-interface"
Expand All @@ -18,6 +24,34 @@ import (
"github.com/hashicorp/terraform-plugin-testing/internal/plugintest"
)

func getJSONOutput(wd *plugintest.WorkingDir) []string {
stdoutFile, err := os.Open(filepath.Join(wd.GetBaseDir(), "stdout.txt"))
if err != nil {
log.Fatal(err)
}

scanner := bufio.NewScanner(stdoutFile)
var jsonOutput []string

for scanner.Scan() {
var outer struct {
Diagnostic tfjson.Diagnostic
}

txt := scanner.Text()

if json.Unmarshal([]byte(txt), &outer) == nil {
jsonOutput = append(jsonOutput, txt)
}
}

if err := scanner.Err(); err != nil {
log.Fatal(err)
}

return jsonOutput
}

func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugintest.WorkingDir, step TestStep, providers *providerFactories, w io.Writer) error {
t.Helper()

Expand All @@ -29,7 +63,7 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint
// require a refresh before applying
// failing to do this will result in data sources not being updated
err = runProviderCommand(ctx, t, func() error {
return wd.RefreshJSON(ctx, w)
return wd.Refresh(ctx)
}, wd, providers)
if err != nil {
return fmt.Errorf("Error running pre-apply refresh: %w", err)
Expand Down Expand Up @@ -68,14 +102,16 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint
}

// Apply the diff, creating real resources
// TODO: Update all Errorf outputs that should use contents of streaming json
// after calling terraform-exec with `-json`.
err = runProviderCommand(ctx, t, func() error {
return wd.ApplyJSON(ctx, w)
}, wd, providers)
if err != nil {
if step.Destroy {
return fmt.Errorf("Error running destroy: %w", err)
}
return fmt.Errorf("Error running apply: %w", err)
return fmt.Errorf("Error running apply: %s", strings.Join(getJSONOutput(wd), "\n"))
}

// Get the new state
Expand Down
60 changes: 59 additions & 1 deletion helper/resource/teststep_providers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@ import (

"github.com/google/go-cmp/cmp"
"github.com/hashicorp/go-cty/cty"
fwdiag "github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-framework/resource"
fwresourceschema "github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)

Expand Down Expand Up @@ -2411,6 +2417,58 @@ func TestTest_TestStep_ProviderFactories_ExpectWarningSummaryRefreshOnly(t *test
})
}

func TestTest_TestStep_ProviderFactories_ExpectWarningSummaryPlanOnly(t *testing.T) {
t.Parallel()

Test(t, TestCase{
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"random": providerserver.NewProtocol5WithError(&testprovider.Provider{
MetadataMethod: func(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "random"
},
ResourcesMethod: func(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource{
func() resource.Resource {
return &testprovider.Resource{
MetadataMethod: func(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_password"
},
SchemaMethod: func(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = fwresourceschema.Schema{
Attributes: map[string]fwresourceschema.Attribute{
"id": fwresourceschema.StringAttribute{
Computed: true,
},
},
}
},
CreateMethod: func(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data struct {
Id types.String `tfsdk:"id"`
}

data.Id = types.StringValue("example-id")

diags := resp.State.Set(ctx, &data)
resp.Diagnostics.Append(diags...)

resp.Diagnostics.Append(fwdiag.NewWarningDiagnostic("warning diagnostic - detail", ""))
},
}
},
}
},
}),
},
Steps: []TestStep{
{
Config: `resource "random_password" "test" { }`,
ExpectWarning: regexp.MustCompile(`.*warning diagnostic - detail`),
},
},
})
}

func setTimeForTest(t time.Time) func() {
return func() {
getTimeForTest = func() time.Time {
Expand Down
66 changes: 66 additions & 0 deletions internal/testing/testprovider/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package testprovider

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/resource"
)

var _ provider.Provider = &Provider{}

// Provider is declarative provider.Provider for unit testing.
type Provider struct {
// Provider interface methods
MetadataMethod func(context.Context, provider.MetadataRequest, *provider.MetadataResponse)
ConfigureMethod func(context.Context, provider.ConfigureRequest, *provider.ConfigureResponse)
SchemaMethod func(context.Context, provider.SchemaRequest, *provider.SchemaResponse)
DataSourcesMethod func(context.Context) []func() datasource.DataSource
ResourcesMethod func(context.Context) []func() resource.Resource
}

// Configure satisfies the provider.Provider interface.
func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
if p == nil || p.ConfigureMethod == nil {
return
}

p.ConfigureMethod(ctx, req, resp)
}

// DataSources satisfies the provider.Provider interface.
func (p *Provider) DataSources(ctx context.Context) []func() datasource.DataSource {
if p == nil || p.DataSourcesMethod == nil {
return nil
}

return p.DataSourcesMethod(ctx)
}

// Metadata satisfies the provider.Provider interface.
func (p *Provider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
if p == nil || p.MetadataMethod == nil {
return
}

p.MetadataMethod(ctx, req, resp)
}

// Schema satisfies the provider.Provider interface.
func (p *Provider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
if p == nil || p.SchemaMethod == nil {
return
}

p.SchemaMethod(ctx, req, resp)
}

// Resources satisfies the provider.Provider interface.
func (p *Provider) Resources(ctx context.Context) []func() resource.Resource {
if p == nil || p.ResourcesMethod == nil {
return nil
}

return p.ResourcesMethod(ctx)
}
74 changes: 74 additions & 0 deletions internal/testing/testprovider/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package testprovider

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/resource"
)

var _ resource.Resource = &Resource{}

// Resource is declarative resource.Resource for unit testing.
type Resource struct {
// Resource interface methods
MetadataMethod func(context.Context, resource.MetadataRequest, *resource.MetadataResponse)
SchemaMethod func(context.Context, resource.SchemaRequest, *resource.SchemaResponse)
CreateMethod func(context.Context, resource.CreateRequest, *resource.CreateResponse)
DeleteMethod func(context.Context, resource.DeleteRequest, *resource.DeleteResponse)
ReadMethod func(context.Context, resource.ReadRequest, *resource.ReadResponse)
UpdateMethod func(context.Context, resource.UpdateRequest, *resource.UpdateResponse)
}

// Metadata satisfies the resource.Resource interface.
func (r *Resource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
if r.MetadataMethod == nil {
return
}

r.MetadataMethod(ctx, req, resp)
}

// Schema satisfies the resource.Resource interface.
func (r *Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
if r.SchemaMethod == nil {
return
}

r.SchemaMethod(ctx, req, resp)
}

// Create satisfies the resource.Resource interface.
func (r *Resource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
if r.CreateMethod == nil {
return
}

r.CreateMethod(ctx, req, resp)
}

// Delete satisfies the resource.Resource interface.
func (r *Resource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
if r.DeleteMethod == nil {
return
}

r.DeleteMethod(ctx, req, resp)
}

// Read satisfies the resource.Resource interface.
func (r *Resource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
if r.ReadMethod == nil {
return
}

r.ReadMethod(ctx, req, resp)
}

// Update satisfies the resource.Resource interface.
func (r *Resource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
if r.UpdateMethod == nil {
return
}

r.UpdateMethod(ctx, req, resp)
}

0 comments on commit 021c2e8

Please sign in to comment.