|
| 1 | +# Copyright 2023-2026 Buf Technologies, Inc. |
| 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 | +# http://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 | +"""Benchmarks for CEL rule evaluation, by rule category. |
| 16 | +
|
| 17 | +Run with `uv run poe bench`. This file only touches the public protovalidate |
| 18 | +API, so the same file produces comparable numbers on any branch (e.g. to |
| 19 | +compare CEL backends, check out the baseline branch, drop this file in, and |
| 20 | +run it there). |
| 21 | +
|
| 22 | +Each benchmark measures steady-state `collect_violations` on a shared |
| 23 | +`Validator`, so per-message-type compilation is warmed up by the calibration |
| 24 | +phase and the numbers reflect rule evaluation, not compilation. |
| 25 | +""" |
| 26 | + |
| 27 | +import time |
| 28 | + |
| 29 | +from google.protobuf import any_pb2, duration_pb2, timestamp_pb2 |
| 30 | + |
| 31 | +import protovalidate |
| 32 | +from buf.validate.conformance.cases import ( |
| 33 | + kitchen_sink_pb2, |
| 34 | + numbers_pb2, |
| 35 | + repeated_pb2, |
| 36 | + strings_pb2, |
| 37 | + wkt_timestamp_pb2, |
| 38 | +) |
| 39 | + |
| 40 | +_validator = protovalidate.Validator() |
| 41 | + |
| 42 | + |
| 43 | +def _run(benchmark, msg, *, expected_violations: int = 0): |
| 44 | + violations = benchmark(_validator.collect_violations, msg) |
| 45 | + assert len(violations) == expected_violations |
| 46 | + |
| 47 | + |
| 48 | +def test_int64_range_valid(benchmark): |
| 49 | + _run(benchmark, numbers_pb2.Int64GTELTE(val=200)) |
| 50 | + |
| 51 | + |
| 52 | +def test_int64_range_invalid(benchmark): |
| 53 | + _run(benchmark, numbers_pb2.Int64GTELTE(val=300), expected_violations=1) |
| 54 | + |
| 55 | + |
| 56 | +def test_string_len_valid(benchmark): |
| 57 | + _run(benchmark, strings_pb2.StringLen(val="foo")) |
| 58 | + |
| 59 | + |
| 60 | +def test_string_email_valid(benchmark): |
| 61 | + _run(benchmark, strings_pb2.StringEmail(val="foo@example.com")) |
| 62 | + |
| 63 | + |
| 64 | +def test_string_pattern_valid(benchmark): |
| 65 | + _run(benchmark, strings_pb2.StringPattern(val="Foo123")) |
| 66 | + |
| 67 | + |
| 68 | +def test_repeated_unique_valid(benchmark): |
| 69 | + _run(benchmark, repeated_pb2.RepeatedUnique(val=["a", "b", "c", "d", "e"])) |
| 70 | + |
| 71 | + |
| 72 | +def test_timestamp_gt_now_valid(benchmark): |
| 73 | + ts = timestamp_pb2.Timestamp() |
| 74 | + ts.FromSeconds(int(time.time()) + 3600) |
| 75 | + _run(benchmark, wkt_timestamp_pb2.TimestampGTNow(val=ts)) |
| 76 | + |
| 77 | + |
| 78 | +def _kitchen_sink_msg() -> kitchen_sink_pb2.KitchenSinkMessage: |
| 79 | + inner = duration_pb2.Duration(seconds=1) |
| 80 | + any_val = any_pb2.Any() |
| 81 | + any_val.Pack(inner) |
| 82 | + return kitchen_sink_pb2.KitchenSinkMessage( |
| 83 | + val=kitchen_sink_pb2.ComplexTestMsg( |
| 84 | + const="abcd", |
| 85 | + int_const=5, |
| 86 | + bool_const=False, |
| 87 | + float_val={"value": 1.0}, |
| 88 | + dur_val=duration_pb2.Duration(seconds=3), |
| 89 | + ts_val=timestamp_pb2.Timestamp(seconds=100), |
| 90 | + float_const=7.0, |
| 91 | + double_in=123, |
| 92 | + enum_const=kitchen_sink_pb2.COMPLEX_TEST_ENUM_TWO, |
| 93 | + any_val=any_val, |
| 94 | + rep_ts_val=[timestamp_pb2.Timestamp(nanos=2000000)], |
| 95 | + map_val={-1: "a", -2: "b"}, |
| 96 | + bytes_val=b"\x00\x99", |
| 97 | + x="oneof", |
| 98 | + ) |
| 99 | + ) |
| 100 | + |
| 101 | + |
| 102 | +def test_kitchen_sink_valid(benchmark): |
| 103 | + _run(benchmark, _kitchen_sink_msg()) |
0 commit comments