github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/fieldNamesLowerSnakeCaseRule_test.go (about) 1 package rules_test 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/yoheimuta/go-protoparser/v4/parser" 8 "github.com/yoheimuta/go-protoparser/v4/parser/meta" 9 10 "github.com/yoheimuta/protolint/internal/addon/rules" 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 TestFieldNamesLowerSnakeCaseRule_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 fields", 24 inputProto: &parser.Proto{ 25 ProtoBody: []parser.Visitee{ 26 &parser.Enum{}, 27 }, 28 }, 29 }, 30 { 31 name: "no failures for proto with valid field names", 32 inputProto: &parser.Proto{ 33 ProtoBody: []parser.Visitee{ 34 &parser.Service{}, 35 &parser.Message{ 36 MessageBody: []parser.Visitee{ 37 &parser.Field{ 38 FieldName: "song_name", 39 }, 40 &parser.Field{ 41 FieldName: "singer", 42 }, 43 &parser.MapField{ 44 MapName: "song_name2", 45 }, 46 &parser.Oneof{ 47 OneofFields: []*parser.OneofField{ 48 { 49 FieldName: "song_name3", 50 }, 51 }, 52 }, 53 }, 54 }, 55 }, 56 }, 57 }, 58 { 59 name: "failures for proto with invalid field names", 60 inputProto: &parser.Proto{ 61 ProtoBody: []parser.Visitee{ 62 &parser.Message{ 63 MessageBody: []parser.Visitee{ 64 &parser.Field{ 65 FieldName: "song_Name", 66 Meta: meta.Meta{ 67 Pos: meta.Position{ 68 Filename: "example.proto", 69 Offset: 100, 70 Line: 5, 71 Column: 10, 72 }, 73 }, 74 }, 75 &parser.MapField{ 76 MapName: "MapFieldName", 77 Meta: meta.Meta{ 78 Pos: meta.Position{ 79 Filename: "example.proto", 80 Offset: 210, 81 Line: 14, 82 Column: 30, 83 }, 84 }, 85 }, 86 &parser.Oneof{ 87 OneofFields: []*parser.OneofField{ 88 { 89 FieldName: "OneofFieldName", 90 Meta: meta.Meta{ 91 Pos: meta.Position{ 92 Filename: "example.proto", 93 Offset: 300, 94 Line: 21, 95 Column: 45, 96 }, 97 }, 98 }, 99 }, 100 }, 101 }, 102 }, 103 }, 104 }, 105 wantFailures: []report.Failure{ 106 report.Failuref( 107 meta.Position{ 108 Filename: "example.proto", 109 Offset: 100, 110 Line: 5, 111 Column: 10, 112 }, 113 "FIELD_NAMES_LOWER_SNAKE_CASE", 114 `Field name "song_Name" must be underscore_separated_names like "song_name"`, 115 ), 116 report.Failuref( 117 meta.Position{ 118 Filename: "example.proto", 119 Offset: 210, 120 Line: 14, 121 Column: 30, 122 }, 123 "FIELD_NAMES_LOWER_SNAKE_CASE", 124 `Field name "MapFieldName" must be underscore_separated_names like "map_field_name"`, 125 ), 126 report.Failuref( 127 meta.Position{ 128 Filename: "example.proto", 129 Offset: 300, 130 Line: 21, 131 Column: 45, 132 }, 133 "FIELD_NAMES_LOWER_SNAKE_CASE", 134 `Field name "OneofFieldName" must be underscore_separated_names like "oneof_field_name"`, 135 ), 136 }, 137 }, 138 } 139 140 for _, test := range tests { 141 test := test 142 t.Run(test.name, func(t *testing.T) { 143 rule := rules.NewFieldNamesLowerSnakeCaseRule(rule.SeverityError, false, autodisable.Noop) 144 145 got, err := rule.Apply(test.inputProto) 146 if err != nil { 147 t.Errorf("got err %v, but want nil", err) 148 return 149 } 150 if !reflect.DeepEqual(got, test.wantFailures) { 151 t.Errorf("got %v, but want %v", got, test.wantFailures) 152 } 153 }) 154 } 155 } 156 157 func TestFieldNamesLowerSnakeCaseRule_Apply_fix(t *testing.T) { 158 tests := []struct { 159 name string 160 inputFilename string 161 wantFilename string 162 }{ 163 { 164 name: "no fix for a correct proto", 165 inputFilename: "lower_snake_case.proto", 166 wantFilename: "lower_snake_case.proto", 167 }, 168 { 169 name: "fix for an incorrect proto", 170 inputFilename: "invalid.proto", 171 wantFilename: "lower_snake_case.proto", 172 }, 173 } 174 175 for _, test := range tests { 176 test := test 177 t.Run(test.name, func(t *testing.T) { 178 r := rules.NewFieldNamesLowerSnakeCaseRule(rule.SeverityError, true, autodisable.Noop) 179 testApplyFix(t, r, test.inputFilename, test.wantFilename) 180 }) 181 } 182 } 183 184 func TestFieldNamesLowerSnakeCaseRule_Apply_disable(t *testing.T) { 185 tests := []struct { 186 name string 187 inputFilename string 188 inputPlacementType autodisable.PlacementType 189 wantFilename string 190 }{ 191 { 192 name: "do nothing in case of no violations", 193 inputFilename: "lower_snake_case.proto", 194 wantFilename: "lower_snake_case.proto", 195 }, 196 { 197 name: "insert disable:next comments", 198 inputFilename: "invalid.proto", 199 inputPlacementType: autodisable.Next, 200 wantFilename: "disable_next.proto", 201 }, 202 { 203 name: "insert disable:this comments", 204 inputFilename: "invalid.proto", 205 inputPlacementType: autodisable.ThisThenNext, 206 wantFilename: "disable_this.proto", 207 }, 208 } 209 210 for _, test := range tests { 211 test := test 212 t.Run(test.name, func(t *testing.T) { 213 r := rules.NewFieldNamesLowerSnakeCaseRule(rule.SeverityError, true, test.inputPlacementType) 214 testApplyFix(t, r, test.inputFilename, test.wantFilename) 215 }) 216 } 217 }