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

     1  package rules_test
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/yoheimuta/go-protoparser/v4/parser/meta"
     8  
     9  	"github.com/yoheimuta/go-protoparser/v4/parser"
    10  
    11  	"github.com/yoheimuta/protolint/internal/addon/rules"
    12  	"github.com/yoheimuta/protolint/linter/report"
    13  	"github.com/yoheimuta/protolint/linter/rule"
    14  )
    15  
    16  func TestFieldsHaveCommentRule_Apply(t *testing.T) {
    17  	tests := []struct {
    18  		name                         string
    19  		inputProto                   *parser.Proto
    20  		inputShouldFollowGolangStyle bool
    21  		wantFailures                 []report.Failure
    22  	}{
    23  		{
    24  			name: "no failures for proto without field",
    25  			inputProto: &parser.Proto{
    26  				ProtoBody: []parser.Visitee{},
    27  			},
    28  		},
    29  		{
    30  			name: "no failures for proto including valid fields with comments",
    31  			inputProto: &parser.Proto{
    32  				ProtoBody: []parser.Visitee{
    33  					&parser.Message{
    34  						MessageBody: []parser.Visitee{
    35  							&parser.Field{
    36  								FieldName: "FieldName",
    37  								Comments: []*parser.Comment{
    38  									{
    39  										Raw: "// a field name.",
    40  									},
    41  								},
    42  							},
    43  							&parser.MapField{
    44  								MapName: "MapFieldName",
    45  								Comments: []*parser.Comment{
    46  									{
    47  										Raw: "// a map field name.",
    48  									},
    49  								},
    50  							},
    51  							&parser.Oneof{
    52  								OneofFields: []*parser.OneofField{
    53  									{
    54  										FieldName: "OneofFieldName",
    55  										Comments: []*parser.Comment{
    56  											{
    57  												Raw: "// a oneof field name.",
    58  											},
    59  										},
    60  									},
    61  								},
    62  							},
    63  							&parser.Field{
    64  								FieldName: "FieldName",
    65  								InlineComment: &parser.Comment{
    66  									Raw: "// a field name.",
    67  								},
    68  							},
    69  							&parser.MapField{
    70  								MapName: "MapFieldName",
    71  								InlineComment: &parser.Comment{
    72  									Raw: "// a map field name.",
    73  								},
    74  							},
    75  							&parser.Oneof{
    76  								OneofFields: []*parser.OneofField{
    77  									{
    78  										FieldName: "OneofFieldName",
    79  										InlineComment: &parser.Comment{
    80  											Raw: "// a oneof field name.",
    81  										},
    82  									},
    83  								},
    84  							},
    85  						},
    86  					},
    87  				},
    88  			},
    89  		},
    90  		{
    91  			name: "no failures for proto including valid fields with Golang style comments",
    92  			inputProto: &parser.Proto{
    93  				ProtoBody: []parser.Visitee{
    94  					&parser.Message{
    95  						MessageBody: []parser.Visitee{
    96  							&parser.Field{
    97  								FieldName: "FieldName",
    98  								Comments: []*parser.Comment{
    99  									{
   100  										Raw: "// FieldName is a field name.",
   101  									},
   102  								},
   103  							},
   104  							&parser.MapField{
   105  								MapName: "MapFieldName",
   106  								Comments: []*parser.Comment{
   107  									{
   108  										Raw: "// MapFieldName is a map field name.",
   109  									},
   110  								},
   111  							},
   112  							&parser.Oneof{
   113  								OneofFields: []*parser.OneofField{
   114  									{
   115  										FieldName: "OneofFieldName",
   116  										Comments: []*parser.Comment{
   117  											{
   118  												Raw: "// OneofFieldName is a oneof field name.",
   119  											},
   120  										},
   121  									},
   122  								},
   123  							},
   124  						},
   125  					},
   126  				},
   127  			},
   128  			inputShouldFollowGolangStyle: true,
   129  		},
   130  		{
   131  			name: "failures for proto with invalid fields",
   132  			inputProto: &parser.Proto{
   133  				ProtoBody: []parser.Visitee{
   134  					&parser.Message{
   135  						MessageBody: []parser.Visitee{
   136  							&parser.Field{
   137  								FieldName: "FieldName",
   138  								Meta: meta.Meta{
   139  									Pos: meta.Position{
   140  										Filename: "example.proto",
   141  										Offset:   150,
   142  										Line:     7,
   143  										Column:   15,
   144  									},
   145  								},
   146  							},
   147  							&parser.MapField{
   148  								MapName: "MapFieldName",
   149  								Meta: meta.Meta{
   150  									Pos: meta.Position{
   151  										Filename: "example.proto",
   152  										Offset:   200,
   153  										Line:     14,
   154  										Column:   30,
   155  									},
   156  								},
   157  							},
   158  							&parser.Oneof{
   159  								OneofFields: []*parser.OneofField{
   160  									{
   161  										FieldName: "OneofFieldName",
   162  										Meta: meta.Meta{
   163  											Pos: meta.Position{
   164  												Filename: "example.proto",
   165  												Offset:   300,
   166  												Line:     21,
   167  												Column:   45,
   168  											},
   169  										},
   170  									},
   171  								},
   172  							},
   173  						},
   174  					},
   175  				},
   176  			},
   177  			wantFailures: []report.Failure{
   178  				report.Failuref(
   179  					meta.Position{
   180  						Filename: "example.proto",
   181  						Offset:   150,
   182  						Line:     7,
   183  						Column:   15,
   184  					},
   185  					"FIELDS_HAVE_COMMENT",
   186  					`Field "FieldName" should have a comment`,
   187  				),
   188  				report.Failuref(
   189  					meta.Position{
   190  						Filename: "example.proto",
   191  						Offset:   200,
   192  						Line:     14,
   193  						Column:   30,
   194  					},
   195  					"FIELDS_HAVE_COMMENT",
   196  					`Field "MapFieldName" should have a comment`,
   197  				),
   198  				report.Failuref(
   199  					meta.Position{
   200  						Filename: "example.proto",
   201  						Offset:   300,
   202  						Line:     21,
   203  						Column:   45,
   204  					},
   205  					"FIELDS_HAVE_COMMENT",
   206  					`Field "OneofFieldName" should have a comment`,
   207  				),
   208  			},
   209  		},
   210  		{
   211  			name: "failures for proto with invalid fields without Golang style comments",
   212  			inputProto: &parser.Proto{
   213  				ProtoBody: []parser.Visitee{
   214  					&parser.Message{
   215  						MessageBody: []parser.Visitee{
   216  							&parser.Field{
   217  								FieldName: "FieldName",
   218  								Comments: []*parser.Comment{
   219  									{
   220  										Raw: "// a field name.",
   221  									},
   222  								},
   223  								Meta: meta.Meta{
   224  									Pos: meta.Position{
   225  										Filename: "example.proto",
   226  										Offset:   150,
   227  										Line:     7,
   228  										Column:   15,
   229  									},
   230  								},
   231  							},
   232  							&parser.MapField{
   233  								MapName: "MapFieldName",
   234  								Comments: []*parser.Comment{
   235  									{
   236  										Raw: "// a map field name.",
   237  									},
   238  								},
   239  								Meta: meta.Meta{
   240  									Pos: meta.Position{
   241  										Filename: "example.proto",
   242  										Offset:   200,
   243  										Line:     14,
   244  										Column:   30,
   245  									},
   246  								},
   247  							},
   248  							&parser.Oneof{
   249  								OneofFields: []*parser.OneofField{
   250  									{
   251  										FieldName: "OneofFieldName",
   252  										Comments: []*parser.Comment{
   253  											{
   254  												Raw: "// a oneof field name.",
   255  											},
   256  										},
   257  										Meta: meta.Meta{
   258  											Pos: meta.Position{
   259  												Filename: "example.proto",
   260  												Offset:   300,
   261  												Line:     21,
   262  												Column:   45,
   263  											},
   264  										},
   265  									},
   266  								},
   267  							},
   268  						},
   269  					},
   270  				},
   271  			},
   272  			inputShouldFollowGolangStyle: true,
   273  			wantFailures: []report.Failure{
   274  				report.Failuref(
   275  					meta.Position{
   276  						Filename: "example.proto",
   277  						Offset:   150,
   278  						Line:     7,
   279  						Column:   15,
   280  					},
   281  					"FIELDS_HAVE_COMMENT",
   282  					`Field "FieldName" should have a comment of the form "// FieldName ..."`,
   283  				),
   284  				report.Failuref(
   285  					meta.Position{
   286  						Filename: "example.proto",
   287  						Offset:   200,
   288  						Line:     14,
   289  						Column:   30,
   290  					},
   291  					"FIELDS_HAVE_COMMENT",
   292  					`Field "MapFieldName" should have a comment of the form "// MapFieldName ..."`,
   293  				),
   294  				report.Failuref(
   295  					meta.Position{
   296  						Filename: "example.proto",
   297  						Offset:   300,
   298  						Line:     21,
   299  						Column:   45,
   300  					},
   301  					"FIELDS_HAVE_COMMENT",
   302  					`Field "OneofFieldName" should have a comment of the form "// OneofFieldName ..."`,
   303  				),
   304  			},
   305  		},
   306  		{
   307  			name: "failures for proto with fields without Golang style comments due to the inline comment",
   308  			inputProto: &parser.Proto{
   309  				ProtoBody: []parser.Visitee{
   310  					&parser.Message{
   311  						MessageBody: []parser.Visitee{
   312  							&parser.Field{
   313  								FieldName: "FieldName2",
   314  								InlineComment: &parser.Comment{
   315  									Raw: "// FieldName2 is a field name.",
   316  								},
   317  							},
   318  							&parser.MapField{
   319  								MapName: "MapFieldName2",
   320  								InlineComment: &parser.Comment{
   321  									Raw: "// MapFieldName2 is a map field name.",
   322  								},
   323  							},
   324  							&parser.Oneof{
   325  								OneofFields: []*parser.OneofField{
   326  									{
   327  										FieldName: "OneofFieldName2",
   328  										InlineComment: &parser.Comment{
   329  											Raw: "// OneofFieldName2 is a oneof field name.",
   330  										},
   331  									},
   332  								},
   333  							},
   334  						},
   335  					},
   336  				},
   337  			},
   338  			inputShouldFollowGolangStyle: true,
   339  			wantFailures: []report.Failure{
   340  				report.Failuref(
   341  					meta.Position{},
   342  					"FIELDS_HAVE_COMMENT",
   343  					`Field "FieldName2" should have a comment of the form "// FieldName2 ..."`,
   344  				),
   345  				report.Failuref(
   346  					meta.Position{},
   347  					"FIELDS_HAVE_COMMENT",
   348  					`Field "MapFieldName2" should have a comment of the form "// MapFieldName2 ..."`,
   349  				),
   350  				report.Failuref(
   351  					meta.Position{},
   352  					"FIELDS_HAVE_COMMENT",
   353  					`Field "OneofFieldName2" should have a comment of the form "// OneofFieldName2 ..."`,
   354  				),
   355  			},
   356  		},
   357  	}
   358  
   359  	for _, test := range tests {
   360  		test := test
   361  		t.Run(test.name, func(t *testing.T) {
   362  			rule := rules.NewFieldsHaveCommentRule(rule.SeverityError, test.inputShouldFollowGolangStyle)
   363  
   364  			got, err := rule.Apply(test.inputProto)
   365  			if err != nil {
   366  				t.Errorf("got err %v, but want nil", err)
   367  				return
   368  			}
   369  			if !reflect.DeepEqual(got, test.wantFailures) {
   370  				t.Errorf("got %v, but want %v", got, test.wantFailures)
   371  			}
   372  		})
   373  	}
   374  }