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