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 }