github.com/greenpau/go-identity@v1.1.6/internal/tag/tag_test.go (about) 1 // Copyright 2020 Paul Greenberg greenpau@outlook.com 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tag 16 17 import ( 18 "bufio" 19 "fmt" 20 "github.com/greenpau/go-identity" 21 "github.com/greenpau/go-identity/internal/tests" 22 "github.com/greenpau/go-identity/pkg/qr" 23 "github.com/greenpau/go-identity/pkg/requests" 24 "os" 25 "path/filepath" 26 "strings" 27 "testing" 28 ) 29 30 func TestTagCompliance(t *testing.T) { 31 testcases := []struct { 32 name string 33 entry interface{} 34 opts *Options 35 shouldErr bool 36 err error 37 }{ 38 { 39 name: "test public key", 40 entry: &identity.PublicKey{}, 41 }, 42 { 43 name: "test AttestationObject struct", 44 entry: &identity.AttestationObject{}, 45 opts: &Options{ 46 DisableTagMismatch: true, 47 }, 48 }, 49 { 50 name: "test AttestationStatement struct", 51 entry: &identity.AttestationStatement{}, 52 opts: &Options{ 53 DisableTagMismatch: true, 54 }, 55 }, 56 { 57 name: "test AuthData struct", 58 entry: &identity.AuthData{}, 59 opts: &Options{ 60 DisableTagMismatch: true, 61 }, 62 }, 63 { 64 name: "test ClientData struct", 65 entry: &identity.ClientData{}, 66 opts: &Options{ 67 DisableTagMismatch: true, 68 }, 69 }, 70 { 71 name: "test CredentialData struct", 72 entry: &identity.CredentialData{}, 73 opts: &Options{ 74 DisableTagMismatch: true, 75 }, 76 }, 77 { 78 name: "test CreditCard struct", 79 entry: &identity.CreditCard{}, 80 }, 81 { 82 name: "test CreditCardAssociation struct", 83 entry: &identity.CreditCardAssociation{}, 84 }, 85 { 86 name: "test CreditCardIssuer struct", 87 entry: &identity.CreditCardIssuer{}, 88 }, 89 { 90 name: "test Database struct", 91 entry: &identity.Database{}, 92 }, 93 { 94 name: "test Device struct", 95 entry: &identity.Device{}, 96 }, 97 { 98 name: "test EmailAddress struct", 99 entry: &identity.EmailAddress{}, 100 }, 101 { 102 name: "test Handle struct", 103 entry: &identity.Handle{}, 104 }, 105 { 106 name: "test Image struct", 107 entry: &identity.Image{}, 108 }, 109 { 110 name: "test Location struct", 111 entry: &identity.Location{}, 112 }, 113 { 114 name: "test LockoutState struct", 115 entry: &identity.LockoutState{}, 116 }, 117 { 118 name: "test MfaDevice struct", 119 entry: &identity.MfaDevice{}, 120 }, 121 { 122 name: "test MfaToken struct", 123 entry: &identity.MfaToken{}, 124 }, 125 { 126 name: "test MfaTokenBundle struct", 127 entry: &identity.MfaTokenBundle{}, 128 }, 129 { 130 name: "test Name struct", 131 entry: &identity.Name{}, 132 }, 133 { 134 name: "test Organization struct", 135 entry: &identity.Organization{}, 136 }, 137 { 138 name: "test Password struct", 139 entry: &identity.Password{}, 140 }, 141 { 142 name: "test PublicKey struct", 143 entry: &identity.PublicKey{}, 144 }, 145 { 146 name: "test PublicKeyBundle struct", 147 entry: &identity.PublicKeyBundle{}, 148 }, 149 { 150 name: "test Registration struct", 151 entry: &identity.Registration{}, 152 }, 153 { 154 name: "test Request struct", 155 entry: &requests.Request{}, 156 }, 157 { 158 name: "test Role struct", 159 entry: &identity.Role{}, 160 }, 161 { 162 name: "test User struct", 163 entry: &identity.User{}, 164 }, 165 { 166 name: "test Policy struct", 167 entry: &identity.Policy{}, 168 }, 169 { 170 name: "test UserPolicy struct", 171 entry: &identity.UserPolicy{}, 172 opts: &Options{ 173 DisableTagOnEmpty: true, 174 }, 175 }, 176 { 177 name: "test PasswordPolicy struct", 178 entry: &identity.PasswordPolicy{}, 179 opts: &Options{ 180 DisableTagOnEmpty: true, 181 }, 182 }, 183 { 184 name: "test WebAuthnRegisterRequest struct", 185 entry: &identity.WebAuthnRegisterRequest{}, 186 opts: &Options{ 187 DisableTagMismatch: true, 188 }, 189 }, 190 { 191 name: "test requests.User struct", 192 entry: &requests.User{}, 193 opts: &Options{}, 194 }, 195 { 196 name: "test requests.WebAuthn struct", 197 entry: &requests.WebAuthn{}, 198 opts: &Options{}, 199 }, 200 { 201 name: "test requests.Key struct", 202 entry: &requests.Key{}, 203 opts: &Options{}, 204 }, 205 { 206 name: "test requests.MfaToken struct", 207 entry: &requests.MfaToken{}, 208 opts: &Options{}, 209 }, 210 { 211 name: "test requests.Flags struct", 212 entry: &requests.Flags{}, 213 opts: &Options{}, 214 }, 215 { 216 name: "test identity.UserMetadata struct", 217 entry: &identity.UserMetadata{}, 218 opts: &Options{}, 219 }, 220 { 221 name: "test requests.Query struct", 222 entry: &requests.Query{}, 223 opts: &Options{}, 224 }, 225 { 226 name: "test identity.UserMetadataBundle struct", 227 entry: &identity.UserMetadataBundle{}, 228 opts: &Options{}, 229 }, 230 { 231 name: "test requests.Response struct", 232 entry: &requests.Response{}, 233 opts: &Options{}, 234 }, 235 { 236 name: "test requests.Upstream struct", 237 entry: &requests.Upstream{}, 238 opts: &Options{}, 239 }, 240 { 241 name: "test requests.Sandbox struct", 242 entry: &requests.Sandbox{}, 243 opts: &Options{}, 244 }, 245 { 246 name: "test qr.Code struct", 247 entry: &qr.Code{}, 248 opts: &Options{}, 249 }, 250 { 251 name: "test identity.WebAuthnAuthenticateRequest struct", 252 entry: &identity.WebAuthnAuthenticateRequest{}, 253 opts: &Options{}, 254 }, 255 { 256 name: "test identity.APIKeyBundle struct", 257 entry: &identity.APIKeyBundle{}, 258 opts: &Options{}, 259 }, 260 { 261 name: "test identity.APIKey struct", 262 entry: &identity.APIKey{}, 263 opts: &Options{}, 264 }, 265 } 266 267 for _, tc := range testcases { 268 t.Run(tc.name, func(t *testing.T) { 269 msgs, err := GetTagCompliance(tc.entry, tc.opts) 270 if tests.EvalErrWithLog(t, err, nil, tc.shouldErr, tc.err, msgs) { 271 return 272 } 273 }) 274 } 275 } 276 277 func TestStructTagCompliance(t *testing.T) { 278 var files []string 279 structMap := make(map[string]bool) 280 walkFn := func(path string, fileInfo os.FileInfo, err error) error { 281 if err != nil { 282 return err 283 } 284 if fileInfo.IsDir() { 285 return nil 286 } 287 fileName := filepath.Base(path) 288 fileExt := filepath.Ext(fileName) 289 if fileExt != ".go" { 290 return nil 291 } 292 if strings.Contains(fileName, "_test.go") { 293 return nil 294 } 295 if strings.Contains(path, "/tag/") || strings.Contains(path, "/errors/") { 296 return nil 297 } 298 // t.Logf("%s %d", path, fileInfo.Size()) 299 files = append(files, path) 300 return nil 301 } 302 if err := filepath.Walk("../../", walkFn); err != nil { 303 t.Error(err) 304 } 305 306 for _, fp := range files { 307 // t.Logf("file %s", fp) 308 var pkgFound bool 309 var pkgName string 310 fh, _ := os.Open(fp) 311 defer fh.Close() 312 scanner := bufio.NewScanner(fh) 313 for scanner.Scan() { 314 line := strings.TrimSpace(scanner.Text()) 315 if strings.HasPrefix(line, "package ") { 316 pkgFound = true 317 pkgName = strings.Split(line, " ")[1] 318 // t.Logf("package %s", pkgName) 319 continue 320 } 321 if !pkgFound { 322 continue 323 } 324 if strings.HasPrefix(line, "type") && strings.Contains(line, "struct") { 325 structName := strings.Split(line, " ")[1] 326 // t.Logf("%s.%s", pkgName, structName) 327 structMap[pkgName+"."+structName] = false 328 } 329 330 //fmt.Println(scanner.Text()) 331 } 332 if err := scanner.Err(); err != nil { 333 t.Errorf("failed reading %q: %v", fp, err) 334 } 335 } 336 337 fp := "../../internal/tag/tag_test.go" 338 fh, _ := os.Open(fp) 339 defer fh.Close() 340 scanner := bufio.NewScanner(fh) 341 for scanner.Scan() { 342 line := strings.TrimSpace(scanner.Text()) 343 for k := range structMap { 344 if strings.Contains(line, k+"{}") { 345 structMap[k] = true 346 } 347 } 348 } 349 if err := scanner.Err(); err != nil { 350 t.Errorf("failed reading %q: %v", fp, err) 351 } 352 353 if len(structMap) > 0 { 354 var msgs []string 355 for k, v := range structMap { 356 if v == false { 357 t.Logf("Found struct %s", k) 358 msgs = append(msgs, fmt.Sprintf("{\nname: \"test %s struct\",\nentry: &%s{},\nopts: &Options{},\n},", k, k)) 359 } 360 } 361 if len(msgs) > 0 { 362 t.Logf("Add the following tests:\n" + strings.Join(msgs, "\n")) 363 t.Fatal("Fix above structs") 364 } 365 } 366 }