content: // Protocol Buffers - Google's data interchange format
  // Copyright 2008 Google Inc.  All rights reserved.
  // http://code.google.com/p/protobuf/
  //
  // 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.test;
  import com.google.protobuf.*;
  
  import protobuf_unittest.UnittestProto.TestAllTypes;
  import protobuf_unittest.UnittestProto.TestAllExtensions;
  import protobuf_unittest.UnittestProto.TestRequired;
  import protobuf_unittest.UnittestProto.TestRequiredForeign;
  import protobuf_unittest.UnittestProto.ForeignMessage;
  
  import junit.framework.TestCase;
  
  import java.util.List;
  
  /**
   * Misc. unit tests for message operations that apply to both generated
   * and dynamic messages.
   *
   * @author kenton@google.com Kenton Varda
   */
  public class MessageTest extends TestCase {
    // =================================================================
    // Message-merging tests.
  
    static final TestAllTypes MERGE_SOURCE =
      TestAllTypes.newBuilder()
        .setOptionalInt32(1)
        .setOptionalString("foo")
        .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
        .addRepeatedString("bar")
        .build();
  
    static final TestAllTypes MERGE_DEST =
      TestAllTypes.newBuilder()
        .setOptionalInt64(2)
        .setOptionalString("baz")
        .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
        .addRepeatedString("qux")
        .build();
  
    static final String MERGE_RESULT_TEXT =
        "optional_int32: 1\n" +
        "optional_int64: 2\n" +
        "optional_string: \"foo\"\n" +
        "optional_foreign_message {\n" +
        "  c: 3\n" +
        "}\n" +
        "repeated_string: \"qux\"\n" +
        "repeated_string: \"bar\"\n";
  
    public void testMergeFrom() throws Exception {
      TestAllTypes result =
        TestAllTypes.newBuilder(MERGE_DEST)
          .mergeFrom(MERGE_SOURCE).build();
  
      assertEquals(MERGE_RESULT_TEXT, result.toString());
    }
  
    /**
     * Test merging a DynamicMessage into a GeneratedMessage.  As long as they
     * have the same descriptor, this should work, but it is an entirely different
     * code path.
     */
    public void testMergeFromDynamic() throws Exception {
      TestAllTypes result =
        TestAllTypes.newBuilder(MERGE_DEST)
          .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
          .build();
  
      assertEquals(MERGE_RESULT_TEXT, result.toString());
    }
  
    /** Test merging two DynamicMessages. */
    public void testDynamicMergeFrom() throws Exception {
      DynamicMessage result =
        DynamicMessage.newBuilder(MERGE_DEST)
          .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
          .build();
  
      assertEquals(MERGE_RESULT_TEXT, result.toString());
    }
  
    // =================================================================
    // Required-field-related tests.
  
    private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
      TestRequired.getDefaultInstance();
    private static final TestRequired TEST_REQUIRED_INITIALIZED =
      TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
  
    public void testRequired() throws Exception {
      TestRequired.Builder builder = TestRequired.newBuilder();
  
      assertFalse(builder.isInitialized());
      builder.setA(1);
      assertFalse(builder.isInitialized());
      builder.setB(1);
      assertFalse(builder.isInitialized());
      builder.setC(1);
      assertTrue(builder.isInitialized());
    }
  
    public void testRequiredForeign() throws Exception {
      TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
  
      assertTrue(builder.isInitialized());
  
      builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
      assertFalse(builder.isInitialized());
  
      builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
      assertTrue(builder.isInitialized());
  
      builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
      assertFalse(builder.isInitialized());
  
      builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
      assertTrue(builder.isInitialized());
    }
  
    public void testRequiredExtension() throws Exception {
      TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
  
      assertTrue(builder.isInitialized());
  
      builder.setExtension(TestRequired.single, TEST_REQUIRED_UNINITIALIZED);
      assertFalse(builder.isInitialized());
  
      builder.setExtension(TestRequired.single, TEST_REQUIRED_INITIALIZED);
      assertTrue(builder.isInitialized());
  
      builder.addExtension(TestRequired.multi, TEST_REQUIRED_UNINITIALIZED);
      assertFalse(builder.isInitialized());
  
      builder.setExtension(TestRequired.multi, 0, TEST_REQUIRED_INITIALIZED);
      assertTrue(builder.isInitialized());
    }
  
    public void testRequiredDynamic() throws Exception {
      Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
      DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
  
      assertFalse(builder.isInitialized());
      builder.setField(descriptor.findFieldByName("a"), 1);
      assertFalse(builder.isInitialized());
      builder.setField(descriptor.findFieldByName("b"), 1);
      assertFalse(builder.isInitialized());
      builder.setField(descriptor.findFieldByName("c"), 1);
      assertTrue(builder.isInitialized());
    }
  
    public void testRequiredDynamicForeign() throws Exception {
      Descriptors.Descriptor descriptor = TestRequiredForeign.getDescriptor();
      DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
  
      assertTrue(builder.isInitialized());
  
      builder.setField(descriptor.findFieldByName("optional_message"),
                       TEST_REQUIRED_UNINITIALIZED);
      assertFalse(builder.isInitialized());
  
      builder.setField(descriptor.findFieldByName("optional_message"),
                       TEST_REQUIRED_INITIALIZED);
      assertTrue(builder.isInitialized());
  
      builder.addRepeatedField(descriptor.findFieldByName("repeated_message"),
                               TEST_REQUIRED_UNINITIALIZED);
      assertFalse(builder.isInitialized());
  
      builder.setRepeatedField(descriptor.findFieldByName("repeated_message"), 0,
                               TEST_REQUIRED_INITIALIZED);
      assertTrue(builder.isInitialized());
    }
  
    public void testUninitializedException() throws Exception {
      try {
        TestRequired.newBuilder().build();
        fail("Should have thrown an exception.");
      } catch (UninitializedMessageException e) {
        assertEquals("Message missing required fields: a, b, c", e.getMessage());
      }
    }
  
    public void testBuildPartial() throws Exception {
      // We're mostly testing that no exception is thrown.
      TestRequired message = TestRequired.newBuilder().buildPartial();
      assertFalse(message.isInitialized());
    }
  
    public void testNestedUninitializedException() throws Exception {
      try {
        TestRequiredForeign.newBuilder()
          .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
          .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
          .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
          .build();
        fail("Should have thrown an exception.");
      } catch (UninitializedMessageException e) {
        assertEquals(
          "Message missing required fields: " +
          "optional_message.a, " +
          "optional_message.b, " +
          "optional_message.c, " +
          "repeated_message[0].a, " +
          "repeated_message[0].b, " +
          "repeated_message[0].c, " +
          "repeated_message[1].a, " +
          "repeated_message[1].b, " +
          "repeated_message[1].c",
          e.getMessage());
      }
    }
  
    public void testBuildNestedPartial() throws Exception {
      // We're mostly testing that no exception is thrown.
      TestRequiredForeign message =
        TestRequiredForeign.newBuilder()
          .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
          .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
          .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
          .buildPartial();
      assertFalse(message.isInitialized());
    }
  
    public void testParseUnititialized() throws Exception {
      try {
        TestRequired.parseFrom(ByteString.EMPTY);
        fail("Should have thrown an exception.");
      } catch (InvalidProtocolBufferException e) {
        assertEquals("Message missing required fields: a, b, c", e.getMessage());
      }
    }
  
    public void testParseNestedUnititialized() throws Exception {
      ByteString data =
        TestRequiredForeign.newBuilder()
          .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
          .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
          .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
          .buildPartial().toByteString();
  
      try {
        TestRequiredForeign.parseFrom(data);
        fail("Should have thrown an exception.");
      } catch (InvalidProtocolBufferException e) {
        assertEquals(
          "Message missing required fields: " +
          "optional_message.a, " +
          "optional_message.b, " +
          "optional_message.c, " +
          "repeated_message[0].a, " +
          "repeated_message[0].b, " +
          "repeated_message[0].c, " +
          "repeated_message[1].a, " +
          "repeated_message[1].b, " +
          "repeated_message[1].c",
          e.getMessage());
      }
    }
  
    public void testDynamicUninitializedException() throws Exception {
      try {
        DynamicMessage.newBuilder(TestRequired.getDescriptor()).build();
        fail("Should have thrown an exception.");
      } catch (UninitializedMessageException e) {
        assertEquals("Message missing required fields: a, b, c", e.getMessage());
      }
    }
  
    public void testDynamicBuildPartial() throws Exception {
      // We're mostly testing that no exception is thrown.
      DynamicMessage message =
        DynamicMessage.newBuilder(TestRequired.getDescriptor())
          .buildPartial();
      assertFalse(message.isInitialized());
    }
  
    public void testDynamicParseUnititialized() throws Exception {
      try {
        Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
        DynamicMessage.parseFrom(descriptor, ByteString.EMPTY);
        fail("Should have thrown an exception.");
      } catch (InvalidProtocolBufferException e) {
        assertEquals("Message missing required fields: a, b, c", e.getMessage());
      }
    }
    
    /** Test reading unset repeated message from DynamicMessage. */
    public void testDynamicRepeatedMessageNull() throws Exception {
      Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
      DynamicMessage result =
        DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
          .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
          .build();
  
      assertTrue(result.getField(result.getDescriptorForType()
          .findFieldByName("repeated_foreign_message")) instanceof List<?>);
      assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
          .findFieldByName("repeated_foreign_message")), 0);
    }
    
    /** Test reading repeated message from DynamicMessage. */
    public void testDynamicRepeatedMessageNotNull() throws Exception {
  
      TestAllTypes REPEATED_NESTED =
        TestAllTypes.newBuilder()
          .setOptionalInt32(1)
          .setOptionalString("foo")
          .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
          .addRepeatedString("bar")
          .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
          .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
          .build();
      Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
      DynamicMessage result =
        DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
          .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
          .build();
  
      assertTrue(result.getField(result.getDescriptorForType()
          .findFieldByName("repeated_foreign_message")) instanceof List<?>);
      assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
          .findFieldByName("repeated_foreign_message")), 2);
    }
  }
  