github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/quoteConsistentRule_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/protolint/internal/linter/config"
    10  
    11  	"github.com/yoheimuta/go-protoparser/v4/parser"
    12  	"github.com/yoheimuta/protolint/internal/addon/rules"
    13  	"github.com/yoheimuta/protolint/linter/report"
    14  	"github.com/yoheimuta/protolint/linter/rule"
    15  )
    16  
    17  func TestQuoteConsistentRule_Apply(t *testing.T) {
    18  	tests := []struct {
    19  		name         string
    20  		inputProto   *parser.Proto
    21  		inputQuote   config.QuoteType
    22  		wantFailures []report.Failure
    23  	}{
    24  		{
    25  			name: "no failures for proto with consistent double-quoted strings",
    26  			inputProto: &parser.Proto{
    27  				ProtoBody: []parser.Visitee{
    28  					&parser.Syntax{
    29  						ProtobufVersionQuote: `"proto3"`,
    30  					},
    31  					&parser.Import{
    32  						Location: `"google/protobuf/empty.proto"`,
    33  					},
    34  					&parser.Option{
    35  						Constant: `"com.example.foo"`,
    36  					},
    37  					&parser.Enum{
    38  						EnumBody: []parser.Visitee{
    39  							&parser.EnumField{
    40  								EnumValueOptions: []*parser.EnumValueOption{
    41  									{
    42  										Constant: `"custom option"`,
    43  									},
    44  								},
    45  							},
    46  						},
    47  					},
    48  					&parser.Message{
    49  						MessageBody: []parser.Visitee{
    50  							&parser.Field{
    51  								FieldOptions: []*parser.FieldOption{
    52  									{
    53  										Constant: `"field option"`,
    54  									},
    55  								},
    56  							},
    57  						},
    58  					},
    59  				},
    60  			},
    61  			inputQuote: config.DoubleQuote,
    62  		},
    63  		{
    64  			name: "no failures for proto with consistent single-quoted strings",
    65  			inputProto: &parser.Proto{
    66  				ProtoBody: []parser.Visitee{
    67  					&parser.Syntax{
    68  						ProtobufVersionQuote: `'proto3'`,
    69  					},
    70  					&parser.Import{
    71  						Location: `'google/protobuf/empty.proto'`,
    72  					},
    73  					&parser.Option{
    74  						Constant: `'com.example.foo'`,
    75  					},
    76  					&parser.Enum{
    77  						EnumBody: []parser.Visitee{
    78  							&parser.EnumField{
    79  								EnumValueOptions: []*parser.EnumValueOption{
    80  									{
    81  										Constant: `'custom option'`,
    82  									},
    83  								},
    84  							},
    85  						},
    86  					},
    87  					&parser.Message{
    88  						MessageBody: []parser.Visitee{
    89  							&parser.Field{
    90  								FieldOptions: []*parser.FieldOption{
    91  									{
    92  										Constant: `'field option'`,
    93  									},
    94  								},
    95  							},
    96  						},
    97  					},
    98  				},
    99  			},
   100  			inputQuote: config.SingleQuote,
   101  		},
   102  		{
   103  			name: "failures for proto with an inconsistent double-quoted strings",
   104  			inputProto: &parser.Proto{
   105  				ProtoBody: []parser.Visitee{
   106  					&parser.Syntax{
   107  						ProtobufVersionQuote: `"proto3"`,
   108  					},
   109  					&parser.Import{
   110  						Location: `"google/protobuf/empty.proto"`,
   111  					},
   112  					&parser.Option{
   113  						Constant: `"com.example.foo"`,
   114  					},
   115  					&parser.Enum{
   116  						EnumBody: []parser.Visitee{
   117  							&parser.EnumField{
   118  								EnumValueOptions: []*parser.EnumValueOption{
   119  									{
   120  										Constant: `"custom option"`,
   121  									},
   122  								},
   123  							},
   124  						},
   125  					},
   126  					&parser.Message{
   127  						MessageBody: []parser.Visitee{
   128  							&parser.Field{
   129  								FieldOptions: []*parser.FieldOption{
   130  									{
   131  										Constant: `"field option"`,
   132  									},
   133  								},
   134  							},
   135  						},
   136  					},
   137  				},
   138  			},
   139  			inputQuote: config.SingleQuote,
   140  			wantFailures: []report.Failure{
   141  				report.Failuref(
   142  					meta.Position{},
   143  					"QUOTE_CONSISTENT",
   144  					`Quoted string should be 'proto3' but was "proto3".`,
   145  				),
   146  				report.Failuref(
   147  					meta.Position{},
   148  					"QUOTE_CONSISTENT",
   149  					`Quoted string should be 'google/protobuf/empty.proto' but was "google/protobuf/empty.proto".`,
   150  				),
   151  				report.Failuref(
   152  					meta.Position{},
   153  					"QUOTE_CONSISTENT",
   154  					`Quoted string should be 'com.example.foo' but was "com.example.foo".`,
   155  				),
   156  				report.Failuref(
   157  					meta.Position{},
   158  					"QUOTE_CONSISTENT",
   159  					`Quoted string should be 'custom option' but was "custom option".`,
   160  				),
   161  				report.Failuref(
   162  					meta.Position{},
   163  					"QUOTE_CONSISTENT",
   164  					`Quoted string should be 'field option' but was "field option".`,
   165  				),
   166  			},
   167  		},
   168  		{
   169  			name: "failures for proto with an inconsistent single-quoted strings",
   170  			inputProto: &parser.Proto{
   171  				ProtoBody: []parser.Visitee{
   172  					&parser.Syntax{
   173  						ProtobufVersionQuote: `'proto3'`,
   174  					},
   175  					&parser.Import{
   176  						Location: `'google/protobuf/empty.proto'`,
   177  					},
   178  					&parser.Option{
   179  						Constant: `'com.example.foo'`,
   180  					},
   181  					&parser.Enum{
   182  						EnumBody: []parser.Visitee{
   183  							&parser.EnumField{
   184  								EnumValueOptions: []*parser.EnumValueOption{
   185  									{
   186  										Constant: `'custom option'`,
   187  									},
   188  								},
   189  							},
   190  						},
   191  					},
   192  					&parser.Message{
   193  						MessageBody: []parser.Visitee{
   194  							&parser.Field{
   195  								FieldOptions: []*parser.FieldOption{
   196  									{
   197  										Constant: `'field option'`,
   198  									},
   199  								},
   200  							},
   201  						},
   202  					},
   203  				},
   204  			},
   205  			inputQuote: config.DoubleQuote,
   206  			wantFailures: []report.Failure{
   207  				report.Failuref(
   208  					meta.Position{},
   209  					"QUOTE_CONSISTENT",
   210  					`Quoted string should be "proto3" but was 'proto3'.`,
   211  				),
   212  				report.Failuref(
   213  					meta.Position{},
   214  					"QUOTE_CONSISTENT",
   215  					`Quoted string should be "google/protobuf/empty.proto" but was 'google/protobuf/empty.proto'.`,
   216  				),
   217  				report.Failuref(
   218  					meta.Position{},
   219  					"QUOTE_CONSISTENT",
   220  					`Quoted string should be "com.example.foo" but was 'com.example.foo'.`,
   221  				),
   222  				report.Failuref(
   223  					meta.Position{},
   224  					"QUOTE_CONSISTENT",
   225  					`Quoted string should be "custom option" but was 'custom option'.`,
   226  				),
   227  				report.Failuref(
   228  					meta.Position{},
   229  					"QUOTE_CONSISTENT",
   230  					`Quoted string should be "field option" but was 'field option'.`,
   231  				),
   232  			},
   233  		},
   234  	}
   235  
   236  	for _, test := range tests {
   237  		test := test
   238  		t.Run(test.name, func(t *testing.T) {
   239  			rule := rules.NewQuoteConsistentRule(rule.SeverityError, test.inputQuote, false)
   240  
   241  			got, err := rule.Apply(test.inputProto)
   242  			if err != nil {
   243  				t.Errorf("got err %v, but want nil", err)
   244  				return
   245  			}
   246  			if !reflect.DeepEqual(got, test.wantFailures) {
   247  				t.Errorf("got %v, but want %v", got, test.wantFailures)
   248  			}
   249  		})
   250  	}
   251  }
   252  
   253  func TestQuoteConsistentRule_Apply_fix(t *testing.T) {
   254  	tests := []struct {
   255  		name          string
   256  		inputQuote    config.QuoteType
   257  		inputFilename string
   258  		wantFilename  string
   259  	}{
   260  		{
   261  			name:          "no fix for a double-quoted proto",
   262  			inputQuote:    config.DoubleQuote,
   263  			inputFilename: "double-quoted.proto",
   264  			wantFilename:  "double-quoted.proto",
   265  		},
   266  		{
   267  			name:          "fix for an inconsistent proto with double-quoted consistency",
   268  			inputQuote:    config.DoubleQuote,
   269  			inputFilename: "inconsistent.proto",
   270  			wantFilename:  "double-quoted.proto",
   271  		},
   272  		{
   273  			name:          "fix for an inconsistent proto with single-quoted consistency",
   274  			inputQuote:    config.SingleQuote,
   275  			inputFilename: "inconsistent.proto",
   276  			wantFilename:  "single-quoted.proto",
   277  		},
   278  	}
   279  
   280  	for _, test := range tests {
   281  		test := test
   282  		t.Run(test.name, func(t *testing.T) {
   283  			r := rules.NewQuoteConsistentRule(
   284  				rule.SeverityError,
   285  				test.inputQuote,
   286  				true,
   287  			)
   288  			testApplyFix(t, r, test.inputFilename, test.wantFilename)
   289  		})
   290  	}
   291  }