19
19
import static com .google .common .truth .extensions .proto .FieldScopeUtil .asList ;
20
20
21
21
import com .google .protobuf .Descriptors .FieldDescriptor ;
22
+ import com .google .protobuf .ExtensionRegistry ;
22
23
import com .google .protobuf .Message ;
24
+ import com .google .protobuf .TypeRegistry ;
23
25
24
26
/** Factory class for {@link FieldScope} instances. */
25
27
public final class FieldScopes {
@@ -66,7 +68,58 @@ public final class FieldScopes {
66
68
// Alternatively II, add Scope.PARTIAL support to ProtoFluentEquals, but with a different name and
67
69
// explicit documentation that it may cause issues with Proto 3.
68
70
public static FieldScope fromSetFields (Message message ) {
69
- return FieldScopeImpl .createFromSetFields (message );
71
+ return fromSetFields (
72
+ message , AnyUtils .defaultTypeRegistry (), AnyUtils .defaultExtensionRegistry ());
73
+ }
74
+
75
+ /**
76
+ * Returns a {@link FieldScope} which is constrained to precisely those specific field paths that
77
+ * are explicitly set in the message. Note that, for version 3 protobufs, such a {@link
78
+ * FieldScope} will omit fields in the provided message which are set to default values.
79
+ *
80
+ * <p>This can be used limit the scope of a comparison to a complex set of fields in a very brief
81
+ * statement. Often, {@code message} is the expected half of a comparison about to be performed.
82
+ *
83
+ * <p>Example usage:
84
+ *
85
+ * <pre>{@code
86
+ * Foo actual = Foo.newBuilder().setBar(3).setBaz(4).build();
87
+ * Foo expected = Foo.newBuilder().setBar(3).setBaz(5).build();
88
+ * // Fails, because actual.getBaz() != expected.getBaz().
89
+ * assertThat(actual).isEqualTo(expected);
90
+ *
91
+ * Foo scope = Foo.newBuilder().setBar(2).build();
92
+ * // Succeeds, because only the field 'bar' is compared.
93
+ * assertThat(actual).withPartialScope(FieldScopes.fromSetFields(scope)).isEqualTo(expected);
94
+ *
95
+ * }</pre>
96
+ *
97
+ * <p>The returned {@link FieldScope} does not respect repeated field indices nor map keys. For
98
+ * example, if the provided message sets different field values for different elements of a
99
+ * repeated field, like so:
100
+ *
101
+ * <pre>{@code
102
+ * sub_message: {
103
+ * foo: "foo"
104
+ * }
105
+ * sub_message: {
106
+ * bar: "bar"
107
+ * }
108
+ * }</pre>
109
+ *
110
+ * <p>The {@link FieldScope} will contain {@code sub_message.foo} and {@code sub_message.bar} for
111
+ * *all* repeated {@code sub_messages}, including those beyond index 1.
112
+ *
113
+ * <p>If there are {@code google.protobuf.Any} protos anywhere within these messages, they will be
114
+ * unpacked using the provided {@link TypeRegistry} and {@link ExtensionRegistry} to determine
115
+ * which fields within them should be compared.
116
+ *
117
+ * @see ProtoFluentAssertion#unpackingAnyUsing
118
+ * @since 1.2
119
+ */
120
+ public static FieldScope fromSetFields (
121
+ Message message , TypeRegistry typeRegistry , ExtensionRegistry extensionRegistry ) {
122
+ return FieldScopeImpl .createFromSetFields (message , typeRegistry , extensionRegistry );
70
123
}
71
124
72
125
/**
@@ -89,7 +142,29 @@ public static FieldScope fromSetFields(
89
142
* or the {@link FieldScope} for the merge of all the messages. These are equivalent.
90
143
*/
91
144
public static FieldScope fromSetFields (Iterable <? extends Message > messages ) {
92
- return FieldScopeImpl .createFromSetFields (messages );
145
+ return fromSetFields (
146
+ messages , AnyUtils .defaultTypeRegistry (), AnyUtils .defaultExtensionRegistry ());
147
+ }
148
+
149
+ /**
150
+ * Creates a {@link FieldScope} covering the fields set in every message in the provided list of
151
+ * messages, with the same semantics as in {@link #fromSetFields(Message)}.
152
+ *
153
+ * <p>This can be thought of as the union of the {@link FieldScope}s for each individual message,
154
+ * or the {@link FieldScope} for the merge of all the messages. These are equivalent.
155
+ *
156
+ * <p>If there are {@code google.protobuf.Any} protos anywhere within these messages, they will be
157
+ * unpacked using the provided {@link TypeRegistry} and {@link ExtensionRegistry} to determine
158
+ * which fields within them should be compared.
159
+ *
160
+ * @see ProtoFluentAssertion#unpackingAnyUsing
161
+ * @since 1.2
162
+ */
163
+ public static FieldScope fromSetFields (
164
+ Iterable <? extends Message > messages ,
165
+ TypeRegistry typeRegistry ,
166
+ ExtensionRegistry extensionRegistry ) {
167
+ return FieldScopeImpl .createFromSetFields (messages , typeRegistry , extensionRegistry );
93
168
}
94
169
95
170
/**
0 commit comments