github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/orderRule_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/report" 12 "github.com/yoheimuta/protolint/linter/rule" 13 ) 14 15 func TestOrderRule_Apply(t *testing.T) { 16 tests := []struct { 17 name string 18 inputProto *parser.Proto 19 wantFailures []report.Failure 20 }{ 21 { 22 name: "no failures for proto including all elements in order", 23 inputProto: &parser.Proto{ 24 ProtoBody: []parser.Visitee{ 25 &parser.Syntax{}, 26 &parser.Package{}, 27 &parser.Import{}, 28 &parser.Import{}, 29 &parser.Option{}, 30 &parser.Option{}, 31 &parser.Message{}, 32 &parser.Enum{}, 33 &parser.Service{}, 34 &parser.Extend{}, 35 }, 36 }, 37 }, 38 { 39 name: "no failures for proto omitting the syntax", 40 inputProto: &parser.Proto{ 41 ProtoBody: []parser.Visitee{ 42 &parser.Package{}, 43 &parser.Import{}, 44 &parser.Import{}, 45 &parser.Option{}, 46 &parser.Option{}, 47 &parser.Message{}, 48 &parser.Enum{}, 49 &parser.Service{}, 50 &parser.Extend{}, 51 }, 52 }, 53 }, 54 { 55 name: "no failures for proto omitting the package", 56 inputProto: &parser.Proto{ 57 ProtoBody: []parser.Visitee{ 58 &parser.Syntax{}, 59 &parser.Import{}, 60 &parser.Import{}, 61 &parser.Option{}, 62 &parser.Option{}, 63 &parser.Message{}, 64 &parser.Enum{}, 65 &parser.Service{}, 66 &parser.Extend{}, 67 }, 68 }, 69 }, 70 { 71 name: "no failures for proto omitting the imports", 72 inputProto: &parser.Proto{ 73 ProtoBody: []parser.Visitee{ 74 &parser.Syntax{}, 75 &parser.Package{}, 76 &parser.Option{}, 77 &parser.Option{}, 78 &parser.Message{}, 79 &parser.Enum{}, 80 &parser.Service{}, 81 &parser.Extend{}, 82 }, 83 }, 84 }, 85 { 86 name: "no failures for proto omitting the options", 87 inputProto: &parser.Proto{ 88 ProtoBody: []parser.Visitee{ 89 &parser.Syntax{}, 90 &parser.Package{}, 91 &parser.Import{}, 92 &parser.Import{}, 93 &parser.Message{}, 94 &parser.Enum{}, 95 &parser.Service{}, 96 &parser.Extend{}, 97 }, 98 }, 99 }, 100 { 101 name: "no failures for proto omitting the everything else", 102 inputProto: &parser.Proto{ 103 ProtoBody: []parser.Visitee{ 104 &parser.Syntax{}, 105 &parser.Package{}, 106 &parser.Import{}, 107 &parser.Import{}, 108 &parser.Option{}, 109 &parser.Option{}, 110 }, 111 }, 112 }, 113 { 114 name: "no failures for proto including only the everything else", 115 inputProto: &parser.Proto{ 116 ProtoBody: []parser.Visitee{ 117 &parser.Message{}, 118 &parser.Enum{}, 119 &parser.Service{}, 120 &parser.Extend{}, 121 }, 122 }, 123 }, 124 { 125 name: "no failures for proto omitting the syntax and the package", 126 inputProto: &parser.Proto{ 127 ProtoBody: []parser.Visitee{ 128 &parser.Import{}, 129 &parser.Import{}, 130 &parser.Option{}, 131 &parser.Option{}, 132 &parser.Message{}, 133 &parser.Enum{}, 134 &parser.Service{}, 135 &parser.Extend{}, 136 }, 137 }, 138 }, 139 { 140 name: "no failures for proto omitting the syntax, the package and the imports", 141 inputProto: &parser.Proto{ 142 ProtoBody: []parser.Visitee{ 143 &parser.Option{}, 144 &parser.Option{}, 145 &parser.Message{}, 146 &parser.Enum{}, 147 &parser.Service{}, 148 &parser.Extend{}, 149 }, 150 }, 151 }, 152 { 153 name: "no failures for proto omitting the syntax, the package and the options", 154 inputProto: &parser.Proto{ 155 ProtoBody: []parser.Visitee{ 156 &parser.Import{}, 157 &parser.Import{}, 158 &parser.Message{}, 159 &parser.Enum{}, 160 &parser.Service{}, 161 &parser.Extend{}, 162 }, 163 }, 164 }, 165 { 166 name: "failures for proto in which the order of the syntax is invalid", 167 inputProto: &parser.Proto{ 168 ProtoBody: []parser.Visitee{ 169 &parser.Package{}, 170 &parser.Syntax{ 171 Meta: meta.Meta{ 172 Pos: meta.Position{ 173 Filename: "example.proto", 174 Offset: 100, 175 Line: 5, 176 Column: 10, 177 }, 178 }, 179 }, 180 }, 181 }, 182 wantFailures: []report.Failure{ 183 report.Failuref( 184 meta.Position{ 185 Filename: "example.proto", 186 Offset: 100, 187 Line: 5, 188 Column: 10, 189 }, 190 "ORDER", 191 `Syntax should be located at the top. Check if the file is ordered in the correct manner.`, 192 ), 193 }, 194 }, 195 { 196 name: "failures for proto in which the order of the package is invalid", 197 inputProto: &parser.Proto{ 198 ProtoBody: []parser.Visitee{ 199 &parser.Syntax{}, 200 &parser.Import{}, 201 &parser.Package{ 202 Meta: meta.Meta{ 203 Pos: meta.Position{ 204 Filename: "example.proto", 205 Offset: 100, 206 Line: 5, 207 Column: 10, 208 }, 209 }, 210 }, 211 }, 212 }, 213 wantFailures: []report.Failure{ 214 report.Failuref( 215 meta.Position{ 216 Filename: "example.proto", 217 Offset: 100, 218 Line: 5, 219 Column: 10, 220 }, 221 "ORDER", 222 `The order of Package is invalid. Check if the file is ordered in the correct manner.`, 223 ), 224 }, 225 }, 226 { 227 name: "failures for proto in which the order of the imports is invalid", 228 inputProto: &parser.Proto{ 229 ProtoBody: []parser.Visitee{ 230 &parser.Syntax{}, 231 &parser.Package{}, 232 &parser.Message{}, 233 &parser.Import{ 234 Meta: meta.Meta{ 235 Pos: meta.Position{ 236 Filename: "example.proto", 237 Offset: 100, 238 Line: 5, 239 Column: 10, 240 }, 241 }, 242 }, 243 &parser.Import{}, 244 &parser.Option{}, 245 &parser.Import{ 246 Meta: meta.Meta{ 247 Pos: meta.Position{ 248 Filename: "example.proto", 249 Offset: 200, 250 Line: 10, 251 Column: 20, 252 }, 253 }, 254 }, 255 }, 256 }, 257 wantFailures: []report.Failure{ 258 report.Failuref( 259 meta.Position{ 260 Filename: "example.proto", 261 Offset: 100, 262 Line: 5, 263 Column: 10, 264 }, 265 "ORDER", 266 `The order of Import is invalid. Check if the file is ordered in the correct manner.`, 267 ), 268 report.Failuref( 269 meta.Position{ 270 Filename: "example.proto", 271 Offset: 200, 272 Line: 10, 273 Column: 20, 274 }, 275 "ORDER", 276 `The order of Import is invalid. Check if the file is ordered in the correct manner.`, 277 ), 278 }, 279 }, 280 { 281 name: "failures for proto in which the order of the options is invalid", 282 inputProto: &parser.Proto{ 283 ProtoBody: []parser.Visitee{ 284 &parser.Option{}, 285 &parser.Extend{}, 286 &parser.Option{ 287 Meta: meta.Meta{ 288 Pos: meta.Position{ 289 Filename: "example.proto", 290 Offset: 100, 291 Line: 5, 292 Column: 10, 293 }, 294 }, 295 }, 296 &parser.Option{}, 297 &parser.Service{}, 298 &parser.Option{ 299 Meta: meta.Meta{ 300 Pos: meta.Position{ 301 Filename: "example.proto", 302 Offset: 200, 303 Line: 10, 304 Column: 20, 305 }, 306 }, 307 }, 308 }, 309 }, 310 wantFailures: []report.Failure{ 311 report.Failuref( 312 meta.Position{ 313 Filename: "example.proto", 314 Offset: 100, 315 Line: 5, 316 Column: 10, 317 }, 318 "ORDER", 319 `The order of Option is invalid. Check if the file is ordered in the correct manner.`, 320 ), 321 report.Failuref( 322 meta.Position{ 323 Filename: "example.proto", 324 Offset: 200, 325 Line: 10, 326 Column: 20, 327 }, 328 "ORDER", 329 `The order of Option is invalid. Check if the file is ordered in the correct manner.`, 330 ), 331 }, 332 }, 333 } 334 335 for _, test := range tests { 336 test := test 337 t.Run(test.name, func(t *testing.T) { 338 rule := rules.NewOrderRule(rule.SeverityError, false) 339 340 got, err := rule.Apply(test.inputProto) 341 if err != nil { 342 t.Errorf("got err %v, but want nil", err) 343 return 344 } 345 if !reflect.DeepEqual(got, test.wantFailures) { 346 t.Errorf("got %v, but want %v", got, test.wantFailures) 347 } 348 }) 349 } 350 } 351 352 func TestOrderRule_Apply_fix(t *testing.T) { 353 tests := []struct { 354 name string 355 inputFilename string 356 wantFilename string 357 }{ 358 { 359 name: "no fix for a correct proto", 360 inputFilename: "order.proto", 361 wantFilename: "order.proto", 362 }, 363 { 364 name: "fix for an incorrect proto", 365 inputFilename: "invalid.proto", 366 wantFilename: "order.proto", 367 }, 368 { 369 name: "fix for an incorrect proto while keeping contiguous misc elements", 370 inputFilename: "invalidContiguousMisc.proto", 371 wantFilename: "orderContiguousMisc.proto", 372 }, 373 { 374 name: "fix for an incorrect proto filled with many elements", 375 inputFilename: "invalidMany.proto", 376 wantFilename: "orderMany.proto", 377 }, 378 { 379 name: "fix for an incorrect proto filled with many comments", 380 inputFilename: "invalidWithComments.proto", 381 wantFilename: "orderWithComments.proto", 382 }, 383 } 384 385 for _, test := range tests { 386 test := test 387 t.Run(test.name, func(t *testing.T) { 388 r := rules.NewOrderRule(rule.SeverityError, true) 389 testApplyFix(t, r, test.inputFilename, test.wantFilename) 390 }) 391 } 392 }