@@ -19,6 +19,8 @@ import (
1919 "encoding/json"
2020 "fmt"
2121 "io"
22+ "os"
23+ "sort"
2224 "testing"
2325 "text/template"
2426
@@ -33,9 +35,12 @@ import (
3335 "github.com/stretchr/testify/assert"
3436 "github.com/stretchr/testify/require"
3537
38+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
3639 bridgetesting "github.com/pulumi/pulumi-terraform-bridge/v3/internal/testing"
3740 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge"
41+ "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info"
3842 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfgen/internal/testprovider"
43+ sdkv2 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2"
3944 "github.com/pulumi/pulumi-terraform-bridge/v3/unstable/metadata"
4045 "github.com/pulumi/pulumi-terraform-bridge/x/muxer"
4146)
@@ -116,6 +121,159 @@ func TestCSharpMiniRandom(t *testing.T) {
116121 bridgetesting .AssertEqualsJSONFile (t , "test_data/minirandom-schema-csharp.json" , schema )
117122}
118123
124+ // Test the ability to force type sharing. Some of the upstream providers generate very large concrete schemata by in
125+ // Go, with TF not being materially affected. The example is inspired by QuickSight types in AWS. In Pulumi the default
126+ // projection is going to generate named types for every instance of the shared schema. This may lead to SDK bloat. Test
127+ // the ability of the provider author to curb the bloat and force an explit sharing.
128+ func TestTypeSharing (t * testing.T ) {
129+ tmpdir := t .TempDir ()
130+ barCharVisualSchema := func () * schema.Schema {
131+ return & schema.Schema {
132+ Type : schema .TypeList ,
133+ Optional : true ,
134+ MinItems : 1 ,
135+ MaxItems : 1 ,
136+ Elem : & schema.Resource {
137+ Schema : map [string ]* schema.Schema {
138+ "nest" : {
139+ Type : schema .TypeList ,
140+ MaxItems : 1 ,
141+ Optional : true ,
142+ Elem : & schema.Resource {
143+ Schema : map [string ]* schema.Schema {
144+ "nested_prop" : {
145+ Type : schema .TypeBool ,
146+ Optional : true ,
147+ },
148+ },
149+ },
150+ },
151+ },
152+ },
153+ }
154+ }
155+ visualsSchema := func () * schema.Schema {
156+ return & schema.Schema {
157+ Type : schema .TypeList ,
158+ MinItems : 1 ,
159+ MaxItems : 50 ,
160+ Optional : true ,
161+ Elem : & schema.Resource {
162+ Schema : map [string ]* schema.Schema {
163+ "bar_chart_visual" : barCharVisualSchema (),
164+ "box_plot_visual" : barCharVisualSchema (),
165+ },
166+ },
167+ }
168+ }
169+ provider := info.Provider {
170+ Name : "testprov" ,
171+ P : sdkv2 .NewProvider (& schema.Provider {
172+ ResourcesMap : map [string ]* schema.Resource {
173+ "testprov_r1" : {
174+ Schema : map [string ]* schema.Schema {
175+ "sheets" : {
176+ Type : schema .TypeList ,
177+ MinItems : 1 ,
178+ MaxItems : 20 ,
179+ Optional : true ,
180+ Elem : & schema.Resource {
181+ Schema : map [string ]* schema.Schema {
182+ "visuals" : visualsSchema (),
183+ },
184+ },
185+ },
186+ },
187+ },
188+ "testprov_r2" : {
189+ Schema : map [string ]* schema.Schema {
190+ "x" : {
191+ Type : schema .TypeInt ,
192+ Optional : true ,
193+ },
194+ "sheets" : {
195+ Type : schema .TypeList ,
196+ MinItems : 1 ,
197+ MaxItems : 20 ,
198+ Optional : true ,
199+ Elem : & schema.Resource {
200+ Schema : map [string ]* schema.Schema {
201+ "y" : {
202+ Type : schema .TypeBool ,
203+ Optional : true ,
204+ },
205+ "visuals" : visualsSchema (),
206+ },
207+ },
208+ },
209+ },
210+ },
211+ },
212+ }),
213+ UpstreamRepoPath : tmpdir ,
214+ Resources : map [string ]* info.Resource {
215+ "testprov_r1" : {
216+ Tok : "testprov:index:R1" ,
217+ Fields : map [string ]* info.Schema {
218+ "sheets" : {
219+ Elem : & info.Schema {
220+ Fields : map [string ]* info.Schema {
221+ "visuals" : {
222+ Elem : & info.Schema {
223+ TypePrefixOverride : tfbridge .StringRef ("" ),
224+ },
225+ },
226+ },
227+ },
228+ },
229+ },
230+ },
231+ "testprov_r2" : {
232+ Tok : "testprov:index:R2" ,
233+ Fields : map [string ]* info.Schema {
234+ "sheets" : {
235+ Elem : & info.Schema {
236+ Fields : map [string ]* info.Schema {
237+ "visuals" : {
238+ Elem : & info.Schema {
239+ Type : "testprov:index/Visual:Visual" ,
240+ OmitType : true ,
241+ },
242+ },
243+ },
244+ },
245+ },
246+ },
247+ },
248+ },
249+ }
250+ schema , err := GenerateSchema (provider , diag .DefaultSink (os .Stdout , os .Stdout , diag.FormatOptions {
251+ Color : colors .Never ,
252+ }))
253+ require .NoError (t , err )
254+
255+ keys := []string {}
256+ for k := range schema .Types {
257+ keys = append (keys , string (k ))
258+ }
259+ sort .Strings (keys )
260+
261+ // Note that there is only one set of helper types, and they are not prefixed by any of the resource names.
262+ autogold .Expect ([]string {
263+ "testprov:index/R1Sheet:R1Sheet" , "testprov:index/R2Sheet:R2Sheet" ,
264+ "testprov:index/Visual:Visual" ,
265+ "testprov:index/VisualBarChartVisual:VisualBarChartVisual" ,
266+ "testprov:index/VisualBarChartVisualNest:VisualBarChartVisualNest" ,
267+ "testprov:index/VisualBoxPlotVisual:VisualBoxPlotVisual" ,
268+ "testprov:index/VisualBoxPlotVisualNest:VisualBoxPlotVisualNest" ,
269+ }).Equal (t , keys )
270+
271+ bytes , err := json .MarshalIndent (schema , "" , " " )
272+ require .NoError (t , err )
273+
274+ autogold .ExpectFile (t , autogold .Raw (string (bytes )))
275+ }
276+
119277// TestPropertyDocumentationEdits tests that documentation edits are applied to
120278// individual properties. This includes both the property description and
121279// deprecation message. This tests the following workflow
0 commit comments