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; 32 33 import protobuf_unittest.UnittestProto.TestAllTypes; 34 import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; 35 36 import junit.framework.TestCase; 37 38 import java.util.Collections; 39 import java.util.List; 40 41 /** 42 * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality. 43 * More extensive testing is provided via other tests that exercise the 44 * builder. 45 * 46 * @author jonp@google.com (Jon Perlow) 47 */ 48 public class RepeatedFieldBuilderTest extends TestCase { 49 testBasicUse()50 public void testBasicUse() { 51 TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); 52 RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder, 53 TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent); 54 builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); 55 builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); 56 assertEquals(0, builder.getMessage(0).getOptionalInt32()); 57 assertEquals(1, builder.getMessage(1).getOptionalInt32()); 58 59 List<TestAllTypes> list = builder.build(); 60 assertEquals(2, list.size()); 61 assertEquals(0, list.get(0).getOptionalInt32()); 62 assertEquals(1, list.get(1).getOptionalInt32()); 63 assertIsUnmodifiable(list); 64 65 // Make sure it doesn't change. 66 List<TestAllTypes> list2 = builder.build(); 67 assertSame(list, list2); 68 assertEquals(0, mockParent.getInvalidationCount()); 69 } 70 testGoingBackAndForth()71 public void testGoingBackAndForth() { 72 TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); 73 RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder, 74 TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent); 75 builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); 76 builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); 77 assertEquals(0, builder.getMessage(0).getOptionalInt32()); 78 assertEquals(1, builder.getMessage(1).getOptionalInt32()); 79 80 // Convert to list 81 List<TestAllTypes> list = builder.build(); 82 assertEquals(2, list.size()); 83 assertEquals(0, list.get(0).getOptionalInt32()); 84 assertEquals(1, list.get(1).getOptionalInt32()); 85 assertIsUnmodifiable(list); 86 87 // Update 0th item 88 assertEquals(0, mockParent.getInvalidationCount()); 89 builder.getBuilder(0).setOptionalString("foo"); 90 assertEquals(1, mockParent.getInvalidationCount()); 91 list = builder.build(); 92 assertEquals(2, list.size()); 93 assertEquals(0, list.get(0).getOptionalInt32()); 94 assertEquals("foo", list.get(0).getOptionalString()); 95 assertEquals(1, list.get(1).getOptionalInt32()); 96 assertIsUnmodifiable(list); 97 assertEquals(1, mockParent.getInvalidationCount()); 98 } 99 testVariousMethods()100 public void testVariousMethods() { 101 TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); 102 RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder, 103 TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent); 104 builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); 105 builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build()); 106 builder.addBuilder(0, TestAllTypes.getDefaultInstance()) 107 .setOptionalInt32(0); 108 builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3); 109 110 assertEquals(0, builder.getMessage(0).getOptionalInt32()); 111 assertEquals(1, builder.getMessage(1).getOptionalInt32()); 112 assertEquals(2, builder.getMessage(2).getOptionalInt32()); 113 assertEquals(3, builder.getMessage(3).getOptionalInt32()); 114 115 assertEquals(0, mockParent.getInvalidationCount()); 116 List<TestAllTypes> messages = builder.build(); 117 assertEquals(4, messages.size()); 118 assertSame(messages, builder.build()); // expect same list 119 120 // Remove a message. 121 builder.remove(2); 122 assertEquals(1, mockParent.getInvalidationCount()); 123 assertEquals(3, builder.getCount()); 124 assertEquals(0, builder.getMessage(0).getOptionalInt32()); 125 assertEquals(1, builder.getMessage(1).getOptionalInt32()); 126 assertEquals(3, builder.getMessage(2).getOptionalInt32()); 127 128 // Remove a builder. 129 builder.remove(0); 130 assertEquals(1, mockParent.getInvalidationCount()); 131 assertEquals(2, builder.getCount()); 132 assertEquals(1, builder.getMessage(0).getOptionalInt32()); 133 assertEquals(3, builder.getMessage(1).getOptionalInt32()); 134 135 // Test clear. 136 builder.clear(); 137 assertEquals(1, mockParent.getInvalidationCount()); 138 assertEquals(0, builder.getCount()); 139 assertTrue(builder.isEmpty()); 140 } 141 testLists()142 public void testLists() { 143 TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); 144 RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder, 145 TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent); 146 builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); 147 builder.addMessage(0, 148 TestAllTypes.newBuilder().setOptionalInt32(0).build()); 149 assertEquals(0, builder.getMessage(0).getOptionalInt32()); 150 assertEquals(1, builder.getMessage(1).getOptionalInt32()); 151 152 // Use list of builders. 153 List<TestAllTypes.Builder> builders = builder.getBuilderList(); 154 assertEquals(0, builders.get(0).getOptionalInt32()); 155 assertEquals(1, builders.get(1).getOptionalInt32()); 156 builders.get(0).setOptionalInt32(10); 157 builders.get(1).setOptionalInt32(11); 158 159 // Use list of protos 160 List<TestAllTypes> protos = builder.getMessageList(); 161 assertEquals(10, protos.get(0).getOptionalInt32()); 162 assertEquals(11, protos.get(1).getOptionalInt32()); 163 164 // Add an item to the builders and verify it's updated in both 165 builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build()); 166 assertEquals(3, builders.size()); 167 assertEquals(3, protos.size()); 168 } 169 assertIsUnmodifiable(List<?> list)170 private void assertIsUnmodifiable(List<?> list) { 171 if (list == Collections.emptyList()) { 172 // OKAY -- Need to check this b/c EmptyList allows you to call clear. 173 } else { 174 try { 175 list.clear(); 176 fail("List wasn't immutable"); 177 } catch (UnsupportedOperationException e) { 178 // good 179 } 180 } 181 } 182 183 private RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder, 184 TestAllTypesOrBuilder> newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent)185 newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent) { 186 return new RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder, 187 TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false, 188 parent, false); 189 } 190 } 191