github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/enumFieldNamesPrefixRule_test.go (about)

     1  package rules_test
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/yoheimuta/protolint/internal/addon/rules"
     8  
     9  	"github.com/yoheimuta/go-protoparser/v4/parser"
    10  	"github.com/yoheimuta/go-protoparser/v4/parser/meta"
    11  	"github.com/yoheimuta/protolint/linter/autodisable"
    12  	"github.com/yoheimuta/protolint/linter/report"
    13  	"github.com/yoheimuta/protolint/linter/rule"
    14  )
    15  
    16  func TestEnumFieldNamesPrefixRule_Apply(t *testing.T) {
    17  	tests := []struct {
    18  		name         string
    19  		inputProto   *parser.Proto
    20  		wantFailures []report.Failure
    21  	}{
    22  		{
    23  			name: "no failures for proto without enum fields",
    24  			inputProto: &parser.Proto{
    25  				ProtoBody: []parser.Visitee{
    26  					&parser.Enum{
    27  						EnumName: "FooBar",
    28  					},
    29  				},
    30  			},
    31  		},
    32  		{
    33  			name: "no failures for proto with valid enum field names",
    34  			inputProto: &parser.Proto{
    35  				ProtoBody: []parser.Visitee{
    36  					&parser.Service{},
    37  					&parser.Enum{
    38  						EnumName: "FooBar",
    39  						EnumBody: []parser.Visitee{
    40  							&parser.EnumField{
    41  								Ident:  "FOO_BAR_UNSPECIFIED",
    42  								Number: "0",
    43  							},
    44  							&parser.EnumField{
    45  								Ident:  "FOO_BAR_FIRST_VALUE",
    46  								Number: "1",
    47  							},
    48  							&parser.EnumField{
    49  								Ident:  "FOO_BAR_SECOND_VALUE",
    50  								Number: "2",
    51  							},
    52  						},
    53  					},
    54  				},
    55  			},
    56  		},
    57  		{
    58  			name: "no failures for proto with valid enum field names even when its enum name is snake case",
    59  			inputProto: &parser.Proto{
    60  				ProtoBody: []parser.Visitee{
    61  					&parser.Service{},
    62  					&parser.Enum{
    63  						EnumName: "foo_bar",
    64  						EnumBody: []parser.Visitee{
    65  							&parser.EnumField{
    66  								Ident:  "FOO_BAR_UNSPECIFIED",
    67  								Number: "0",
    68  							},
    69  						},
    70  					},
    71  				},
    72  			},
    73  		},
    74  		{
    75  			name: "no failures for proto with valid enum field names even when its camel-case string starts with a 2-letter abbreviation",
    76  			inputProto: &parser.Proto{
    77  				ProtoBody: []parser.Visitee{
    78  					&parser.Service{},
    79  					&parser.Enum{
    80  						EnumName: "ITDepartmentRegion",
    81  						EnumBody: []parser.Visitee{
    82  							&parser.EnumField{
    83  								Ident:  "IT_DEPARTMENT_REGION_UNSPECIFIED",
    84  								Number: "0",
    85  							},
    86  						},
    87  					},
    88  				},
    89  			},
    90  		},
    91  		{
    92  			name: "no failures for proto with valid enum field names even when its camel-case string includes OAuth",
    93  			inputProto: &parser.Proto{
    94  				ProtoBody: []parser.Visitee{
    95  					&parser.Service{},
    96  					&parser.Enum{
    97  						EnumName: "ListAccountPipedriveOAuthsEnabledFilter",
    98  						EnumBody: []parser.Visitee{
    99  							&parser.EnumField{
   100  								Ident:  "LIST_ACCOUNT_PIPEDRIVE_OAUTHS_ENABLED_FILTER_UNSPECIFIED",
   101  								Number: "0",
   102  							},
   103  						},
   104  					},
   105  				},
   106  			},
   107  		},
   108  		{
   109  			name: "failures for proto with invalid enum field names",
   110  			inputProto: &parser.Proto{
   111  				ProtoBody: []parser.Visitee{
   112  					&parser.Enum{
   113  						EnumName: "FooBar",
   114  						EnumBody: []parser.Visitee{
   115  							&parser.EnumField{
   116  								Ident:  "BAR_UNSPECIFIED",
   117  								Number: "0",
   118  								Meta: meta.Meta{
   119  									Pos: meta.Position{
   120  										Filename: "example.proto",
   121  										Offset:   100,
   122  										Line:     5,
   123  										Column:   10,
   124  									},
   125  								},
   126  							},
   127  						},
   128  					},
   129  				},
   130  			},
   131  			wantFailures: []report.Failure{
   132  				report.Failuref(
   133  					meta.Position{
   134  						Filename: "example.proto",
   135  						Offset:   100,
   136  						Line:     5,
   137  						Column:   10,
   138  					},
   139  					"ENUM_FIELD_NAMES_PREFIX",
   140  					`EnumField name "BAR_UNSPECIFIED" should have the prefix "FOO_BAR"`,
   141  				),
   142  			},
   143  		},
   144  	}
   145  
   146  	for _, test := range tests {
   147  		test := test
   148  		t.Run(test.name, func(t *testing.T) {
   149  			rule := rules.NewEnumFieldNamesPrefixRule(rule.SeverityError, false, autodisable.Noop)
   150  
   151  			got, err := rule.Apply(test.inputProto)
   152  			if err != nil {
   153  				t.Errorf("got err %v, but want nil", err)
   154  				return
   155  			}
   156  			if !reflect.DeepEqual(got, test.wantFailures) {
   157  				t.Errorf("got %v, but want %v", got, test.wantFailures)
   158  			}
   159  		})
   160  	}
   161  }
   162  
   163  func TestEnumFieldNamesPrefixRule_Apply_fix(t *testing.T) {
   164  	tests := []struct {
   165  		name          string
   166  		inputFilename string
   167  		wantFilename  string
   168  	}{
   169  		{
   170  			name:          "no fix for a correct proto",
   171  			inputFilename: "prefix.proto",
   172  			wantFilename:  "prefix.proto",
   173  		},
   174  		{
   175  			name:          "fix for an incorrect proto",
   176  			inputFilename: "invalid.proto",
   177  			wantFilename:  "prefix.proto",
   178  		},
   179  	}
   180  
   181  	for _, test := range tests {
   182  		test := test
   183  		t.Run(test.name, func(t *testing.T) {
   184  			r := rules.NewEnumFieldNamesPrefixRule(rule.SeverityError, true, autodisable.Noop)
   185  			testApplyFix(t, r, test.inputFilename, test.wantFilename)
   186  		})
   187  	}
   188  }
   189  
   190  func TestEnumFieldNamesPrefixRule_Apply_disable(t *testing.T) {
   191  	tests := []struct {
   192  		name               string
   193  		inputFilename      string
   194  		inputPlacementType autodisable.PlacementType
   195  		wantFilename       string
   196  	}{
   197  		{
   198  			name:          "do nothing in case of no violations",
   199  			inputFilename: "prefix.proto",
   200  			wantFilename:  "prefix.proto",
   201  		},
   202  		{
   203  			name:               "insert disable:next comments",
   204  			inputFilename:      "invalid.proto",
   205  			inputPlacementType: autodisable.Next,
   206  			wantFilename:       "disable_next.proto",
   207  		},
   208  		{
   209  			name:               "insert disable:this comments",
   210  			inputFilename:      "invalid.proto",
   211  			inputPlacementType: autodisable.ThisThenNext,
   212  			wantFilename:       "disable_this.proto",
   213  		},
   214  	}
   215  
   216  	for _, test := range tests {
   217  		test := test
   218  		t.Run(test.name, func(t *testing.T) {
   219  			r := rules.NewEnumFieldNamesPrefixRule(rule.SeverityError, true, test.inputPlacementType)
   220  			testApplyFix(t, r, test.inputFilename, test.wantFilename)
   221  		})
   222  	}
   223  }