Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,10 @@ mavenPublishing {

dependencies {
annotationProcessor(libs.nullaway)
api(libs.jspecify)
api(libs.protobuf.java)
implementation(enforcedPlatform(libs.cel))
implementation(libs.cel.core)
implementation(libs.guava)
implementation(libs.ipaddress)
implementation(libs.jakarta.mail.api)

buf("build.buf:buf:${libs.versions.buf.get()}:${osdetector.classifier}@exe")

Expand All @@ -271,5 +269,5 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")

errorprone(libs.errorprone)
errorprone(libs.errorprone.core)
}
10 changes: 8 additions & 2 deletions conformance/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ plugins {
alias(libs.plugins.osdetector)
}

// Conformance tests aren't bound by lowest common library version.
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}

val buf: Configuration by configurations.creating

tasks.register("configureBuf") {
Expand Down Expand Up @@ -116,7 +122,7 @@ configure<SpotlessExtension> {

dependencies {
implementation(project(":"))
implementation(libs.guava)
implementation(libs.errorprone.annotations)
implementation(libs.protobuf.java)

implementation(libs.assertj)
Expand All @@ -127,5 +133,5 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")

errorprone(libs.errorprone)
errorprone(libs.errorprone.core)
}
218 changes: 0 additions & 218 deletions conformance/expected-failures.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,224 +107,6 @@ custom_constraints:
#ERROR: <input>:1:1: expression of type 'int' cannot be range of a comprehension (must be list, map, or dynamic)
# | this.all(e, e == 1)
# | ^
library/is_email:
- invalid/non_ascii
# input: [type.googleapis.com/buf.validate.conformance.cases.IsEmail]:{val:"µ@example.com"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_email"
# got: valid
- invalid/quoted-string/a
# input: [type.googleapis.com/buf.validate.conformance.cases.IsEmail]:{val:"\"foo bar\"@example.com"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_email"
# got: valid
- invalid/quoted-string/b
# input: [type.googleapis.com/buf.validate.conformance.cases.IsEmail]:{val:"\"foo..bar\"@example.com"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_email"
# got: valid
- valid/empty_atext
# input: [type.googleapis.com/buf.validate.conformance.cases.IsEmail]:{val:".@example.com"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_email"
# message: ""
- valid/exhaust_atext
# input: [type.googleapis.com/buf.validate.conformance.cases.IsEmail]:{val:"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'*+-/=?^_`{|}~@example.com"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_email"
# message: ""
- valid/label_all_digits
# input: [type.googleapis.com/buf.validate.conformance.cases.IsEmail]:{val:"foo@0.1.2.3.4.5.6.7.8.9"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_email"
# message: ""
- valid/multiple_empty_atext
# input: [type.googleapis.com/buf.validate.conformance.cases.IsEmail]:{val:"...@example.com"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_email"
# message: ""
library/is_host_and_port:
- port_required/false/invalid/ipv6_zone-id_too_short
# input: [type.googleapis.com/buf.validate.conformance.cases.IsHostAndPort]:{val:"[::1%]"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_host_and_port"
# got: valid
- port_required/false/invalid/port_number_sign
# input: [type.googleapis.com/buf.validate.conformance.cases.IsHostAndPort]:{val:"example.com:+0"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_host_and_port"
# got: valid
- port_required/false/valid/ipv6_embedded_ipv4
# input: [type.googleapis.com/buf.validate.conformance.cases.IsHostAndPort]:{val:"[0:0:0:0:0:ffff:192.1.56.10]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_host_and_port"
# message: ""
- port_required/false/valid/ipv6_with_zone-id
# input: [type.googleapis.com/buf.validate.conformance.cases.IsHostAndPort]:{val:"[::1%foo]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_host_and_port"
# message: ""
- port_required/false/valid/ipv6_zone-id_any_non_null_character
# input: [type.googleapis.com/buf.validate.conformance.cases.IsHostAndPort]:{val:"[::1%% :x\x1f]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_host_and_port"
# message: ""
- port_required/true/invalid/port_number_sign
# input: [type.googleapis.com/buf.validate.conformance.cases.IsHostAndPort]:{val:"example.com:+0" port_required:true}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_host_and_port"
# got: valid
library/is_ip:
- version/omitted/invalid/ipv6_zone-id
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIp]:{val:"::1%"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_ip"
# got: valid
- version/omitted/valid/ipv6_zone-id
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIp]:{val:"::1%foo"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_ip"
# message: ""
- version/omitted/valid/ipv6_zone-id_any_non_null_character
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIp]:{val:"::1%% :x\x1f"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_ip"
# message: ""
library/is_ip_prefix:
- version/omitted/strict/omitted/invalid/ipv4_bad_leading_zero_in_prefix-length
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIpPrefix]:{val:"192.168.1.0/024"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_ip_prefix"
# got: valid
- version/omitted/strict/omitted/invalid/ipv4_prefix_leading_space
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIpPrefix]:{val:" 127.0.0.1/16"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_ip_prefix"
# got: valid
- version/omitted/strict/omitted/invalid/ipv4_prefix_trailing_space
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIpPrefix]:{val:"127.0.0.1/16 "}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_ip_prefix"
# got: valid
- version/omitted/strict/omitted/invalid/ipv6_bad_leading_zero_in_prefix-length
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIpPrefix]:{val:"2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF/024"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_ip_prefix"
# got: valid
- version/omitted/strict/omitted/invalid/ipv6_prefix_leading_space
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIpPrefix]:{val:" ::1/64"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_ip_prefix"
# got: valid
- version/omitted/strict/omitted/invalid/ipv6_prefix_trailing_space
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIpPrefix]:{val:"::1/64 "}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_ip_prefix"
# got: valid
- version/omitted/strict/omitted/invalid/ipv6_zone-id/a
# input: [type.googleapis.com/buf.validate.conformance.cases.IsIpPrefix]:{val:"::1%en1/64"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_ip_prefix"
# got: valid
library/is_uri:
- invalid/host/c
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://foo@你好.com"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/host_ipv6/a
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://2001:0db8:85a3:0000:0000:8a2e:0370:7334"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/host_ipv6_zone-id_empty
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[::1%25]"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/host_ipv6_zone-id_unquoted
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[::1%eth0]"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/host_reg-name_pct-encoded_invalid_utf8
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://foo%c3x%96"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/port/a
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://example.com:8a"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/port/b
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://example.com:x"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/userinfo_reserved_at
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://@@example.com"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- valid/host_ipfuture_exhaust
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[vF.-!$&'()*+,;=._~0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/host_ipfuture_long
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[v1234AF.x]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/host_ipfuture_short
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[v1.x]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/host_ipv6_zone-id_pct-encoded_ascii
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[::1%25foo%61%20%23]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/host_ipv6_zone-id_pct-encoded_utf8
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[::1%25foo%c3%96]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/path-empty
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"foo:"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
library/is_uri_ref:
- valid/empty_string
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUriRef]:{}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri_ref"
# message: ""
- valid/path-empty
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUriRef]:{}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri_ref"
# message: ""
standard_constraints/ignore:
- proto/2023/map/ignore_always/invalid/populated
# input: [type.googleapis.com/buf.validate.conformance.cases.EditionsMapIgnoreAlways]:{val:{key:1 value:1}}
Expand Down
Binary file added conformance/src/main/java/build/.DS_Store
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import build.buf.validate.conformance.harness.TestConformanceRequest;
import build.buf.validate.conformance.harness.TestConformanceResponse;
import build.buf.validate.conformance.harness.TestResult;
import com.google.common.base.Splitter;
import com.google.errorprone.annotations.FormatMethod;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
Expand All @@ -34,7 +33,6 @@
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.TypeRegistry;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {
Expand Down Expand Up @@ -84,8 +82,11 @@ static TestConformanceResponse testConformance(TestConformanceRequest request) {
static TestResult testCase(
Validator validator, Map<String, Descriptors.Descriptor> fileDescriptors, Any testCase)
throws InvalidProtocolBufferException {
List<String> urlParts = Splitter.on('/').limit(2).splitToList(testCase.getTypeUrl());
String fullName = urlParts.get(urlParts.size() - 1);
String fullName = testCase.getTypeUrl();
int slash = fullName.indexOf('/');
if (slash != -1) {
fullName = fullName.substring(slash + 1);
}
Descriptors.Descriptor descriptor = fileDescriptors.get(fullName);
if (descriptor == null) {
return unexpectedErrorResult("Unable to find descriptor: %s", fullName);
Expand Down
9 changes: 4 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
assertj = "3.27.3"
buf = "1.52.1"
cel = "0.5.1"
ipaddress = "5.5.1"
error-prone = "2.38.0"
junit = "5.12.2"
maven-publish = "0.31.0"
# When updating, make sure to update versions in the following files to match and regenerate code with 'make generate'.
Expand All @@ -17,10 +17,9 @@ assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" }
buf = { module = "build.buf:buf", version.ref = "buf" }
cel = { module = "org.projectnessie.cel:cel-bom", version.ref = "cel" }
cel-core = { module = "org.projectnessie.cel:cel-core" }
errorprone = { module = "com.google.errorprone:error_prone_core", version = "2.38.0" }
guava = { module = "com.google.guava:guava", version = "33.4.0-jre" }
ipaddress = { module = "com.github.seancfoley:ipaddress", version.ref = "ipaddress" }
jakarta-mail-api = { module = "jakarta.mail:jakarta.mail-api", version = "2.1.3" }
errorprone-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "error-prone" }
errorprone-core = { module = "com.google.errorprone:error_prone_core", version.ref = "error-prone" }
jspecify = { module ="org.jspecify:jspecify", version = "1.0.0" }
junit-bom = { module = "org.junit:junit-bom", version.ref = "junit" }
maven-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "maven-publish" }
nullaway = { module = "com.uber.nullaway:nullaway", version = "0.12.6" }
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/build/buf/protovalidate/CelPrograms.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import build.buf.protovalidate.exceptions.ExecutionException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import org.jspecify.annotations.Nullable;

/** Evaluator that executes a {@link CompiledProgram}. */
class CelPrograms implements Evaluator {
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/build/buf/protovalidate/CompiledProgram.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import build.buf.protovalidate.exceptions.ExecutionException;
import build.buf.validate.FieldPath;
import javax.annotation.Nullable;
import org.jspecify.annotations.Nullable;
import org.projectnessie.cel.Program;
import org.projectnessie.cel.common.types.Err;
import org.projectnessie.cel.common.types.ref.Val;
Expand Down Expand Up @@ -63,8 +63,7 @@ public CompiledProgram(
* violations.
* @throws ExecutionException If the evaluation of the CEL program fails with an error.
*/
@Nullable
public ConstraintViolation.Builder eval(Value fieldValue, Variable bindings)
public ConstraintViolation.@Nullable Builder eval(Value fieldValue, Variable bindings)
throws ExecutionException {
Program.EvalResult evalResult = program.eval(bindings);
Val val = evalResult.getVal();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/build/buf/protovalidate/ConstraintCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nullable;
import org.jspecify.annotations.Nullable;
import org.projectnessie.cel.Ast;
import org.projectnessie.cel.Env;
import org.projectnessie.cel.EnvOption;
Expand Down Expand Up @@ -199,7 +199,7 @@ public List<CompiledProgram> compile(
return celRules;
}

private @Nullable build.buf.validate.PredefinedConstraints getFieldConstraints(
private build.buf.validate.@Nullable PredefinedConstraints getFieldConstraints(
FieldDescriptor constraintFieldDesc) throws CompilationException {
DescriptorProtos.FieldOptions options = constraintFieldDesc.getOptions();
// If the protovalidate field option is unknown, reparse options using our extension registry.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import java.util.Deque;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nullable;
import org.jspecify.annotations.Nullable;

/**
* {@link ConstraintViolation} contains all of the collected information about an individual
Expand Down
Loading