Skip to content

Commit cbdbf63

Browse files
authored
Allow users to set examples without constraints in PROTOVALIDATE lint rule (#3831)
1 parent de92461 commit cbdbf63

File tree

12 files changed

+175
-79
lines changed

12 files changed

+175
-79
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- Fix type filtering on `buf generate` for empty files, files with no declared types.
99
- Fix CEL check on `buf lint` for predefined `rules` variables.
1010
- Fix `buf config migrate` to filter out removed rules.
11+
- Allow users to set examples without constraints in `PROTOVALIDATE` lint rule.
1112
- Add ppc64le binaries for Linux to releases.
1213

1314
## [v1.53.0] - 2025-04-21

private/bufpkg/bufcheck/bufcheckserver/internal/buflintvalidate/field.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -759,8 +759,8 @@ func checkExampleValues(
759759
})
760760
}
761761
if !hasRules {
762-
adder.addForPathf(pathToExampleValues, "example value is specified by there are no constraints defined")
763-
// No need to check if example values satifisy constraints, because there is none.
762+
// Since there are no constraints to check example values against, we already checked
763+
// if the proper example type has been set on the field, so we can return here.
764764
return nil
765765
}
766766
// For each example value, instantiate a message of its containing message's type

private/bufpkg/bufcheck/lint_test.go

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -586,10 +586,12 @@ func TestRunProtovalidate(t *testing.T) {
586586
bufanalysistesting.NewFileAnnotation(t, "bool.proto", 19, 31, 19, 69, "PROTOVALIDATE"),
587587
bufanalysistesting.NewFileAnnotation(t, "bool.proto", 20, 50, 20, 88, "PROTOVALIDATE"),
588588
bufanalysistesting.NewFileAnnotation(t, "bool.proto", 27, 5, 27, 46, "PROTOVALIDATE"),
589+
bufanalysistesting.NewFileAnnotation(t, "bool.proto", 33, 45, 33, 89, "PROTOVALIDATE"),
589590
bufanalysistesting.NewFileAnnotation(t, "bytes.proto", 21, 5, 21, 48, "PROTOVALIDATE"),
590591
bufanalysistesting.NewFileAnnotation(t, "bytes.proto", 26, 5, 26, 45, "PROTOVALIDATE"),
591592
bufanalysistesting.NewFileAnnotation(t, "bytes.proto", 31, 5, 31, 45, "PROTOVALIDATE"),
592593
bufanalysistesting.NewFileAnnotation(t, "bytes.proto", 43, 5, 43, 65, "PROTOVALIDATE"),
594+
bufanalysistesting.NewFileAnnotation(t, "bytes.proto", 46, 45, 46, 106, "PROTOVALIDATE"),
593595
bufanalysistesting.NewFileAnnotation(t, "cel_field.proto", 10, 37, 14, 4, "PROTOVALIDATE"),
594596
bufanalysistesting.NewFileAnnotation(t, "cel_field.proto", 17, 5, 21, 6, "PROTOVALIDATE"),
595597
bufanalysistesting.NewFileAnnotation(t, "cel_field.proto", 29, 5, 33, 6, "PROTOVALIDATE"),
@@ -624,8 +626,10 @@ func TestRunProtovalidate(t *testing.T) {
624626
bufanalysistesting.NewFileAnnotation(t, "duration.proto", 122, 5, 125, 6, "PROTOVALIDATE"),
625627
bufanalysistesting.NewFileAnnotation(t, "duration.proto", 127, 5, 130, 6, "PROTOVALIDATE"),
626628
bufanalysistesting.NewFileAnnotation(t, "duration.proto", 155, 5, 158, 6, "PROTOVALIDATE"),
629+
bufanalysistesting.NewFileAnnotation(t, "duration.proto", 164, 64, 164, 126, "PROTOVALIDATE"),
627630
bufanalysistesting.NewFileAnnotation(t, "enum.proto", 28, 5, 28, 40, "PROTOVALIDATE"),
628631
bufanalysistesting.NewFileAnnotation(t, "enum.proto", 36, 5, 36, 42, "PROTOVALIDATE"),
632+
bufanalysistesting.NewFileAnnotation(t, "enum.proto", 39, 47, 39, 102, "PROTOVALIDATE"),
629633
bufanalysistesting.NewFileAnnotation(t, "extension.proto", 25, 7, 25, 43, "PROTOVALIDATE"),
630634
bufanalysistesting.NewFileAnnotation(t, "extension.proto", 30, 7, 30, 58, "PROTOVALIDATE"),
631635
bufanalysistesting.NewFileAnnotation(t, "extension.proto", 40, 5, 40, 41, "PROTOVALIDATE"),
@@ -644,6 +648,10 @@ func TestRunProtovalidate(t *testing.T) {
644648
bufanalysistesting.NewFileAnnotation(t, "map.proto", 56, 41, 56, 80, "PROTOVALIDATE"),
645649
bufanalysistesting.NewFileAnnotation(t, "map.proto", 70, 5, 70, 53, "PROTOVALIDATE"),
646650
bufanalysistesting.NewFileAnnotation(t, "map.proto", 71, 5, 71, 77, "PROTOVALIDATE"),
651+
bufanalysistesting.NewFileAnnotation(t, "map.proto", 78, 5, 78, 57, "PROTOVALIDATE"),
652+
bufanalysistesting.NewFileAnnotation(t, "map.proto", 83, 5, 83, 55, "PROTOVALIDATE"),
653+
bufanalysistesting.NewFileAnnotation(t, "map.proto", 86, 5, 86, 57, "PROTOVALIDATE"),
654+
bufanalysistesting.NewFileAnnotation(t, "map.proto", 87, 5, 87, 55, "PROTOVALIDATE"),
647655
bufanalysistesting.NewFileAnnotation(t, "message.proto", 20, 3, 20, 49, "PROTOVALIDATE"),
648656
bufanalysistesting.NewFileAnnotation(t, "message.proto", 27, 5, 27, 51, "PROTOVALIDATE"),
649657
bufanalysistesting.NewFileAnnotation(t, "number.proto", 20, 5, 20, 42, "PROTOVALIDATE"),
@@ -665,20 +673,34 @@ func TestRunProtovalidate(t *testing.T) {
665673
bufanalysistesting.NewFileAnnotation(t, "number.proto", 139, 5, 139, 50, "PROTOVALIDATE"),
666674
bufanalysistesting.NewFileAnnotation(t, "number.proto", 142, 5, 142, 52, "PROTOVALIDATE"),
667675
bufanalysistesting.NewFileAnnotation(t, "number.proto", 160, 5, 160, 44, "PROTOVALIDATE"),
668-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 170, 5, 170, 45, "PROTOVALIDATE"),
669-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 180, 5, 180, 45, "PROTOVALIDATE"),
670-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 190, 5, 190, 43, "PROTOVALIDATE"),
671-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 200, 5, 200, 43, "PROTOVALIDATE"),
672-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 210, 5, 210, 46, "PROTOVALIDATE"),
673-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 220, 5, 220, 46, "PROTOVALIDATE"),
674-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 230, 5, 230, 44, "PROTOVALIDATE"),
675-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 240, 5, 240, 44, "PROTOVALIDATE"),
676-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 250, 5, 250, 44, "PROTOVALIDATE"),
677-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 260, 5, 260, 44, "PROTOVALIDATE"),
678-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 270, 5, 270, 43, "PROTOVALIDATE"),
679-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 280, 5, 280, 43, "PROTOVALIDATE"),
680-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 290, 5, 290, 44, "PROTOVALIDATE"),
681-
bufanalysistesting.NewFileAnnotation(t, "number.proto", 300, 5, 300, 44, "PROTOVALIDATE"),
676+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 163, 53, 163, 91, "PROTOVALIDATE"),
677+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 172, 5, 172, 45, "PROTOVALIDATE"),
678+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 180, 54, 180, 95, "PROTOVALIDATE"),
679+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 184, 5, 184, 45, "PROTOVALIDATE"),
680+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 194, 5, 194, 43, "PROTOVALIDATE"),
681+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 197, 51, 197, 91, "PROTOVALIDATE"),
682+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 206, 5, 206, 43, "PROTOVALIDATE"),
683+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 209, 51, 209, 91, "PROTOVALIDATE"),
684+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 218, 5, 218, 46, "PROTOVALIDATE"),
685+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 221, 57, 221, 97, "PROTOVALIDATE"),
686+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 230, 5, 230, 46, "PROTOVALIDATE"),
687+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 233, 57, 233, 97, "PROTOVALIDATE"),
688+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 242, 5, 242, 44, "PROTOVALIDATE"),
689+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 245, 52, 245, 90, "PROTOVALIDATE"),
690+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 254, 5, 254, 44, "PROTOVALIDATE"),
691+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 257, 52, 257, 90, "PROTOVALIDATE"),
692+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 266, 5, 266, 44, "PROTOVALIDATE"),
693+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 269, 52, 269, 90, "PROTOVALIDATE"),
694+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 278, 5, 278, 44, "PROTOVALIDATE"),
695+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 281, 52, 281, 90, "PROTOVALIDATE"),
696+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 290, 5, 290, 43, "PROTOVALIDATE"),
697+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 293, 77, 293, 116, "PROTOVALIDATE"),
698+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 302, 5, 302, 43, "PROTOVALIDATE"),
699+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 305, 77, 305, 116, "PROTOVALIDATE"),
700+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 314, 5, 314, 44, "PROTOVALIDATE"),
701+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 317, 79, 317, 117, "PROTOVALIDATE"),
702+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 326, 5, 326, 44, "PROTOVALIDATE"),
703+
bufanalysistesting.NewFileAnnotation(t, "number.proto", 329, 79, 329, 117, "PROTOVALIDATE"),
682704
bufanalysistesting.NewFileAnnotation(t, "oneof.proto", 13, 7, 13, 43, "PROTOVALIDATE"),
683705
bufanalysistesting.NewFileAnnotation(t, "oneof.proto", 19, 7, 19, 43, "PROTOVALIDATE"),
684706
bufanalysistesting.NewFileAnnotation(t, "repeated.proto", 25, 5, 25, 48, "PROTOVALIDATE"),
@@ -689,6 +711,7 @@ func TestRunProtovalidate(t *testing.T) {
689711
bufanalysistesting.NewFileAnnotation(t, "repeated.proto", 53, 26, 53, 74, "PROTOVALIDATE"),
690712
bufanalysistesting.NewFileAnnotation(t, "repeated.proto", 55, 42, 55, 76, "PROTOVALIDATE"),
691713
bufanalysistesting.NewFileAnnotation(t, "repeated.proto", 65, 5, 65, 62, "PROTOVALIDATE"),
714+
bufanalysistesting.NewFileAnnotation(t, "repeated.proto", 68, 55, 68, 110, "PROTOVALIDATE"),
692715
bufanalysistesting.NewFileAnnotation(t, "string.proto", 31, 5, 31, 46, "PROTOVALIDATE"),
693716
bufanalysistesting.NewFileAnnotation(t, "string.proto", 36, 5, 36, 44, "PROTOVALIDATE"),
694717
bufanalysistesting.NewFileAnnotation(t, "string.proto", 41, 5, 41, 44, "PROTOVALIDATE"),
@@ -717,6 +740,7 @@ func TestRunProtovalidate(t *testing.T) {
717740
bufanalysistesting.NewFileAnnotation(t, "string.proto", 133, 5, 133, 45, "PROTOVALIDATE"),
718741
bufanalysistesting.NewFileAnnotation(t, "string.proto", 152, 5, 152, 51, "PROTOVALIDATE"),
719742
bufanalysistesting.NewFileAnnotation(t, "string.proto", 154, 5, 154, 49, "PROTOVALIDATE"),
743+
bufanalysistesting.NewFileAnnotation(t, "string.proto", 157, 46, 157, 86, "PROTOVALIDATE"),
720744
bufanalysistesting.NewFileAnnotation(t, "timestamp.proto", 57, 5, 60, 6, "PROTOVALIDATE"),
721745
bufanalysistesting.NewFileAnnotation(t, "timestamp.proto", 61, 5, 64, 6, "PROTOVALIDATE"),
722746
bufanalysistesting.NewFileAnnotation(t, "timestamp.proto", 68, 5, 71, 6, "PROTOVALIDATE"),
@@ -731,6 +755,7 @@ func TestRunProtovalidate(t *testing.T) {
731755
bufanalysistesting.NewFileAnnotation(t, "timestamp.proto", 142, 5, 145, 6, "PROTOVALIDATE"),
732756
bufanalysistesting.NewFileAnnotation(t, "timestamp.proto", 150, 5, 153, 6, "PROTOVALIDATE"),
733757
bufanalysistesting.NewFileAnnotation(t, "timestamp.proto", 157, 5, 160, 6, "PROTOVALIDATE"),
758+
bufanalysistesting.NewFileAnnotation(t, "timestamp.proto", 198, 65, 201, 4, "PROTOVALIDATE"),
734759
)
735760
}
736761

private/bufpkg/bufcheck/testdata/lint/protovalidate/proto/bool.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,9 @@ message BoolTest {
2626
(buf.validate.field).bool.const = true,
2727
(buf.validate.field).bool.example = false
2828
];
29+
bool valid_no_constraint_example = 6 [
30+
(buf.validate.field).bool.example = true,
31+
(buf.validate.field).bool.example = false
32+
];
33+
bool invalid_example_type_mistmatch = 12 [(buf.validate.field).string.example = "true"];
2934
}

private/bufpkg/bufcheck/testdata/lint/protovalidate/proto/bytes.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,6 @@ message BytesTest {
4242
// invalid, fails one of the rules
4343
(buf.validate.field).bytes.example = "ÀÀÀÀÀÇÇÇÇÇÇÇÇÅÅÅÅÅÅÅÅ"
4444
];
45+
bytes valid_no_constraint_example = 11 [(buf.validate.field).bytes.example = "ÀÀÀÀÀÇÇÇÇÇÇÇÇÅÅÅÅÅÅÅÅ"];
46+
bytes invalid_example_type_mismatch = 12 [(buf.validate.field).string.example = "ÀÀÀÀÀÇÇÇÇÇÇÇÇÅÅÅÅÅÅÅÅ"];
4547
}

private/bufpkg/bufcheck/testdata/lint/protovalidate/proto/duration.proto

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,148 +13,153 @@ message DurationTest {
1313
// valid
1414
google.protobuf.Duration valid_range_1 = 3 [
1515
(buf.validate.field).duration.gt = {
16-
seconds: 5,
16+
seconds: 5
1717
nanos: 1
1818
},
1919
(buf.validate.field).duration.lt = {
20-
seconds: 5,
20+
seconds: 5
2121
nanos: 2
2222
}
2323
];
2424
// it's ok to have gt > lt
2525
google.protobuf.Duration valid_range_2 = 4 [
2626
(buf.validate.field).duration.gt = {
27-
seconds: 5,
27+
seconds: 5
2828
nanos: 2
2929
},
3030
(buf.validate.field).duration.lte = {
31-
seconds: 5,
31+
seconds: 5
3232
nanos: 1
3333
}
3434
];
3535
google.protobuf.Duration valid_range_3 = 5 [
3636
(buf.validate.field).duration.gte = {
37-
seconds: -5,
37+
seconds: -5
3838
nanos: -20
3939
},
4040
(buf.validate.field).duration.lt = {
41-
seconds: -4,
41+
seconds: -4
4242
nanos: -1
4343
}
4444
];
4545
google.protobuf.Duration valid_range_4 = 6 [
4646
(buf.validate.field).duration.gte = {
47-
seconds: -4,
47+
seconds: -4
4848
nanos: -2
4949
},
5050
(buf.validate.field).duration.lte = {
51-
seconds: -4,
51+
seconds: -4
5252
nanos: -1
5353
}
5454
];
5555
google.protobuf.Duration invalid_range_1 = 7 [
5656
// gt == lte
5757
(buf.validate.field).duration.gt = {
58-
seconds: 1,
58+
seconds: 1
5959
nanos: 2
6060
},
6161
(buf.validate.field).duration.lte = {
62-
seconds: 1,
62+
seconds: 1
6363
nanos: 2
6464
}
6565
];
6666
google.protobuf.Duration invalid_range_2 = 8 [
6767
// gte == lt
6868
(buf.validate.field).duration.gte = {
69-
seconds: 2,
69+
seconds: 2
7070
nanos: 1
7171
},
7272
(buf.validate.field).duration.lt = {
73-
seconds: 2,
73+
seconds: 2
7474
nanos: 1
7575
}
7676
];
7777
google.protobuf.Duration invalid_range_3 = 9 [
7878
// gt == lt
7979
(buf.validate.field).duration.gt = {
80-
seconds: -2,
80+
seconds: -2
8181
nanos: -1
8282
},
8383
(buf.validate.field).duration.lt = {
84-
seconds: -2,
84+
seconds: -2
8585
nanos: -1
8686
}
8787
];
8888
google.protobuf.Duration equal_lte_gte = 10 [
8989
// lte == gte
9090
(buf.validate.field).duration.gte = {
91-
seconds: -1,
91+
seconds: -1
9292
nanos: -1
9393
},
9494
(buf.validate.field).duration.lte = {
95-
seconds: -1,
95+
seconds: -1
9696
nanos: -1
9797
}
9898
];
9999
google.protobuf.Duration invalid_Duration = 11 [
100100
(buf.validate.field).duration.gte = {
101-
seconds: 1,
101+
seconds: 1
102102
nanos: 1
103103
},
104104
// seconds and nanos must have the same sign
105105
(buf.validate.field).duration.lte = {
106-
seconds: 1,
106+
seconds: 1
107107
nanos: -1
108108
}
109109
];
110110
google.protobuf.Duration in_range_Duration = 13 [
111111
(buf.validate.field).duration.gte = {
112-
seconds: -9223372036,
112+
seconds: -9223372036
113113
nanos: -854775428
114114
},
115115
(buf.validate.field).duration.lte = {
116-
seconds: 9223372036,
116+
seconds: 9223372036
117117
nanos: 854775428
118118
}
119119
];
120120
google.protobuf.Duration out_of_range = 14 [
121121
// 1 nanosecond lower than the minimum value allowed
122122
(buf.validate.field).duration.gte = {
123-
seconds: -9223372036,
123+
seconds: -9223372036
124124
nanos: -854775429
125125
},
126126
// 1 nanosecond higher than the maximum value allowed
127127
(buf.validate.field).duration.lte = {
128-
seconds: 9223372036,
128+
seconds: 9223372036
129129
nanos: 854775429
130130
}
131131
];
132132
google.protobuf.Duration valid_example = 20 [
133133
(buf.validate.field).duration.lt = {
134-
seconds: 17,
134+
seconds: 17
135135
nanos: 25
136136
},
137137
(buf.validate.field).duration.gt = {
138-
seconds: 5,
138+
seconds: 5
139139
nanos: 1
140140
},
141141
(buf.validate.field).duration.example = {
142-
seconds: 7,
142+
seconds: 7
143143
nanos: 3
144144
}
145145
];
146146
google.protobuf.Duration invalid_example = 21 [
147147
(buf.validate.field).duration.lt = {
148-
seconds: 17,
148+
seconds: 17
149149
nanos: 25
150150
},
151151
(buf.validate.field).duration.gt = {
152-
seconds: 5,
152+
seconds: 5
153153
nanos: 1
154154
},
155155
(buf.validate.field).duration.example = {
156-
seconds: 2,
156+
seconds: 2
157157
nanos: 3
158158
}
159159
];
160+
google.protobuf.Duration valid_no_constraint_example = 22 [(buf.validate.field).duration.example = {
161+
seconds: 2
162+
nanos: 3
163+
}];
164+
google.protobuf.Duration invalid_no_constraint_example = 23 [(buf.validate.field).timestamp.example = {seconds: 1672444800}];
160165
}

private/bufpkg/bufcheck/testdata/lint/protovalidate/proto/enum.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,6 @@ message EnumTest {
3535
(buf.validate.field).enum.defined_only = true,
3636
(buf.validate.field).enum.example = 4
3737
];
38+
TestEnum valid_no_constraint_example = 8 [(buf.validate.field).enum.example = 2];
39+
TestEnum invalid_no_constraint_example = 9 [(buf.validate.field).string.example = "TEST_ENUM_FIRST"];
3840
}

private/bufpkg/bufcheck/testdata/lint/protovalidate/proto/map.proto

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,20 @@ message MapTest {
7070
(buf.validate.field).map.keys.int64.example = -1,
7171
(buf.validate.field).map.values.string.example = "this_is_a_long_string"
7272
];
73+
map<int64, string> valid_keys_values_no_constraint_example = 13 [
74+
(buf.validate.field).map.keys.int64.example = -1,
75+
(buf.validate.field).map.values.string.example = "good"
76+
];
77+
map<int64, string> invalid_keys_valid_values_no_constriant_example = 16 [
78+
(buf.validate.field).map.keys.string.example = "bad",
79+
(buf.validate.field).map.values.string.example = "good"
80+
];
81+
map<int64, string> valid_keys_invalid_values_no_constriant_example = 17 [
82+
(buf.validate.field).map.keys.int64.example = 1,
83+
(buf.validate.field).map.values.int64.example = -1
84+
];
85+
map<int64, string> invalid_keys_invalid_values_no_constriant_example = 18 [
86+
(buf.validate.field).map.keys.string.example = "bad",
87+
(buf.validate.field).map.values.int64.example = -1
88+
];
7389
}

0 commit comments

Comments
 (0)