content: // Protocol Buffers - Google's data interchange format
  // Copyright 2008 Google Inc.  All rights reserved.
  // https://developers.google.com/protocol-buffers/
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  //
  //     * Redistributions of source code must retain the above copyright
  // notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above
  // copyright notice, this list of conditions and the following disclaimer
  // in the documentation and/or other materials provided with the
  // distribution.
  //     * Neither the name of Google Inc. nor the names of its
  // contributors may be used to endorse or promote products derived from
  // this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  package com.google.protobuf.util;
  
  import com.google.protobuf.FieldMask;
  import protobuf_unittest.UnittestProto.NestedTestAllTypes;
  import protobuf_unittest.UnittestProto.TestAllTypes;
  
  import junit.framework.TestCase;
  
  /** Unit tests for {@link FieldMaskUtil}. */
  public class FieldMaskUtilTest extends TestCase {
    public void testIsValid() throws Exception {
      assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload"));
      assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "nonexist"));
      assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_int32"));
      assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_int32"));
      assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_nested_message"));
      assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_nested_message"));
      assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.nonexist"));
  
      assertTrue(
          FieldMaskUtil.isValid(NestedTestAllTypes.class, FieldMaskUtil.fromString("payload")));
      assertFalse(
          FieldMaskUtil.isValid(NestedTestAllTypes.class, FieldMaskUtil.fromString("nonexist")));
      assertFalse(
          FieldMaskUtil.isValid(
              NestedTestAllTypes.class, FieldMaskUtil.fromString("payload,nonexist")));
  
      assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.getDescriptor(), "payload"));
      assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.getDescriptor(), "nonexist"));
  
      assertTrue(
          FieldMaskUtil.isValid(
              NestedTestAllTypes.getDescriptor(), FieldMaskUtil.fromString("payload")));
      assertFalse(
          FieldMaskUtil.isValid(
              NestedTestAllTypes.getDescriptor(), FieldMaskUtil.fromString("nonexist")));
  
      assertTrue(
          FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_nested_message.bb"));
      // Repeated fields cannot have sub-paths.
      assertFalse(
          FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_nested_message.bb"));
      // Non-message fields cannot have sub-paths.
      assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_int32.bb"));
    }
  
    public void testToString() throws Exception {
      assertEquals("", FieldMaskUtil.toString(FieldMask.getDefaultInstance()));
      FieldMask mask = FieldMask.newBuilder().addPaths("foo").build();
      assertEquals("foo", FieldMaskUtil.toString(mask));
      mask = FieldMask.newBuilder().addPaths("foo").addPaths("bar").build();
      assertEquals("foo,bar", FieldMaskUtil.toString(mask));
  
      // Empty field paths are ignored.
      mask =
          FieldMask.newBuilder()
              .addPaths("")
              .addPaths("foo")
              .addPaths("")
              .addPaths("bar")
              .addPaths("")
              .build();
      assertEquals("foo,bar", FieldMaskUtil.toString(mask));
    }
  
    public void testFromString() throws Exception {
      FieldMask mask = FieldMaskUtil.fromString("");
      assertEquals(0, mask.getPathsCount());
      mask = FieldMaskUtil.fromString("foo");
      assertEquals(1, mask.getPathsCount());
      assertEquals("foo", mask.getPaths(0));
      mask = FieldMaskUtil.fromString("foo,bar.baz");
      assertEquals(2, mask.getPathsCount());
      assertEquals("foo", mask.getPaths(0));
      assertEquals("bar.baz", mask.getPaths(1));
  
      // Empty field paths are ignore.
      mask = FieldMaskUtil.fromString(",foo,,bar,");
      assertEquals(2, mask.getPathsCount());
      assertEquals("foo", mask.getPaths(0));
      assertEquals("bar", mask.getPaths(1));
  
      // Check whether the field paths are valid if a class parameter is provided.
      mask = FieldMaskUtil.fromString(NestedTestAllTypes.class, ",payload");
  
      try {
        mask = FieldMaskUtil.fromString(NestedTestAllTypes.class, "payload,nonexist");
        fail("Exception is expected.");
      } catch (IllegalArgumentException e) {
        // Expected.
      }
    }
  
    public void testFromFieldNumbers() throws Exception {
      FieldMask mask = FieldMaskUtil.fromFieldNumbers(TestAllTypes.class);
      assertEquals(0, mask.getPathsCount());
      mask =
          FieldMaskUtil.fromFieldNumbers(
              TestAllTypes.class, TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER);
      assertEquals(1, mask.getPathsCount());
      assertEquals("optional_int32", mask.getPaths(0));
      mask =
          FieldMaskUtil.fromFieldNumbers(
              TestAllTypes.class,
              TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER,
              TestAllTypes.OPTIONAL_INT64_FIELD_NUMBER);
      assertEquals(2, mask.getPathsCount());
      assertEquals("optional_int32", mask.getPaths(0));
      assertEquals("optional_int64", mask.getPaths(1));
  
      try {
        int invalidFieldNumber = 1000;
        mask = FieldMaskUtil.fromFieldNumbers(TestAllTypes.class, invalidFieldNumber);
        fail("Exception is expected.");
      } catch (IllegalArgumentException expected) {
      }
    }
  
    public void testToJsonString() throws Exception {
      FieldMask mask = FieldMask.getDefaultInstance();
      assertEquals("", FieldMaskUtil.toJsonString(mask));
      mask = FieldMask.newBuilder().addPaths("foo").build();
      assertEquals("foo", FieldMaskUtil.toJsonString(mask));
      mask = FieldMask.newBuilder().addPaths("foo.bar_baz").addPaths("").build();
      assertEquals("foo.barBaz", FieldMaskUtil.toJsonString(mask));
      mask = FieldMask.newBuilder().addPaths("foo").addPaths("bar_baz").build();
      assertEquals("foo,barBaz", FieldMaskUtil.toJsonString(mask));
    }
  
    public void testFromJsonString() throws Exception {
      FieldMask mask = FieldMaskUtil.fromJsonString("");
      assertEquals(0, mask.getPathsCount());
      mask = FieldMaskUtil.fromJsonString("foo");
      assertEquals(1, mask.getPathsCount());
      assertEquals("foo", mask.getPaths(0));
      mask = FieldMaskUtil.fromJsonString("foo.barBaz");
      assertEquals(1, mask.getPathsCount());
      assertEquals("foo.bar_baz", mask.getPaths(0));
      mask = FieldMaskUtil.fromJsonString("foo,barBaz");
      assertEquals(2, mask.getPathsCount());
      assertEquals("foo", mask.getPaths(0));
      assertEquals("bar_baz", mask.getPaths(1));
    }
  
    public void testUnion() throws Exception {
      // Only test a simple case here and expect
      // {@link FieldMaskTreeTest#testAddFieldPath} to cover all scenarios.
      FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
      FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
      FieldMask result = FieldMaskUtil.union(mask1, mask2);
      assertEquals("bar,foo", FieldMaskUtil.toString(result));
    }
  
    public void testUnion_usingVarArgs() throws Exception {
      FieldMask mask1 = FieldMaskUtil.fromString("foo");
      FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.quz");
      FieldMask mask3 = FieldMaskUtil.fromString("bar.quz");
      FieldMask mask4 = FieldMaskUtil.fromString("bar");
      FieldMask result = FieldMaskUtil.union(mask1, mask2, mask3, mask4);
      assertEquals("bar,foo", FieldMaskUtil.toString(result));
    }
  
    public void testIntersection() throws Exception {
      // Only test a simple case here and expect
      // {@link FieldMaskTreeTest#testIntersectFieldPath} to cover all scenarios.
      FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
      FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
      FieldMask result = FieldMaskUtil.intersection(mask1, mask2);
      assertEquals("bar.baz,bar.quz,foo.bar", FieldMaskUtil.toString(result));
    }
  
    public void testMerge() throws Exception {
      // Only test a simple case here and expect
      // {@link FieldMaskTreeTest#testMerge} to cover all scenarios.
      NestedTestAllTypes source =
          NestedTestAllTypes.newBuilder()
              .setPayload(TestAllTypes.newBuilder().setOptionalInt32(1234))
              .build();
      NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
      FieldMaskUtil.merge(FieldMaskUtil.fromString("payload"), source, builder);
      assertEquals(1234, builder.getPayload().getOptionalInt32());
    }
  }
  