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 
33 import com.google.protobuf.FieldMask;
34 import protobuf_unittest.UnittestProto.NestedTestAllTypes;
35 import protobuf_unittest.UnittestProto.TestAllTypes;
36 
37 import junit.framework.TestCase;
38 
39 /** Unit tests for {@link FieldMaskUtil}. */
40 public class FieldMaskUtilTest extends TestCase {
testIsValid()41   public void testIsValid() throws Exception {
42     assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload"));
43     assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "nonexist"));
44     assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_int32"));
45     assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_int32"));
46     assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_nested_message"));
47     assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_nested_message"));
48     assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.nonexist"));
49 
50     assertTrue(
51         FieldMaskUtil.isValid(NestedTestAllTypes.class, FieldMaskUtil.fromString("payload")));
52     assertFalse(
53         FieldMaskUtil.isValid(NestedTestAllTypes.class, FieldMaskUtil.fromString("nonexist")));
54     assertFalse(
55         FieldMaskUtil.isValid(
56             NestedTestAllTypes.class, FieldMaskUtil.fromString("payload,nonexist")));
57 
58     assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.getDescriptor(), "payload"));
59     assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.getDescriptor(), "nonexist"));
60 
61     assertTrue(
62         FieldMaskUtil.isValid(
63             NestedTestAllTypes.getDescriptor(), FieldMaskUtil.fromString("payload")));
64     assertFalse(
65         FieldMaskUtil.isValid(
66             NestedTestAllTypes.getDescriptor(), FieldMaskUtil.fromString("nonexist")));
67 
68     assertTrue(
69         FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_nested_message.bb"));
70     // Repeated fields cannot have sub-paths.
71     assertFalse(
72         FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_nested_message.bb"));
73     // Non-message fields cannot have sub-paths.
74     assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_int32.bb"));
75   }
76 
testToString()77   public void testToString() throws Exception {
78     assertEquals("", FieldMaskUtil.toString(FieldMask.getDefaultInstance()));
79     FieldMask mask = FieldMask.newBuilder().addPaths("foo").build();
80     assertEquals("foo", FieldMaskUtil.toString(mask));
81     mask = FieldMask.newBuilder().addPaths("foo").addPaths("bar").build();
82     assertEquals("foo,bar", FieldMaskUtil.toString(mask));
83 
84     // Empty field paths are ignored.
85     mask =
86         FieldMask.newBuilder()
87             .addPaths("")
88             .addPaths("foo")
89             .addPaths("")
90             .addPaths("bar")
91             .addPaths("")
92             .build();
93     assertEquals("foo,bar", FieldMaskUtil.toString(mask));
94   }
95 
testFromString()96   public void testFromString() throws Exception {
97     FieldMask mask = FieldMaskUtil.fromString("");
98     assertEquals(0, mask.getPathsCount());
99     mask = FieldMaskUtil.fromString("foo");
100     assertEquals(1, mask.getPathsCount());
101     assertEquals("foo", mask.getPaths(0));
102     mask = FieldMaskUtil.fromString("foo,bar.baz");
103     assertEquals(2, mask.getPathsCount());
104     assertEquals("foo", mask.getPaths(0));
105     assertEquals("bar.baz", mask.getPaths(1));
106 
107     // Empty field paths are ignore.
108     mask = FieldMaskUtil.fromString(",foo,,bar,");
109     assertEquals(2, mask.getPathsCount());
110     assertEquals("foo", mask.getPaths(0));
111     assertEquals("bar", mask.getPaths(1));
112 
113     // Check whether the field paths are valid if a class parameter is provided.
114     mask = FieldMaskUtil.fromString(NestedTestAllTypes.class, ",payload");
115 
116     try {
117       mask = FieldMaskUtil.fromString(NestedTestAllTypes.class, "payload,nonexist");
118       fail("Exception is expected.");
119     } catch (IllegalArgumentException e) {
120       // Expected.
121     }
122   }
123 
testFromFieldNumbers()124   public void testFromFieldNumbers() throws Exception {
125     FieldMask mask = FieldMaskUtil.fromFieldNumbers(TestAllTypes.class);
126     assertEquals(0, mask.getPathsCount());
127     mask =
128         FieldMaskUtil.fromFieldNumbers(
129             TestAllTypes.class, TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER);
130     assertEquals(1, mask.getPathsCount());
131     assertEquals("optional_int32", mask.getPaths(0));
132     mask =
133         FieldMaskUtil.fromFieldNumbers(
134             TestAllTypes.class,
135             TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER,
136             TestAllTypes.OPTIONAL_INT64_FIELD_NUMBER);
137     assertEquals(2, mask.getPathsCount());
138     assertEquals("optional_int32", mask.getPaths(0));
139     assertEquals("optional_int64", mask.getPaths(1));
140 
141     try {
142       int invalidFieldNumber = 1000;
143       mask = FieldMaskUtil.fromFieldNumbers(TestAllTypes.class, invalidFieldNumber);
144       fail("Exception is expected.");
145     } catch (IllegalArgumentException expected) {
146     }
147   }
148 
testToJsonString()149   public void testToJsonString() throws Exception {
150     FieldMask mask = FieldMask.getDefaultInstance();
151     assertEquals("", FieldMaskUtil.toJsonString(mask));
152     mask = FieldMask.newBuilder().addPaths("foo").build();
153     assertEquals("foo", FieldMaskUtil.toJsonString(mask));
154     mask = FieldMask.newBuilder().addPaths("foo.bar_baz").addPaths("").build();
155     assertEquals("foo.barBaz", FieldMaskUtil.toJsonString(mask));
156     mask = FieldMask.newBuilder().addPaths("foo").addPaths("bar_baz").build();
157     assertEquals("foo,barBaz", FieldMaskUtil.toJsonString(mask));
158   }
159 
testFromJsonString()160   public void testFromJsonString() throws Exception {
161     FieldMask mask = FieldMaskUtil.fromJsonString("");
162     assertEquals(0, mask.getPathsCount());
163     mask = FieldMaskUtil.fromJsonString("foo");
164     assertEquals(1, mask.getPathsCount());
165     assertEquals("foo", mask.getPaths(0));
166     mask = FieldMaskUtil.fromJsonString("foo.barBaz");
167     assertEquals(1, mask.getPathsCount());
168     assertEquals("foo.bar_baz", mask.getPaths(0));
169     mask = FieldMaskUtil.fromJsonString("foo,barBaz");
170     assertEquals(2, mask.getPathsCount());
171     assertEquals("foo", mask.getPaths(0));
172     assertEquals("bar_baz", mask.getPaths(1));
173   }
174 
testUnion()175   public void testUnion() throws Exception {
176     // Only test a simple case here and expect
177     // {@link FieldMaskTreeTest#testAddFieldPath} to cover all scenarios.
178     FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
179     FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
180     FieldMask result = FieldMaskUtil.union(mask1, mask2);
181     assertEquals("bar,foo", FieldMaskUtil.toString(result));
182   }
183 
testUnion_usingVarArgs()184   public void testUnion_usingVarArgs() throws Exception {
185     FieldMask mask1 = FieldMaskUtil.fromString("foo");
186     FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.quz");
187     FieldMask mask3 = FieldMaskUtil.fromString("bar.quz");
188     FieldMask mask4 = FieldMaskUtil.fromString("bar");
189     FieldMask result = FieldMaskUtil.union(mask1, mask2, mask3, mask4);
190     assertEquals("bar,foo", FieldMaskUtil.toString(result));
191   }
192 
testIntersection()193   public void testIntersection() throws Exception {
194     // Only test a simple case here and expect
195     // {@link FieldMaskTreeTest#testIntersectFieldPath} to cover all scenarios.
196     FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
197     FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
198     FieldMask result = FieldMaskUtil.intersection(mask1, mask2);
199     assertEquals("bar.baz,bar.quz,foo.bar", FieldMaskUtil.toString(result));
200   }
201 
testMerge()202   public void testMerge() throws Exception {
203     // Only test a simple case here and expect
204     // {@link FieldMaskTreeTest#testMerge} to cover all scenarios.
205     NestedTestAllTypes source =
206         NestedTestAllTypes.newBuilder()
207             .setPayload(TestAllTypes.newBuilder().setOptionalInt32(1234))
208             .build();
209     NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
210     FieldMaskUtil.merge(FieldMaskUtil.fromString("payload"), source, builder);
211     assertEquals(1234, builder.getPayload().getOptionalInt32());
212   }
213 }
214