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  }