FieldMaskTreeTest.java
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf.util;
32 
34 import com.google.protobuf.Message;
36 import protobuf_unittest.UnittestProto.NestedTestAllTypes;
37 import protobuf_unittest.UnittestProto.TestAllTypes;
38 import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
39 import protobuf_unittest.UnittestProto.TestRequired;
40 import protobuf_unittest.UnittestProto.TestRequiredMessage;
41 import junit.framework.TestCase;
42 
43 public class FieldMaskTreeTest extends TestCase {
44  public void testAddFieldPath() throws Exception {
45  FieldMaskTree tree = new FieldMaskTree();
46  assertEquals("", tree.toString());
47  tree.addFieldPath("");
48  assertEquals("", tree.toString());
49  // New branch.
50  tree.addFieldPath("foo");
51  assertEquals("foo", tree.toString());
52  // Redundant path.
53  tree.addFieldPath("foo");
54  assertEquals("foo", tree.toString());
55  // New branch.
56  tree.addFieldPath("bar.baz");
57  assertEquals("bar.baz,foo", tree.toString());
58  // Redundant sub-path.
59  tree.addFieldPath("foo.bar");
60  assertEquals("bar.baz,foo", tree.toString());
61  // New branch from a non-root node.
62  tree.addFieldPath("bar.quz");
63  assertEquals("bar.baz,bar.quz,foo", tree.toString());
64  // A path that matches several existing sub-paths.
65  tree.addFieldPath("bar");
66  assertEquals("bar,foo", tree.toString());
67  }
68 
69  public void testMergeFromFieldMask() throws Exception {
70  FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
71  assertEquals("bar.baz,bar.quz,foo", tree.toString());
72  tree.mergeFromFieldMask(FieldMaskUtil.fromString("foo.bar,bar"));
73  assertEquals("bar,foo", tree.toString());
74  }
75 
76  public void testIntersectFieldPath() throws Exception {
77  FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
78  FieldMaskTree result = new FieldMaskTree();
79  // Empty path.
80  tree.intersectFieldPath("", result);
81  assertEquals("", result.toString());
82  // Non-exist path.
83  tree.intersectFieldPath("quz", result);
84  assertEquals("", result.toString());
85  // Sub-path of an existing leaf.
86  tree.intersectFieldPath("foo.bar", result);
87  assertEquals("foo.bar", result.toString());
88  // Match an existing leaf node.
89  tree.intersectFieldPath("foo", result);
90  assertEquals("foo", result.toString());
91  // Non-exist path.
92  tree.intersectFieldPath("bar.foo", result);
93  assertEquals("foo", result.toString());
94  // Match a non-leaf node.
95  tree.intersectFieldPath("bar", result);
96  assertEquals("bar.baz,bar.quz,foo", result.toString());
97  }
98 
99  public void testMerge() throws Exception {
100  testMergeImpl(true);
101  testMergeImpl(false);
102  testMergeRequire(false);
103  testMergeRequire(true);
104  }
105 
106  private void merge(
107  FieldMaskTree tree,
108  Message source,
109  Message.Builder builder,
111  boolean useDynamicMessage)
112  throws Exception {
113  if (useDynamicMessage) {
114  Message.Builder newBuilder =
115  DynamicMessage.newBuilder(source.getDescriptorForType())
116  .mergeFrom(builder.buildPartial().toByteArray());
117  tree.merge(
118  DynamicMessage.newBuilder(source.getDescriptorForType())
119  .mergeFrom(source.toByteArray())
120  .build(),
121  newBuilder,
122  options);
123  builder.clear();
124  builder.mergeFrom(newBuilder.buildPartial());
125  } else {
126  tree.merge(source, builder, options);
127  }
128  }
129 
130  private void testMergeRequire(boolean useDynamicMessage) throws Exception {
131  TestRequired value = TestRequired.newBuilder().setA(4321).setB(8765).setC(233333).build();
132  TestRequiredMessage source = TestRequiredMessage.newBuilder().setRequiredMessage(value).build();
133 
135  TestRequiredMessage.Builder builder = TestRequiredMessage.newBuilder();
136  merge(
137  new FieldMaskTree().addFieldPath("required_message.a"),
138  source,
139  builder,
140  options,
141  useDynamicMessage);
142  assertTrue(builder.hasRequiredMessage());
143  assertTrue(builder.getRequiredMessage().hasA());
144  assertFalse(builder.getRequiredMessage().hasB());
145  assertFalse(builder.getRequiredMessage().hasC());
146  merge(
147  new FieldMaskTree().addFieldPath("required_message.b").addFieldPath("required_message.c"),
148  source,
149  builder,
150  options,
151  useDynamicMessage);
152  try {
153  assertEquals(builder.build(), source);
154  } catch (UninitializedMessageException e) {
155  throw new AssertionError("required field isn't set", e);
156  }
157  }
158 
159  private void testMergeImpl(boolean useDynamicMessage) throws Exception {
160  TestAllTypes value =
161  TestAllTypes.newBuilder()
162  .setOptionalInt32(1234)
163  .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678))
164  .addRepeatedInt32(4321)
165  .addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765))
166  .build();
167  NestedTestAllTypes source =
168  NestedTestAllTypes.newBuilder()
169  .setPayload(value)
170  .setChild(NestedTestAllTypes.newBuilder().setPayload(value))
171  .build();
172  // Now we have a message source with the following structure:
173  // [root] -+- payload -+- optional_int32
174  // | +- optional_nested_message
175  // | +- repeated_int32
176  // | +- repeated_nested_message
177  // |
178  // +- child --- payload -+- optional_int32
179  // +- optional_nested_message
180  // +- repeated_int32
181  // +- repeated_nested_message
182 
184 
185  // Test merging each individual field.
186  NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
187  merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
188  source, builder, options, useDynamicMessage);
189  NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
190  expected.getPayloadBuilder().setOptionalInt32(1234);
191  assertEquals(expected.build(), builder.build());
192 
193  builder = NestedTestAllTypes.newBuilder();
194  merge(new FieldMaskTree().addFieldPath("payload.optional_nested_message"),
195  source, builder, options, useDynamicMessage);
196  expected = NestedTestAllTypes.newBuilder();
197  expected.getPayloadBuilder().setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678));
198  assertEquals(expected.build(), builder.build());
199 
200  builder = NestedTestAllTypes.newBuilder();
201  merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"),
202  source, builder, options, useDynamicMessage);
203  expected = NestedTestAllTypes.newBuilder();
204  expected.getPayloadBuilder().addRepeatedInt32(4321);
205  assertEquals(expected.build(), builder.build());
206 
207  builder = NestedTestAllTypes.newBuilder();
208  merge(new FieldMaskTree().addFieldPath("payload.repeated_nested_message"),
209  source, builder, options, useDynamicMessage);
210  expected = NestedTestAllTypes.newBuilder();
211  expected.getPayloadBuilder().addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765));
212  assertEquals(expected.build(), builder.build());
213 
214  builder = NestedTestAllTypes.newBuilder();
215  merge(
216  new FieldMaskTree().addFieldPath("child.payload.optional_int32"),
217  source,
218  builder,
219  options,
220  useDynamicMessage);
221  expected = NestedTestAllTypes.newBuilder();
222  expected.getChildBuilder().getPayloadBuilder().setOptionalInt32(1234);
223  assertEquals(expected.build(), builder.build());
224 
225  builder = NestedTestAllTypes.newBuilder();
226  merge(
227  new FieldMaskTree().addFieldPath("child.payload.optional_nested_message"),
228  source,
229  builder,
230  options,
231  useDynamicMessage);
232  expected = NestedTestAllTypes.newBuilder();
233  expected
234  .getChildBuilder()
235  .getPayloadBuilder()
236  .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678));
237  assertEquals(expected.build(), builder.build());
238 
239  builder = NestedTestAllTypes.newBuilder();
240  merge(new FieldMaskTree().addFieldPath("child.payload.repeated_int32"),
241  source, builder, options, useDynamicMessage);
242  expected = NestedTestAllTypes.newBuilder();
243  expected.getChildBuilder().getPayloadBuilder().addRepeatedInt32(4321);
244  assertEquals(expected.build(), builder.build());
245 
246  builder = NestedTestAllTypes.newBuilder();
247  merge(new FieldMaskTree().addFieldPath("child.payload.repeated_nested_message"),
248  source, builder, options, useDynamicMessage);
249  expected = NestedTestAllTypes.newBuilder();
250  expected
251  .getChildBuilder()
252  .getPayloadBuilder()
253  .addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765));
254  assertEquals(expected.build(), builder.build());
255 
256  // Test merging all fields.
257  builder = NestedTestAllTypes.newBuilder();
258  merge(new FieldMaskTree().addFieldPath("child").addFieldPath("payload"),
259  source, builder, options, useDynamicMessage);
260  assertEquals(source, builder.build());
261 
262  // Test repeated options.
263  builder = NestedTestAllTypes.newBuilder();
264  builder.getPayloadBuilder().addRepeatedInt32(1000);
265  merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"),
266  source, builder, options, useDynamicMessage);
267  // Default behavior is to append repeated fields.
268  assertEquals(2, builder.getPayload().getRepeatedInt32Count());
269  assertEquals(1000, builder.getPayload().getRepeatedInt32(0));
270  assertEquals(4321, builder.getPayload().getRepeatedInt32(1));
271  // Change to replace repeated fields.
272  options.setReplaceRepeatedFields(true);
273  merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"),
274  source, builder, options, useDynamicMessage);
275  assertEquals(1, builder.getPayload().getRepeatedInt32Count());
276  assertEquals(4321, builder.getPayload().getRepeatedInt32(0));
277 
278  // Test message options.
279  builder = NestedTestAllTypes.newBuilder();
280  builder.getPayloadBuilder().setOptionalInt32(1000);
281  builder.getPayloadBuilder().setOptionalUint32(2000);
282  merge(new FieldMaskTree().addFieldPath("payload"),
283  source, builder, options, useDynamicMessage);
284  // Default behavior is to merge message fields.
285  assertEquals(1234, builder.getPayload().getOptionalInt32());
286  assertEquals(2000, builder.getPayload().getOptionalUint32());
287 
288  // Test merging unset message fields.
289  NestedTestAllTypes clearedSource = source.toBuilder().clearPayload().build();
290  builder = NestedTestAllTypes.newBuilder();
291  merge(new FieldMaskTree().addFieldPath("payload"),
292  clearedSource, builder, options, useDynamicMessage);
293  assertEquals(false, builder.hasPayload());
294 
295  // Skip a message field if they are unset in both source and target.
296  builder = NestedTestAllTypes.newBuilder();
297  merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
298  clearedSource, builder, options, useDynamicMessage);
299  assertEquals(false, builder.hasPayload());
300 
301  // Change to replace message fields.
302  options.setReplaceMessageFields(true);
303  builder = NestedTestAllTypes.newBuilder();
304  builder.getPayloadBuilder().setOptionalInt32(1000);
305  builder.getPayloadBuilder().setOptionalUint32(2000);
306  merge(new FieldMaskTree().addFieldPath("payload"),
307  source, builder, options, useDynamicMessage);
308  assertEquals(1234, builder.getPayload().getOptionalInt32());
309  assertEquals(0, builder.getPayload().getOptionalUint32());
310 
311  // Test merging unset message fields.
312  builder = NestedTestAllTypes.newBuilder();
313  builder.getPayloadBuilder().setOptionalInt32(1000);
314  builder.getPayloadBuilder().setOptionalUint32(2000);
315  merge(new FieldMaskTree().addFieldPath("payload"),
316  clearedSource, builder, options, useDynamicMessage);
317  assertEquals(false, builder.hasPayload());
318 
319  // Test merging unset primitive fields.
320  builder = source.toBuilder();
321  builder.getPayloadBuilder().clearOptionalInt32();
322  NestedTestAllTypes sourceWithPayloadInt32Unset = builder.build();
323  builder = source.toBuilder();
324  merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
325  sourceWithPayloadInt32Unset, builder, options, useDynamicMessage);
326  assertEquals(true, builder.getPayload().hasOptionalInt32());
327  assertEquals(0, builder.getPayload().getOptionalInt32());
328 
329  // Change to clear unset primitive fields.
330  options.setReplacePrimitiveFields(true);
331  builder = source.toBuilder();
332  merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
333  sourceWithPayloadInt32Unset, builder, options, useDynamicMessage);
334  assertEquals(true, builder.hasPayload());
335  assertEquals(false, builder.getPayload().hasOptionalInt32());
336  }
337 }
com.google.protobuf.util.FieldMaskTreeTest
Definition: FieldMaskTreeTest.java:43
com.google.protobuf.util.FieldMaskTreeTest.testMergeFromFieldMask
void testMergeFromFieldMask()
Definition: FieldMaskTreeTest.java:69
options
Message * options
Definition: src/google/protobuf/descriptor.cc:3119
com.google.protobuf
Definition: ProtoCaliperBenchmark.java:2
com.google.protobuf.UninitializedMessageException
Definition: UninitializedMessageException.java:47
com.google.protobuf.util.FieldMaskTreeTest.testIntersectFieldPath
void testIntersectFieldPath()
Definition: FieldMaskTreeTest.java:76
com.google.protobuf.util.FieldMaskTreeTest.testMergeRequire
void testMergeRequire(boolean useDynamicMessage)
Definition: FieldMaskTreeTest.java:130
com.google.protobuf.util.FieldMaskUtil.MergeOptions
Definition: FieldMaskUtil.java:271
com.google.protobuf.DynamicMessage.newBuilder
static Builder newBuilder(Descriptor type)
Definition: DynamicMessage.java:140
com.google.protobuf.util.FieldMaskUtil.fromString
static FieldMask fromString(String value)
Definition: FieldMaskUtil.java:84
com.google.protobuf.Message.Builder
Definition: Message.java:104
com.google.protobuf.DynamicMessage.Builder.mergeFrom
Builder mergeFrom(Message other)
Definition: DynamicMessage.java:366
com.google.protobuf.util.FieldMaskTreeTest.merge
void merge(FieldMaskTree tree, Message source, Message.Builder builder, FieldMaskUtil.MergeOptions options, boolean useDynamicMessage)
Definition: FieldMaskTreeTest.java:106
source
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:3072
com.google.protobuf.util.FieldMaskTreeTest.testMerge
void testMerge()
Definition: FieldMaskTreeTest.java:99
com.google.protobuf.util.FieldMaskUtil
Definition: FieldMaskUtil.java:52
com.google.protobuf.DynamicMessage.Builder.build
DynamicMessage build()
Definition: DynamicMessage.java:395
protobuf_unittest
Definition: map_test_util_impl.h:39
com.google.protobuf.DynamicMessage
Definition: DynamicMessage.java:51
com.google
com
com.google.protobuf.util.FieldMaskTreeTest.testMergeImpl
void testMergeImpl(boolean useDynamicMessage)
Definition: FieldMaskTreeTest.java:159
tree
Definition: wepoll.c:502
value
GLsizei const GLfloat * value
Definition: glcorearb.h:3093
gmock_test_utils.TestCase
TestCase
Definition: gmock_test_utils.py:97
com.google.protobuf.util.FieldMaskTreeTest.testAddFieldPath
void testAddFieldPath()
Definition: FieldMaskTreeTest.java:44
com.google.protobuf.Message
Definition: Message.java:50


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:51