Skip to content

Commit 389ffc5

Browse files
authored
internal: Implement fwserver ReadDataSource testing and update proto6server testing (#359)
Reference: #215 This also changes a potential panic into an error where the incoming Config is missing, which was discovered via the new unit testing. Terraform always fills in this data currently, so it does not warrant any CHANGELOG entry, but is good from a defensive coding standpoint.
1 parent f005166 commit 389ffc5

9 files changed

+458
-373
lines changed

internal/fromproto6/readdatasource.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,23 @@ func ReadDataSourceRequest(ctx context.Context, proto6 *tfprotov6.ReadDataSource
1818

1919
var diags diag.Diagnostics
2020

21+
// Panic prevention here to simplify the calling implementations.
22+
// This should not happen, but just in case.
23+
if dataSourceSchema == nil {
24+
diags.AddError(
25+
"Missing DataSource Schema",
26+
"An unexpected error was encountered when handling the request. "+
27+
"This is always an issue in the Terraform Provider SDK used to implement the provider and should be reported to the provider developers.\n\n"+
28+
"Please report this to the provider developer:\n\n"+
29+
"Missing schema.",
30+
)
31+
32+
return nil, diags
33+
}
34+
2135
fw := &fwserver.ReadDataSourceRequest{
22-
DataSourceType: dataSourceType,
36+
DataSourceSchema: *dataSourceSchema,
37+
DataSourceType: dataSourceType,
2338
}
2439

2540
config, configDiags := Config(ctx, proto6.Config, dataSourceSchema)

internal/fromproto6/readdatasource_test.go

+20-4
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,26 @@ func TestReadDataSourceRequest(t *testing.T) {
5656
},
5757
"empty": {
5858
input: &tfprotov6.ReadDataSourceRequest{},
59-
expected: &fwserver.ReadDataSourceRequest{},
59+
expected: nil,
60+
expectedDiagnostics: diag.Diagnostics{
61+
diag.NewErrorDiagnostic(
62+
"Missing DataSource Schema",
63+
"An unexpected error was encountered when handling the request. "+
64+
"This is always an issue in the Terraform Provider SDK used to implement the provider and should be reported to the provider developers.\n\n"+
65+
"Please report this to the provider developer:\n\n"+
66+
"Missing schema.",
67+
),
68+
},
6069
},
6170
"config-missing-schema": {
6271
input: &tfprotov6.ReadDataSourceRequest{
6372
Config: &testProto6DynamicValue,
6473
},
65-
expected: &fwserver.ReadDataSourceRequest{},
74+
expected: nil,
6675
expectedDiagnostics: diag.Diagnostics{
6776
diag.NewErrorDiagnostic(
68-
"Unable to Convert Configuration",
69-
"An unexpected error was encountered when converting the configuration from the protocol type. "+
77+
"Missing DataSource Schema",
78+
"An unexpected error was encountered when handling the request. "+
7079
"This is always an issue in the Terraform Provider SDK used to implement the provider and should be reported to the provider developers.\n\n"+
7180
"Please report this to the provider developer:\n\n"+
7281
"Missing schema.",
@@ -83,12 +92,15 @@ func TestReadDataSourceRequest(t *testing.T) {
8392
Raw: testProto6Value,
8493
Schema: *testFwSchema,
8594
},
95+
DataSourceSchema: *testFwSchema,
8696
},
8797
},
8898
"providermeta-missing-data": {
8999
input: &tfprotov6.ReadDataSourceRequest{},
100+
dataSourceSchema: testFwSchema,
90101
providerMetaSchema: testFwSchema,
91102
expected: &fwserver.ReadDataSourceRequest{
103+
DataSourceSchema: *testFwSchema,
92104
ProviderMeta: &tfsdk.Config{
93105
Raw: tftypes.NewValue(testProto6Type, nil),
94106
Schema: *testFwSchema,
@@ -99,16 +111,20 @@ func TestReadDataSourceRequest(t *testing.T) {
99111
input: &tfprotov6.ReadDataSourceRequest{
100112
ProviderMeta: &testProto6DynamicValue,
101113
},
114+
dataSourceSchema: testFwSchema,
102115
expected: &fwserver.ReadDataSourceRequest{
116+
DataSourceSchema: *testFwSchema,
103117
// This intentionally should not include ProviderMeta
104118
},
105119
},
106120
"providermeta": {
107121
input: &tfprotov6.ReadDataSourceRequest{
108122
ProviderMeta: &testProto6DynamicValue,
109123
},
124+
dataSourceSchema: testFwSchema,
110125
providerMetaSchema: testFwSchema,
111126
expected: &fwserver.ReadDataSourceRequest{
127+
DataSourceSchema: *testFwSchema,
112128
ProviderMeta: &tfsdk.Config{
113129
Raw: testProto6Value,
114130
Schema: *testFwSchema,

internal/fwserver/server_readdatasource.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import (
1111
// ReadDataSourceRequest is the framework server request for the
1212
// ReadDataSource RPC.
1313
type ReadDataSourceRequest struct {
14-
Config *tfsdk.Config
15-
DataSourceType tfsdk.DataSourceType
16-
ProviderMeta *tfsdk.Config
14+
Config *tfsdk.Config
15+
DataSourceSchema tfsdk.Schema
16+
DataSourceType tfsdk.DataSourceType
17+
ProviderMeta *tfsdk.Config
1718
}
1819

1920
// ReadDataSourceResponse is the framework server response for the
@@ -40,10 +41,14 @@ func (s *Server) ReadDataSource(ctx context.Context, req *ReadDataSourceRequest,
4041
return
4142
}
4243

43-
readReq := tfsdk.ReadDataSourceRequest{}
44+
readReq := tfsdk.ReadDataSourceRequest{
45+
Config: tfsdk.Config{
46+
Schema: req.DataSourceSchema,
47+
},
48+
}
4449
readResp := tfsdk.ReadDataSourceResponse{
4550
State: tfsdk.State{
46-
Schema: req.Config.Schema,
51+
Schema: req.DataSourceSchema,
4752
},
4853
}
4954

internal/fwserver/server_readdatasource_test.go

+187-11
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,208 @@ import (
55
"testing"
66

77
"github.com/google/go-cmp/cmp"
8+
"github.com/hashicorp/terraform-plugin-framework/diag"
89
"github.com/hashicorp/terraform-plugin-framework/internal/fwserver"
9-
"github.com/hashicorp/terraform-plugin-framework/internal/testing/emptyprovider"
10+
"github.com/hashicorp/terraform-plugin-framework/internal/testing/testprovider"
11+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
12+
"github.com/hashicorp/terraform-plugin-framework/types"
13+
"github.com/hashicorp/terraform-plugin-go/tftypes"
1014
)
1115

12-
// TODO: Migrate tfsdk.Provider bits of proto6server.testProviderServer to
13-
// new internal/testing/provider.Provider that allows customization of all
14-
// method implementations via struct fields. Then, create additional test
15-
// cases in this unit test.
16-
//
17-
// For now this testing is covered by proto6server.ReadDataSource.
18-
//
19-
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/215
2016
func TestServerReadDataSource(t *testing.T) {
2117
t.Parallel()
2218

19+
testType := tftypes.Object{
20+
AttributeTypes: map[string]tftypes.Type{
21+
"test_computed": tftypes.String,
22+
"test_required": tftypes.String,
23+
},
24+
}
25+
26+
testConfigValue := tftypes.NewValue(testType, map[string]tftypes.Value{
27+
"test_computed": tftypes.NewValue(tftypes.String, nil),
28+
"test_required": tftypes.NewValue(tftypes.String, "test-config-value"),
29+
})
30+
31+
testStateValue := tftypes.NewValue(testType, map[string]tftypes.Value{
32+
"test_computed": tftypes.NewValue(tftypes.String, "test-state-value"),
33+
"test_required": tftypes.NewValue(tftypes.String, "test-config-value"),
34+
})
35+
36+
testSchema := tfsdk.Schema{
37+
Attributes: map[string]tfsdk.Attribute{
38+
"test_computed": {
39+
Computed: true,
40+
Type: types.StringType,
41+
},
42+
"test_required": {
43+
Required: true,
44+
Type: types.StringType,
45+
},
46+
},
47+
}
48+
49+
testConfig := &tfsdk.Config{
50+
Raw: testConfigValue,
51+
Schema: testSchema,
52+
}
53+
54+
testStateUnchanged := &tfsdk.State{
55+
Raw: testConfigValue,
56+
Schema: testSchema,
57+
}
58+
59+
testState := &tfsdk.State{
60+
Raw: testStateValue,
61+
Schema: testSchema,
62+
}
63+
2364
testCases := map[string]struct {
2465
server *fwserver.Server
2566
request *fwserver.ReadDataSourceRequest
2667
expectedResponse *fwserver.ReadDataSourceResponse
2768
}{
28-
"empty-provider": {
69+
"nil": {
2970
server: &fwserver.Server{
30-
Provider: &emptyprovider.Provider{},
71+
Provider: &testprovider.Provider{},
3172
},
3273
expectedResponse: &fwserver.ReadDataSourceResponse{},
3374
},
75+
"request-config": {
76+
server: &fwserver.Server{
77+
Provider: &testprovider.Provider{},
78+
},
79+
request: &fwserver.ReadDataSourceRequest{
80+
Config: testConfig,
81+
DataSourceSchema: testSchema,
82+
DataSourceType: &testprovider.DataSourceType{
83+
GetSchemaMethod: func(_ context.Context) (tfsdk.Schema, diag.Diagnostics) {
84+
return testSchema, nil
85+
},
86+
NewDataSourceMethod: func(_ context.Context, _ tfsdk.Provider) (tfsdk.DataSource, diag.Diagnostics) {
87+
return &testprovider.DataSource{
88+
ReadMethod: func(ctx context.Context, req tfsdk.ReadDataSourceRequest, resp *tfsdk.ReadDataSourceResponse) {
89+
var config struct {
90+
TestComputed types.String `tfsdk:"test_computed"`
91+
TestRequired types.String `tfsdk:"test_required"`
92+
}
93+
94+
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
95+
96+
if config.TestRequired.Value != "test-config-value" {
97+
resp.Diagnostics.AddError("unexpected req.Config value: %s", config.TestRequired.Value)
98+
}
99+
},
100+
}, nil
101+
},
102+
},
103+
},
104+
expectedResponse: &fwserver.ReadDataSourceResponse{
105+
State: testStateUnchanged,
106+
},
107+
},
108+
"request-providermeta": {
109+
server: &fwserver.Server{
110+
Provider: &testprovider.Provider{},
111+
},
112+
request: &fwserver.ReadDataSourceRequest{
113+
Config: testConfig,
114+
DataSourceSchema: testSchema,
115+
DataSourceType: &testprovider.DataSourceType{
116+
GetSchemaMethod: func(_ context.Context) (tfsdk.Schema, diag.Diagnostics) {
117+
return testSchema, nil
118+
},
119+
NewDataSourceMethod: func(_ context.Context, _ tfsdk.Provider) (tfsdk.DataSource, diag.Diagnostics) {
120+
return &testprovider.DataSource{
121+
ReadMethod: func(ctx context.Context, req tfsdk.ReadDataSourceRequest, resp *tfsdk.ReadDataSourceResponse) {
122+
var config struct {
123+
TestComputed types.String `tfsdk:"test_computed"`
124+
TestRequired types.String `tfsdk:"test_required"`
125+
}
126+
127+
resp.Diagnostics.Append(req.ProviderMeta.Get(ctx, &config)...)
128+
129+
if config.TestRequired.Value != "test-config-value" {
130+
resp.Diagnostics.AddError("unexpected req.ProviderMeta value: %s", config.TestRequired.Value)
131+
}
132+
},
133+
}, nil
134+
},
135+
},
136+
ProviderMeta: testConfig,
137+
},
138+
expectedResponse: &fwserver.ReadDataSourceResponse{
139+
State: testStateUnchanged,
140+
},
141+
},
142+
"response-diagnostics": {
143+
server: &fwserver.Server{
144+
Provider: &testprovider.Provider{},
145+
},
146+
request: &fwserver.ReadDataSourceRequest{
147+
Config: testConfig,
148+
DataSourceSchema: testSchema,
149+
DataSourceType: &testprovider.DataSourceType{
150+
GetSchemaMethod: func(_ context.Context) (tfsdk.Schema, diag.Diagnostics) {
151+
return testSchema, nil
152+
},
153+
NewDataSourceMethod: func(_ context.Context, _ tfsdk.Provider) (tfsdk.DataSource, diag.Diagnostics) {
154+
return &testprovider.DataSource{
155+
ReadMethod: func(ctx context.Context, req tfsdk.ReadDataSourceRequest, resp *tfsdk.ReadDataSourceResponse) {
156+
resp.Diagnostics.AddWarning("warning summary", "warning detail")
157+
resp.Diagnostics.AddError("error summary", "error detail")
158+
},
159+
}, nil
160+
},
161+
},
162+
},
163+
expectedResponse: &fwserver.ReadDataSourceResponse{
164+
Diagnostics: diag.Diagnostics{
165+
diag.NewWarningDiagnostic(
166+
"warning summary",
167+
"warning detail",
168+
),
169+
diag.NewErrorDiagnostic(
170+
"error summary",
171+
"error detail",
172+
),
173+
},
174+
State: testStateUnchanged,
175+
},
176+
},
177+
"response-state": {
178+
server: &fwserver.Server{
179+
Provider: &testprovider.Provider{},
180+
},
181+
request: &fwserver.ReadDataSourceRequest{
182+
Config: testConfig,
183+
DataSourceSchema: testSchema,
184+
DataSourceType: &testprovider.DataSourceType{
185+
GetSchemaMethod: func(_ context.Context) (tfsdk.Schema, diag.Diagnostics) {
186+
return testSchema, nil
187+
},
188+
NewDataSourceMethod: func(_ context.Context, _ tfsdk.Provider) (tfsdk.DataSource, diag.Diagnostics) {
189+
return &testprovider.DataSource{
190+
ReadMethod: func(ctx context.Context, req tfsdk.ReadDataSourceRequest, resp *tfsdk.ReadDataSourceResponse) {
191+
var data struct {
192+
TestComputed types.String `tfsdk:"test_computed"`
193+
TestRequired types.String `tfsdk:"test_required"`
194+
}
195+
196+
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
197+
198+
data.TestComputed = types.String{Value: "test-state-value"}
199+
200+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
201+
},
202+
}, nil
203+
},
204+
},
205+
},
206+
expectedResponse: &fwserver.ReadDataSourceResponse{
207+
State: testState,
208+
},
209+
},
34210
}
35211

36212
for name, testCase := range testCases {

0 commit comments

Comments
 (0)