66 "encoding/json"
77 "errors"
88 "fmt"
9- "io/ioutil"
109 "log"
1110 "math/rand"
1211 "net/http"
@@ -92,6 +91,57 @@ type ResourceFixture struct {
9291 New bool
9392}
9493
94+ // wrapper type for calling resource methords
95+ type resourceCRUD func (context.Context , * schema.ResourceData , interface {}) diag.Diagnostics
96+
97+ func (cb resourceCRUD ) before (before func (d * schema.ResourceData )) resourceCRUD {
98+ return func (ctx context.Context , d * schema.ResourceData , i interface {}) diag.Diagnostics {
99+ before (d )
100+ return cb (ctx , d , i )
101+ }
102+ }
103+
104+ func (cb resourceCRUD ) withId (id string ) resourceCRUD {
105+ return cb .before (func (d * schema.ResourceData ) {
106+ d .SetId (id )
107+ })
108+ }
109+
110+ func (f ResourceFixture ) prepareExecution () (resourceCRUD , error ) {
111+ switch {
112+ case f .Create :
113+ if f .ID != "" {
114+ return nil , fmt .Errorf ("ID is not available for Create" )
115+ }
116+ return resourceCRUD (f .Resource .CreateContext ), nil
117+ case f .Read :
118+ if f .ID == "" {
119+ return nil , fmt .Errorf ("ID must be set for Read" )
120+ }
121+ preRead := f .State
122+ f .State = nil
123+ return resourceCRUD (f .Resource .ReadContext ).before (func (d * schema.ResourceData ) {
124+ if f .New {
125+ d .MarkNewResource ()
126+ }
127+ for k , v := range preRead {
128+ d .Set (k , v )
129+ }
130+ }).withId (f .ID ), nil
131+ case f .Update :
132+ if f .ID == "" {
133+ return nil , fmt .Errorf ("ID must be set for Update" )
134+ }
135+ return resourceCRUD (f .Resource .UpdateContext ).withId (f .ID ), nil
136+ case f .Delete :
137+ if f .ID == "" {
138+ return nil , fmt .Errorf ("ID must be set for Delete" )
139+ }
140+ return resourceCRUD (f .Resource .DeleteContext ).withId (f .ID ), nil
141+ }
142+ return nil , fmt .Errorf ("no `Create|Read|Update|Delete: true` specificed" )
143+ }
144+
95145// Apply runs tests from fixture
96146func (f ResourceFixture ) Apply (t * testing.T ) (* schema.ResourceData , error ) {
97147 client , server , err := HttpFixtureClient (t , f .Fixtures )
@@ -122,70 +172,11 @@ func (f ResourceFixture) Apply(t *testing.T) (*schema.ResourceData, error) {
122172 }
123173 f .State = fixHCL (out ).(map [string ]interface {})
124174 }
125- var whatever func (d * schema.ResourceData , c interface {}) error
126- pick := func (
127- a func (* schema.ResourceData , interface {}) error ,
128- b func (context.Context , * schema.ResourceData , interface {}) diag.Diagnostics ,
129- d * schema.ResourceData , m interface {}) error {
130- if b != nil {
131- ctx := context .Background ()
132- diags := b (ctx , d , m )
133- if diags != nil {
134- return fmt .Errorf (diagsToString (diags ))
135- }
136- return nil
137- }
138- return a (d , m )
139- }
140175 resourceConfig := terraform .NewResourceConfigRaw (f .State )
141- switch {
142- case f .Create :
143- // nolint should be a bigger context-aware refactor
144- whatever = func (d * schema.ResourceData , m interface {}) error {
145- //lint:ignore SA1019 TODO - remove later
146- return pick (f .Resource .Create , f .Resource .CreateContext , d , m )
147- }
148- if f .ID != "" {
149- return nil , errors .New ("ID is not available for Create" )
150- }
151- case f .Read :
152- if f .ID == "" {
153- return nil , errors .New ("ID must be set for Read" )
154- }
155- preRead := f .State
156- f .State = nil
157- whatever = func (d * schema.ResourceData , m interface {}) error {
158- d .SetId (f .ID )
159- if f .New {
160- d .MarkNewResource ()
161- }
162- for k , v := range preRead {
163- err = d .Set (k , v )
164- assert .NoError (t , err )
165- }
166- return pick (f .Resource .Read , f .Resource .ReadContext , d , m )
167- }
168- case f .Update :
169- if f .ID == "" {
170- return nil , errors .New ("ID must be set for Update" )
171- }
172- if f .Resource .UpdateContext == nil && f .Resource .Update == nil {
173- return nil , errors .New ("resource does not support Update" )
174- }
175- whatever = func (d * schema.ResourceData , m interface {}) error {
176- d .SetId (f .ID )
177- return pick (f .Resource .Update , f .Resource .UpdateContext , d , m )
178- }
179- case f .Delete :
180- if f .ID == "" {
181- return nil , errors .New ("ID must be set for Delete" )
182- }
183- whatever = func (d * schema.ResourceData , m interface {}) error {
184- d .SetId (f .ID )
185- return pick (f .Resource .Delete , f .Resource .DeleteContext , d , m )
186- }
176+ execute , err := f .prepareExecution ()
177+ if err != nil {
178+ return nil , err
187179 }
188-
189180 if f .State != nil {
190181 diags := f .Resource .Validate (resourceConfig )
191182 if diags .HasError () {
@@ -217,9 +208,12 @@ func (f ResourceFixture) Apply(t *testing.T) (*schema.ResourceData, error) {
217208 if err != nil {
218209 return nil , err
219210 }
220- err = whatever (resourceData , client )
221- if err != nil {
222- return resourceData , err
211+ if execute != nil {
212+ // this is a bit strange, but we'll fix it later
213+ diags := execute (ctx , resourceData , client )
214+ if diags != nil {
215+ return resourceData , fmt .Errorf (diagsToString (diags ))
216+ }
223217 }
224218 if resourceData .Id () == "" && ! f .Removed {
225219 return resourceData , fmt .Errorf ("resource is not expected to be removed" )
@@ -542,7 +536,7 @@ func FirstKeyValue(t *testing.T, str, key string) string {
542536 r := regexp .MustCompile (key + `\s+=\s+"([^"]*)"` )
543537 match := r .FindStringSubmatch (str )
544538 if len (match ) != 2 {
545- t .Fatalf ("Cannot fin d %s in given string" , key )
539+ t .Fatalf ("Cannot find %s in given string" , key )
546540 }
547541 return match [1 ]
548542}
@@ -552,23 +546,6 @@ func AssertErrorStartsWith(t *testing.T, err error, message string) bool {
552546 return err != nil && assert .True (t , strings .HasPrefix (err .Error (), message ), err .Error ())
553547}
554548
555- // TestCreateTempFile ...
556- func TestCreateTempFile (t * testing.T , data string ) string {
557- tmpFile , err := ioutil .TempFile ("" , "tf-test-create-dbfs-file" )
558- if err != nil {
559- t .Fatal (err )
560- }
561- filename := tmpFile .Name ()
562-
563- err = ioutil .WriteFile (filename , []byte (data ), 0644 )
564- if err != nil {
565- os .Remove (filename )
566- t .Fatal (err )
567- }
568-
569- return filename
570- }
571-
572549// GetEnvOrSkipTest proceeds with test only with that env variable
573550func GetEnvOrSkipTest (t * testing.T , name string ) string {
574551 value := os .Getenv (name )
0 commit comments