github.com/googleapis/api-linter@v1.65.2/lint/rule_enabled_test.go (about)

     1  // Copyright 2019 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // 		https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package lint
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/jhump/protoreflect/desc"
    21  	"github.com/jhump/protoreflect/desc/builder"
    22  	dpb "google.golang.org/protobuf/types/descriptorpb"
    23  )
    24  
    25  func TestRuleIsEnabled(t *testing.T) {
    26  	// Create a no-op rule, which we can check enabled status on.
    27  	rule := &FileRule{
    28  		Name: RuleName("a::b::c"),
    29  		LintFile: func(fd *desc.FileDescriptor) []Problem {
    30  			return []Problem{}
    31  		},
    32  	}
    33  
    34  	aliases := map[string]string{
    35  		"a::b::c": "d::e::f",
    36  	}
    37  
    38  	// Create appropriate test permutations.
    39  	tests := []struct {
    40  		testName       string
    41  		fileComment    string
    42  		messageComment string
    43  		enabled        bool
    44  	}{
    45  		{"Enabled", "", "", true},
    46  		{"FileDisabled", "api-linter: a::b::c=disabled", "", false},
    47  		{"MessageDisabled", "", "api-linter: a::b::c=disabled", false},
    48  		{"NameNotMatch", "", "api-linter: other=disabled", true},
    49  		{"RegexpNotMatch", "", "api-lint: a::b::c=disabled", true},
    50  		{"AliasDisabled", "", "api-linter: d::e::f=disabled", false},
    51  		{"FileComments_PrefixMatched_Disabled", "api-linter: a=disabled", "", false},
    52  		{"FileComments_MiddleMatched_Disabled", "api-linter: b=disabled", "", false},
    53  		{"FileComments_SuffixMatched_Disabled", "api-linter: c=disabled", "", false},
    54  		{"FileComments_MultipleLinesMatched_Disabled", "api-linter: x=disabled\napi-linter: a=disabled", "", false},
    55  		{"MessageComments_PrefixMatched_Disabled", "", "api-linter: a=disabled", false},
    56  		{"MessageComments_MiddleMatched_Disabled", "", "api-linter: b=disabled", false},
    57  		{"MessageComments_SuffixMatched_Disabled", "", "api-linter: c=disabled", false},
    58  		{"MessageComments_MultipleLinesMatched_Disabled", "", "api-linter: x=disabled\napi-linter: a=disabled", false},
    59  	}
    60  
    61  	// Run the specific tests individually.
    62  	for _, test := range tests {
    63  		t.Run(test.testName, func(t *testing.T) {
    64  			f, err := builder.NewFile("test.proto").SetSyntaxComments(builder.Comments{
    65  				LeadingComment: test.fileComment,
    66  			}).AddMessage(
    67  				builder.NewMessage("MyMessage").SetComments(builder.Comments{
    68  					LeadingComment: test.messageComment,
    69  				}),
    70  			).Build()
    71  			if err != nil {
    72  				t.Fatalf("Error building test message")
    73  			}
    74  			if got, want := ruleIsEnabled(rule, f.GetMessageTypes()[0], nil, aliases, false), test.enabled; got != want {
    75  				t.Errorf("Expected the test rule to return %v from ruleIsEnabled, got %v", want, got)
    76  			}
    77  			if !test.enabled {
    78  				if got, want := ruleIsEnabled(rule, f.GetMessageTypes()[0], nil, aliases, true), true; got != want {
    79  					t.Errorf("Expected the test rule with ignoreCommentDisables true to return %v from ruleIsEnabled, got %v", want, got)
    80  				}
    81  			}
    82  		})
    83  	}
    84  }
    85  
    86  func TestRuleIsEnabledFirstMessage(t *testing.T) {
    87  	// Create a no-op rule, which we can check enabled status on.
    88  	rule := &FileRule{
    89  		Name: RuleName("test"),
    90  		LintFile: func(fd *desc.FileDescriptor) []Problem {
    91  			return []Problem{}
    92  		},
    93  	}
    94  
    95  	// Build a proto and check that ruleIsEnabled does the right thing.
    96  	f, err := builder.NewFile("test.proto").AddMessage(
    97  		builder.NewMessage("FirstMessage").SetComments(builder.Comments{
    98  			LeadingComment: "api-linter: test=disabled",
    99  		}),
   100  	).AddMessage(
   101  		builder.NewMessage("SecondMessage"),
   102  	).Build()
   103  	if err != nil {
   104  		t.Fatalf("Error building test file: %q", err)
   105  	}
   106  	if got, want := ruleIsEnabled(rule, f.GetMessageTypes()[0], nil, nil, false), false; got != want {
   107  		t.Errorf("Expected the first message to return %v from ruleIsEnabled, got %v", want, got)
   108  	}
   109  	if got, want := ruleIsEnabled(rule, f.GetMessageTypes()[1], nil, nil, false), true; got != want {
   110  		t.Errorf("Expected the second message to return %v from ruleIsEnabled, got %v", want, got)
   111  	}
   112  }
   113  
   114  func TestRuleIsEnabledParent(t *testing.T) {
   115  	// Create a rule that we can check enabled status on.
   116  	rule := &FieldRule{
   117  		Name: RuleName("test"),
   118  		LintField: func(f *desc.FieldDescriptor) []Problem {
   119  			return nil
   120  		},
   121  	}
   122  
   123  	// Build a proto with two messages, one of which disables the rule.
   124  	f, err := builder.NewFile("test.proto").AddMessage(
   125  		builder.NewMessage("Foo").SetComments(builder.Comments{
   126  			LeadingComment: "api-linter: test=disabled",
   127  		}).AddField(builder.NewField("foo", builder.FieldTypeBool())),
   128  	).AddMessage(
   129  		builder.NewMessage("Bar").AddField(builder.NewField("bar", builder.FieldTypeBool())),
   130  	).Build()
   131  	if err != nil {
   132  		t.Fatalf("Error building test file: %q", err)
   133  	}
   134  	if got, want := ruleIsEnabled(rule, f.GetMessageTypes()[0].GetFields()[0], nil, nil, false), false; got != want {
   135  		t.Errorf("Expected the foo field to return %v from ruleIsEnabled; got %v", want, got)
   136  	}
   137  	if got, want := ruleIsEnabled(rule, f.GetMessageTypes()[1].GetFields()[0], nil, nil, false), true; got != want {
   138  		t.Errorf("Expected the foo field to return %v from ruleIsEnabled; got %v", want, got)
   139  	}
   140  }
   141  
   142  func TestRuleIsEnabledDeprecated(t *testing.T) {
   143  	// Create a rule that we can check enabled status on.
   144  	rule := &FieldRule{
   145  		Name: RuleName("test"),
   146  		LintField: func(f *desc.FieldDescriptor) []Problem {
   147  			return nil
   148  		},
   149  	}
   150  
   151  	for _, test := range []struct {
   152  		name            string
   153  		msgDeprecated   bool
   154  		fieldDeprecated bool
   155  		enabled         bool
   156  	}{
   157  		{"Both", true, true, false},
   158  		{"Message", true, false, false},
   159  		{"Field", false, true, false},
   160  		{"Neither", false, false, true},
   161  	} {
   162  		t.Run(test.name, func(t *testing.T) {
   163  			// Build a proto with a message and field, possibly deprecated.
   164  			f, err := builder.NewFile("test.proto").AddMessage(
   165  				builder.NewMessage("Foo").SetOptions(&dpb.MessageOptions{
   166  					Deprecated: &test.msgDeprecated,
   167  				}).AddField(builder.NewField("bar", builder.FieldTypeBool()).SetOptions(
   168  					&dpb.FieldOptions{Deprecated: &test.fieldDeprecated},
   169  				)),
   170  			).Build()
   171  			if err != nil {
   172  				t.Fatalf("Error building test file: %q", err)
   173  			}
   174  			if got, want := ruleIsEnabled(rule, f.GetMessageTypes()[0].GetFields()[0], nil, nil, false), test.enabled; got != want {
   175  				t.Errorf("Expected the foo field to return %v from ruleIsEnabled; got %v", want, got)
   176  			}
   177  		})
   178  	}
   179  }