@@ -2,19 +2,28 @@ package acctest_test
2
2
3
3
import (
4
4
"encoding/json"
5
+ "errors"
5
6
"fmt"
7
+ "go/ast"
8
+ "go/parser"
9
+ "go/token"
6
10
"io/fs"
7
11
"net/http"
12
+ "os"
8
13
"path/filepath"
14
+ "sort"
9
15
"strings"
10
16
"testing"
11
17
18
+ "github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest"
12
19
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/mnq"
13
20
"github.com/stretchr/testify/assert"
14
21
"github.com/stretchr/testify/require"
15
22
"gopkg.in/dnaeon/go-vcr.v3/cassette"
16
23
)
17
24
25
+ const servicesDir = "../services"
26
+
18
27
func exceptionsCassettesCases () map [string ]struct {} {
19
28
return map [string ]struct {}{
20
29
"../services/mnq/testdata/sns-topic-basic.cassette.yaml" : {},
@@ -35,16 +44,17 @@ func exceptionsCassettesCases() map[string]struct{} {
35
44
}
36
45
37
46
// getTestFiles returns a map of cassettes files
38
- func getTestFiles () (map [string ]struct {}, error ) {
47
+ func getTestFiles (includeExceptions bool ) (map [string ]struct {}, error ) {
39
48
filesMap := make (map [string ]struct {})
40
49
exceptions := exceptionsCassettesCases ()
41
50
42
- err := filepath .WalkDir ("../services" , func (path string , _ fs.DirEntry , _ error ) error {
51
+ err := filepath .WalkDir (servicesDir , func (path string , _ fs.DirEntry , _ error ) error {
43
52
isCassette := strings .Contains (path , "cassette" )
44
- _ , isException := exceptions [path ]
45
-
46
- if isCassette && ! isException {
47
- filesMap [fileNameWithoutExtSuffix (path )] = struct {}{}
53
+ if isCassette {
54
+ _ , isException := exceptions [path ]
55
+ if ! isException || includeExceptions {
56
+ filesMap [fileNameWithoutExtSuffix (path )] = struct {}{}
57
+ }
48
58
}
49
59
50
60
return nil
@@ -57,7 +67,7 @@ func getTestFiles() (map[string]struct{}, error) {
57
67
}
58
68
59
69
func TestAccCassettes_Validator (t * testing.T ) {
60
- paths , err := getTestFiles ()
70
+ paths , err := getTestFiles (false )
61
71
require .NoError (t , err )
62
72
63
73
for path := range paths {
@@ -129,3 +139,71 @@ func isTransientStateError(i *cassette.Interaction) bool {
129
139
130
140
return scwError .Type == "transient_state"
131
141
}
142
+
143
+ func listAccTestFunctions () (map [string ]string , error ) {
144
+ fset := token .NewFileSet ()
145
+ testFuncs := map [string ]string {}
146
+
147
+ filepath .Walk (servicesDir , func (path string , info os.FileInfo , err error ) error {
148
+ if err != nil || info .IsDir () || ! strings .HasSuffix (info .Name (), "_test.go" ) {
149
+ return nil
150
+ }
151
+
152
+ pkgFolder := filepath .Base (filepath .Dir (path ))
153
+
154
+ node , err := parser .ParseFile (fset , path , nil , 0 )
155
+ if err != nil {
156
+ return err
157
+ }
158
+
159
+ for _ , decl := range node .Decls {
160
+ if fn , ok := decl .(* ast.FuncDecl ); ok {
161
+ if strings .HasPrefix (fn .Name .Name , "Test" ) && fn .Name .Name != "TestMain" && fn .Recv == nil {
162
+ expectedCassettePath := fmt .Sprintf ("%s/%s" , servicesDir , acctest .BuildCassetteName (fn .Name .Name , pkgFolder , ".cassette" ))
163
+ testFuncs [expectedCassettePath ] = fmt .Sprintf ("%s/%s" , pkgFolder , fn .Name .Name )
164
+ }
165
+ }
166
+ }
167
+
168
+ return nil
169
+ })
170
+
171
+ return testFuncs , nil
172
+ }
173
+
174
+ func TestAccCassettes_CheckOrphans (t * testing.T ) {
175
+ // List actual cassettes
176
+ actualCassettesPaths , err := getTestFiles (true )
177
+ require .NoError (t , err )
178
+
179
+ // List actual acceptance tests functions and their expected cassettes' paths
180
+ expectedCassettesPaths , err := listAccTestFunctions ()
181
+ if err != nil {
182
+ t .Fatalf ("Failed to list acceptance tests: %v" , err )
183
+ }
184
+
185
+ // Look for tests with no matching cassette
186
+ testWithNoCassetteErrs := []string (nil )
187
+ for expectedCassettePath , testName := range expectedCassettesPaths {
188
+ if _ , ok := actualCassettesPaths [expectedCassettePath ]; ! ok {
189
+ testWithNoCassetteErrs = append (testWithNoCassetteErrs , fmt .Sprintf ("- %s has no matching cassette" , testName ))
190
+ }
191
+ }
192
+ sort .Strings (testWithNoCassetteErrs )
193
+ t .Log ("WARNING:\n " , strings .Join (testWithNoCassetteErrs , "\n " ))
194
+
195
+ // Look for cassettes with no matching test
196
+ cassetteWithNoTestErrs := []error (nil )
197
+ for actualCassettePath := range actualCassettesPaths {
198
+ if _ , ok := expectedCassettesPaths [actualCassettePath ]; ! ok {
199
+ cassetteWithNoTestErrs = append (cassetteWithNoTestErrs , fmt .Errorf ("+ cassette [%s] has no matching test" , actualCassettePath ))
200
+ }
201
+ }
202
+
203
+ if len (cassetteWithNoTestErrs ) > 0 {
204
+ sort .Slice (cassetteWithNoTestErrs , func (i , j int ) bool {
205
+ return cassetteWithNoTestErrs [i ].Error () < cassetteWithNoTestErrs [j ].Error ()
206
+ })
207
+ t .Error (errors .Join (cassetteWithNoTestErrs ... ))
208
+ }
209
+ }
0 commit comments