diff options
author | Adam Cozzette <acozzette@google.com> | 2016-06-29 15:23:27 -0700 |
---|---|---|
committer | Adam Cozzette <acozzette@google.com> | 2016-06-29 15:38:03 -0700 |
commit | d64a2d9941c36a7bc2a7959ea10ab8363192ac14 (patch) | |
tree | 52330d146ad63d3d70f3baade00d5d1fea8f5e0c /java/core/src/test | |
parent | c18aa7795a2e02ef700ff8b039d94ecdcc33432f (diff) | |
download | protobuf-d64a2d9941c36a7bc2a7959ea10ab8363192ac14.tar.gz protobuf-d64a2d9941c36a7bc2a7959ea10ab8363192ac14.tar.bz2 protobuf-d64a2d9941c36a7bc2a7959ea10ab8363192ac14.zip |
Integrated internal changes from Google
This includes all internal changes from around May 20 to now.
Diffstat (limited to 'java/core/src/test')
21 files changed, 2788 insertions, 699 deletions
diff --git a/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java index 24b96c60..ec139225 100644 --- a/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java @@ -40,30 +40,31 @@ import java.util.Iterator; /** * Tests for {@link BooleanArrayList}. - * + * * @author dweis@google.com (Daniel Weis) */ public class BooleanArrayListTest extends TestCase { - - private static final BooleanArrayList UNARY_LIST = newImmutableBooleanArrayList(true); + + private static final BooleanArrayList UNARY_LIST = + newImmutableBooleanArrayList(true); private static final BooleanArrayList TERTIARY_LIST = - newImmutableBooleanArrayList(true, true, false); - + newImmutableBooleanArrayList(true, false, true); + private BooleanArrayList list; - + @Override protected void setUp() throws Exception { list = new BooleanArrayList(); } - + public void testEmptyListReturnsSameInstance() { assertSame(BooleanArrayList.emptyList(), BooleanArrayList.emptyList()); } - + public void testEmptyListIsImmutable() { assertImmutable(BooleanArrayList.emptyList()); } - + public void testMakeImmutable() { list.addBoolean(true); list.addBoolean(false); @@ -72,16 +73,16 @@ public class BooleanArrayListTest extends TestCase { list.makeImmutable(); assertImmutable(list); } - + public void testModificationWithIteration() { - list.addAll(asList(true, false, false, true)); + list.addAll(asList(true, false, true, false)); Iterator<Boolean> iterator = list.iterator(); assertEquals(4, list.size()); assertEquals(true, (boolean) list.get(0)); assertEquals(true, (boolean) iterator.next()); list.set(0, true); assertEquals(false, (boolean) iterator.next()); - + list.remove(0); try { iterator.next(); @@ -89,7 +90,7 @@ public class BooleanArrayListTest extends TestCase { } catch (ConcurrentModificationException e) { // expected } - + iterator = list.iterator(); list.add(0, false); try { @@ -99,19 +100,19 @@ public class BooleanArrayListTest extends TestCase { // expected } } - + public void testGet() { assertEquals(true, (boolean) TERTIARY_LIST.get(0)); - assertEquals(true, (boolean) TERTIARY_LIST.get(1)); - assertEquals(false, (boolean) TERTIARY_LIST.get(2)); - + assertEquals(false, (boolean) TERTIARY_LIST.get(1)); + assertEquals(true, (boolean) TERTIARY_LIST.get(2)); + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -119,19 +120,19 @@ public class BooleanArrayListTest extends TestCase { // expected } } - - public void testGetInt() { + + public void testGetBoolean() { assertEquals(true, TERTIARY_LIST.getBoolean(0)); - assertEquals(true, TERTIARY_LIST.getBoolean(1)); - assertEquals(false, TERTIARY_LIST.getBoolean(2)); - + assertEquals(false, TERTIARY_LIST.getBoolean(1)); + assertEquals(true, TERTIARY_LIST.getBoolean(2)); + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -139,7 +140,7 @@ public class BooleanArrayListTest extends TestCase { // expected } } - + public void testSize() { assertEquals(0, BooleanArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); @@ -150,26 +151,26 @@ public class BooleanArrayListTest extends TestCase { list.addBoolean(false); list.addBoolean(false); assertEquals(4, list.size()); - + list.remove(0); assertEquals(3, list.size()); - + list.add(true); assertEquals(4, list.size()); } - + public void testSet() { list.addBoolean(false); list.addBoolean(false); - + assertEquals(false, (boolean) list.set(0, true)); assertEquals(true, list.getBoolean(0)); assertEquals(false, (boolean) list.set(1, false)); assertEquals(false, list.getBoolean(1)); - + try { - list.set(-1, true); + list.set(-1, false); fail(); } catch (IndexOutOfBoundsException e) { // expected @@ -182,17 +183,17 @@ public class BooleanArrayListTest extends TestCase { // expected } } - - public void testSetInt() { + + public void testSetBoolean() { list.addBoolean(true); list.addBoolean(true); - + assertEquals(true, list.setBoolean(0, false)); assertEquals(false, list.getBoolean(0)); assertEquals(true, list.setBoolean(1, false)); assertEquals(false, list.getBoolean(1)); - + try { list.setBoolean(-1, false); fail(); @@ -201,76 +202,78 @@ public class BooleanArrayListTest extends TestCase { } try { - list.setBoolean(2, true); + list.setBoolean(2, false); fail(); } catch (IndexOutOfBoundsException e) { // expected } } - + public void testAdd() { assertEquals(0, list.size()); - assertTrue(list.add(true)); - assertEquals(asList(true), list); - assertTrue(list.add(false)); + assertEquals(asList(false), list); + + assertTrue(list.add(true)); list.add(0, false); - assertEquals(asList(false, true, false), list); - - list.add(0, false); + assertEquals(asList(false, false, true), list); + list.add(0, true); + list.add(0, false); // Force a resize by getting up to 11 elements. for (int i = 0; i < 6; i++) { - list.add(true); + list.add(i % 2 == 0); } - assertEquals(asList(true, false, false, true, false, true, true, true, true, true, true), list); - + assertEquals( + asList(false, true, false, false, true, true, false, true, false, true, false), + list); + try { - list.add(-1, false); + list.add(-1, true); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.add(4, true); } catch (IndexOutOfBoundsException e) { // expected } } - - public void testAddInt() { - assertEquals(0, list.size()); - list.addBoolean(true); - assertEquals(asList(true), list); + public void testAddBoolean() { + assertEquals(0, list.size()); list.addBoolean(false); - assertEquals(asList(true, false), list); + assertEquals(asList(false), list); + + list.addBoolean(true); + assertEquals(asList(false, true), list); } - + public void testAddAll() { assertEquals(0, list.size()); - assertTrue(list.addAll(Collections.singleton(false))); + assertTrue(list.addAll(Collections.singleton(true))); assertEquals(1, list.size()); - assertEquals(false, (boolean) list.get(0)); - assertEquals(false, list.getBoolean(0)); - - assertTrue(list.addAll(asList(true, false, false, false, true))); - assertEquals(asList(false, true, false, false, false, true), list); - + assertEquals(true, (boolean) list.get(0)); + assertEquals(true, list.getBoolean(0)); + + assertTrue(list.addAll(asList(false, true, false, true, false))); + assertEquals(asList(true, false, true, false, true, false), list); + assertTrue(list.addAll(TERTIARY_LIST)); - assertEquals(asList(false, true, false, false, false, true, true, true, false), list); + assertEquals(asList(true, false, true, false, true, false, true, false, true), list); assertFalse(list.addAll(Collections.<Boolean>emptyList())); assertFalse(list.addAll(BooleanArrayList.emptyList())); } - + public void testRemove() { list.addAll(TERTIARY_LIST); assertEquals(true, (boolean) list.remove(0)); - assertEquals(asList(true, false), list); + assertEquals(asList(false, true), list); assertTrue(list.remove(Boolean.TRUE)); assertEquals(asList(false), list); @@ -280,92 +283,93 @@ public class BooleanArrayListTest extends TestCase { assertEquals(false, (boolean) list.remove(0)); assertEquals(asList(), list); - + try { list.remove(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.remove(0); } catch (IndexOutOfBoundsException e) { // expected } } - + private void assertImmutable(BooleanArrayList list) { + try { - list.add(false); + list.add(true); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.add(0, true); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.<Boolean>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { - list.addAll(Collections.singletonList(false)); + list.addAll(Collections.singletonList(true)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(new BooleanArrayList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.singleton(true)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.<Boolean>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { - list.addBoolean(true); + list.addBoolean(false); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.clear(); fail(); @@ -379,63 +383,63 @@ public class BooleanArrayListTest extends TestCase { } catch (UnsupportedOperationException e) { // expected } - + try { list.remove(new Object()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.<Boolean>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.singleton(Boolean.TRUE)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.<Boolean>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { - list.retainAll(Collections.singleton(Boolean.TRUE)); + list.removeAll(Collections.singleton(Boolean.TRUE)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { - list.set(0, true); + list.set(0, false); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.setBoolean(0, false); fail(); @@ -443,7 +447,7 @@ public class BooleanArrayListTest extends TestCase { // expected } } - + private static BooleanArrayList newImmutableBooleanArrayList(boolean... elements) { BooleanArrayList list = new BooleanArrayList(); for (boolean element : elements) { diff --git a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java index ef89b389..b3302441 100644 --- a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java +++ b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java @@ -382,6 +382,14 @@ public class DescriptorsTest extends TestCase { assertEquals(Long.valueOf(8765432109L), field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1)); + OneofDescriptor oneof = descriptor.getOneofs().get(0); + assertNotNull(oneof); + + assertTrue( + oneof.getOptions().hasExtension(UnittestCustomOptions.oneofOpt1)); + assertEquals(Integer.valueOf(-99), + oneof.getOptions().getExtension(UnittestCustomOptions.oneofOpt1)); + EnumDescriptor enumType = UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor(); diff --git a/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java index 85b418c4..8e8e4fe2 100644 --- a/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java @@ -40,39 +40,40 @@ import java.util.Iterator; /** * Tests for {@link DoubleArrayList}. - * + * * @author dweis@google.com (Daniel Weis) */ public class DoubleArrayListTest extends TestCase { - - private static final DoubleArrayList UNARY_LIST = newImmutableDoubleArrayList(1); + + private static final DoubleArrayList UNARY_LIST = + newImmutableDoubleArrayList(1); private static final DoubleArrayList TERTIARY_LIST = newImmutableDoubleArrayList(1, 2, 3); - + private DoubleArrayList list; - + @Override protected void setUp() throws Exception { list = new DoubleArrayList(); } - + public void testEmptyListReturnsSameInstance() { assertSame(DoubleArrayList.emptyList(), DoubleArrayList.emptyList()); } - + public void testEmptyListIsImmutable() { assertImmutable(DoubleArrayList.emptyList()); } - + public void testMakeImmutable() { - list.addDouble(2); + list.addDouble(3); list.addDouble(4); - list.addDouble(6); - list.addDouble(8); + list.addDouble(5); + list.addDouble(7); list.makeImmutable(); assertImmutable(list); } - + public void testModificationWithIteration() { list.addAll(asList(1D, 2D, 3D, 4D)); Iterator<Double> iterator = list.iterator(); @@ -81,7 +82,7 @@ public class DoubleArrayListTest extends TestCase { assertEquals(1D, (double) iterator.next()); list.set(0, 1D); assertEquals(2D, (double) iterator.next()); - + list.remove(0); try { iterator.next(); @@ -89,7 +90,7 @@ public class DoubleArrayListTest extends TestCase { } catch (ConcurrentModificationException e) { // expected } - + iterator = list.iterator(); list.add(0, 0D); try { @@ -99,19 +100,19 @@ public class DoubleArrayListTest extends TestCase { // expected } } - + public void testGet() { assertEquals(1D, (double) TERTIARY_LIST.get(0)); assertEquals(2D, (double) TERTIARY_LIST.get(1)); assertEquals(3D, (double) TERTIARY_LIST.get(2)); - + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -119,19 +120,19 @@ public class DoubleArrayListTest extends TestCase { // expected } } - - public void testGetInt() { + + public void testGetDouble() { assertEquals(1D, TERTIARY_LIST.getDouble(0)); assertEquals(2D, TERTIARY_LIST.getDouble(1)); assertEquals(3D, TERTIARY_LIST.getDouble(2)); - + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -139,35 +140,35 @@ public class DoubleArrayListTest extends TestCase { // expected } } - + public void testSize() { assertEquals(0, DoubleArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); assertEquals(3, TERTIARY_LIST.size()); - list.addDouble(2); + list.addDouble(3); list.addDouble(4); list.addDouble(6); list.addDouble(8); assertEquals(4, list.size()); - + list.remove(0); assertEquals(3, list.size()); - - list.add(16D); + + list.add(17D); assertEquals(4, list.size()); } - + public void testSet() { list.addDouble(2); list.addDouble(4); - - assertEquals(2D, (double) list.set(0, 0D)); - assertEquals(0D, list.getDouble(0)); + + assertEquals(2D, (double) list.set(0, 3D)); + assertEquals(3D, list.getDouble(0)); assertEquals(4D, (double) list.set(1, 0D)); assertEquals(0D, list.getDouble(1)); - + try { list.set(-1, 0D); fail(); @@ -182,17 +183,17 @@ public class DoubleArrayListTest extends TestCase { // expected } } - - public void testSetInt() { - list.addDouble(2); - list.addDouble(4); - - assertEquals(2D, list.setDouble(0, 0)); + + public void testSetDouble() { + list.addDouble(1); + list.addDouble(3); + + assertEquals(1D, list.setDouble(0, 0)); assertEquals(0D, list.getDouble(0)); - assertEquals(4D, list.setDouble(1, 0)); + assertEquals(3D, list.setDouble(1, 0)); assertEquals(0D, list.getDouble(1)); - + try { list.setDouble(-1, 0); fail(); @@ -207,7 +208,7 @@ public class DoubleArrayListTest extends TestCase { // expected } } - + public void testAdd() { assertEquals(0, list.size()); @@ -217,29 +218,31 @@ public class DoubleArrayListTest extends TestCase { assertTrue(list.add(3D)); list.add(0, 4D); assertEquals(asList(4D, 2D, 3D), list); - + list.add(0, 1D); list.add(0, 0D); // Force a resize by getting up to 11 elements. for (int i = 0; i < 6; i++) { list.add(Double.valueOf(5 + i)); } - assertEquals(asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), list); - + assertEquals( + asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), + list); + try { list.add(-1, 5D); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.add(4, 5D); } catch (IndexOutOfBoundsException e) { // expected } } - - public void testAddInt() { + + public void testAddDouble() { assertEquals(0, list.size()); list.addDouble(2); @@ -248,7 +251,7 @@ public class DoubleArrayListTest extends TestCase { list.addDouble(3); assertEquals(asList(2D, 3D), list); } - + public void testAddAll() { assertEquals(0, list.size()); @@ -256,17 +259,17 @@ public class DoubleArrayListTest extends TestCase { assertEquals(1, list.size()); assertEquals(1D, (double) list.get(0)); assertEquals(1D, list.getDouble(0)); - + assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D))); assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list); - + assertTrue(list.addAll(TERTIARY_LIST)); assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D, 1D, 2D, 3D), list); assertFalse(list.addAll(Collections.<Double>emptyList())); assertFalse(list.addAll(DoubleArrayList.emptyList())); } - + public void testRemove() { list.addAll(TERTIARY_LIST); assertEquals(1D, (double) list.remove(0)); @@ -280,96 +283,96 @@ public class DoubleArrayListTest extends TestCase { assertEquals(2D, (double) list.remove(0)); assertEquals(asList(), list); - + try { list.remove(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.remove(0); } catch (IndexOutOfBoundsException e) { // expected } } - + private void assertImmutable(DoubleArrayList list) { if (list.contains(1D)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } - + try { list.add(1D); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.add(0, 1D); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.<Double>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.singletonList(1D)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(new DoubleArrayList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.singleton(1D)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.<Double>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addDouble(0); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.clear(); fail(); @@ -383,28 +386,28 @@ public class DoubleArrayListTest extends TestCase { } catch (UnsupportedOperationException e) { // expected } - + try { list.remove(new Object()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.<Double>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.singleton(1D)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(UNARY_LIST); fail(); @@ -418,28 +421,28 @@ public class DoubleArrayListTest extends TestCase { } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.singleton(1D)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.set(0, 0D); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.setDouble(0, 0); fail(); @@ -447,7 +450,7 @@ public class DoubleArrayListTest extends TestCase { // expected } } - + private static DoubleArrayList newImmutableDoubleArrayList(double... elements) { DoubleArrayList list = new DoubleArrayList(); for (double element : elements) { diff --git a/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java b/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java new file mode 100644 index 00000000..c1246782 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java @@ -0,0 +1,245 @@ +// 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; + +import protobuf_unittest.NonNestedExtension; +import protobuf_unittest.NonNestedExtensionLite; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import java.lang.reflect.Method; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * Tests for {@link ExtensionRegistryFactory} and the {@link ExtensionRegistry} instances it + * creates. + * + * <p>This test simulates the runtime behaviour of the ExtensionRegistryFactory by delegating test + * definitions to two inner classes {@link InnerTest} and {@link InnerLiteTest}, the latter of + * which is executed using a custom ClassLoader, simulating the ProtoLite environment. + * + * <p>The test mechanism employed here is based on the pattern in + * {@code com.google.common.util.concurrent.AbstractFutureFallbackAtomicHelperTest} + */ +public class ExtensionRegistryFactoryTest extends TestCase { + + // A classloader which blacklists some non-Lite classes. + private static final ClassLoader LITE_CLASS_LOADER = getLiteOnlyClassLoader(); + + /** + * Defines the set of test methods which will be run. + */ + static interface RegistryTests { + void testCreate(); + void testEmpty(); + void testIsFullRegistry(); + void testAdd(); + } + + /** + * Test implementations for the non-Lite usage of ExtensionRegistryFactory. + */ + public static class InnerTest implements RegistryTests { + + @Override + public void testCreate() { + ExtensionRegistryLite registry = ExtensionRegistryFactory.create(); + + assertEquals(registry.getClass(), ExtensionRegistry.class); + } + + @Override + public void testEmpty() { + ExtensionRegistryLite emptyRegistry = ExtensionRegistryFactory.createEmpty(); + + assertEquals(emptyRegistry.getClass(), ExtensionRegistry.class); + assertEquals(emptyRegistry, ExtensionRegistry.EMPTY_REGISTRY); + } + + @Override + public void testIsFullRegistry() { + ExtensionRegistryLite registry = ExtensionRegistryFactory.create(); + assertTrue(ExtensionRegistryFactory.isFullRegistry(registry)); + } + + @Override + public void testAdd() { + ExtensionRegistryLite registry1 = ExtensionRegistryLite.newInstance(); + NonNestedExtensionLite.registerAllExtensions(registry1); + registry1.add(NonNestedExtensionLite.nonNestedExtensionLite); + + ExtensionRegistryLite registry2 = ExtensionRegistryLite.newInstance(); + NonNestedExtension.registerAllExtensions((ExtensionRegistry) registry2); + registry2.add(NonNestedExtension.nonNestedExtension); + + ExtensionRegistry fullRegistry1 = (ExtensionRegistry) registry1; + ExtensionRegistry fullRegistry2 = (ExtensionRegistry) registry2; + + assertTrue("Test is using a non-lite extension", + GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom( + NonNestedExtensionLite.nonNestedExtensionLite.getClass())); + assertNull("Extension is not registered in masqueraded full registry", + fullRegistry1.findImmutableExtensionByName("protobuf_unittest.nonNestedExtension")); + GeneratedMessageLite.GeneratedExtension<NonNestedExtensionLite.MessageLiteToBeExtended, ?> + extension = registry1.findLiteExtensionByNumber( + NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1); + assertNotNull("Extension registered in lite registry", extension); + + assertTrue("Test is using a non-lite extension", + GeneratedMessage.GeneratedExtension.class.isAssignableFrom( + NonNestedExtension.nonNestedExtension.getClass())); + assertNotNull("Extension is registered in masqueraded full registry", + fullRegistry2.findImmutableExtensionByName("protobuf_unittest.nonNestedExtension")); + } + } + + /** + * Test implementations for the Lite usage of ExtensionRegistryFactory. + */ + public static final class InnerLiteTest implements RegistryTests { + + @Override + public void testCreate() { + ExtensionRegistryLite registry = ExtensionRegistryFactory.create(); + + assertEquals(registry.getClass(), ExtensionRegistryLite.class); + } + + @Override + public void testEmpty() { + ExtensionRegistryLite emptyRegistry = ExtensionRegistryFactory.createEmpty(); + + assertEquals(emptyRegistry.getClass(), ExtensionRegistryLite.class); + assertEquals(emptyRegistry, ExtensionRegistryLite.EMPTY_REGISTRY_LITE); + } + + @Override + public void testIsFullRegistry() { + ExtensionRegistryLite registry = ExtensionRegistryFactory.create(); + assertFalse(ExtensionRegistryFactory.isFullRegistry(registry)); + } + + @Override + public void testAdd() { + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + NonNestedExtensionLite.registerAllExtensions(registry); + GeneratedMessageLite.GeneratedExtension<NonNestedExtensionLite.MessageLiteToBeExtended, ?> + extension = registry.findLiteExtensionByNumber( + NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1); + assertNotNull("Extension is registered in Lite registry", extension); + } + } + + /** + * Defines a suite of tests which the JUnit3 runner retrieves by reflection. + */ + public static Test suite() { + TestSuite suite = new TestSuite(); + for (Method method : RegistryTests.class.getMethods()) { + suite.addTest(TestSuite.createTest(ExtensionRegistryFactoryTest.class, method.getName())); + } + return suite; + } + + /** + * Sequentially runs first the Lite and then the non-Lite test variant via classloader + * manipulation. + */ + @Override + public void runTest() throws Exception { + ClassLoader storedClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(LITE_CLASS_LOADER); + try { + runTestMethod(LITE_CLASS_LOADER, InnerLiteTest.class); + } finally { + Thread.currentThread().setContextClassLoader(storedClassLoader); + } + try { + runTestMethod(storedClassLoader, InnerTest.class); + } finally { + Thread.currentThread().setContextClassLoader(storedClassLoader); + } + } + + private void runTestMethod(ClassLoader classLoader, Class<? extends RegistryTests> testClass) + throws Exception { + classLoader.loadClass(ExtensionRegistryFactory.class.getName()); + Class<?> test = classLoader.loadClass(testClass.getName()); + String testName = getName(); + test.getMethod(testName).invoke(test.newInstance()); + } + + /** + * Constructs a custom ClassLoader blacklisting the classes which are inspected in the SUT + * to determine the Lite/non-Lite runtime. + */ + private static ClassLoader getLiteOnlyClassLoader() { + ClassLoader testClassLoader = ExtensionRegistryFactoryTest.class.getClassLoader(); + final Set<String> classNamesNotInLite = + Collections.unmodifiableSet( + new HashSet<String>( + Arrays.asList( + ExtensionRegistryFactory.FULL_REGISTRY_CLASS_NAME, + ExtensionRegistry.EXTENSION_CLASS_NAME))); + + // Construct a URLClassLoader delegating to the system ClassLoader, and looking up classes + // in jar files based on the URLs already configured for this test's UrlClassLoader. + // Certain classes throw a ClassNotFoundException by design. + return new URLClassLoader(((URLClassLoader) testClassLoader).getURLs(), + ClassLoader.getSystemClassLoader()) { + @Override + public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (classNamesNotInLite.contains(name)) { + throw new ClassNotFoundException("Class deliberately blacklisted by test."); + } + Class<?> loadedClass = null; + try { + loadedClass = findLoadedClass(name); + if (loadedClass == null) { + loadedClass = findClass(name); + if (resolve) { + resolveClass(loadedClass); + } + } + } catch (ClassNotFoundException e) { + loadedClass = super.loadClass(name, resolve); + } + return loadedClass; + } + }; + } +} diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java index 304cec4f..82f4216b 100644 --- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java +++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java @@ -152,6 +152,26 @@ public class FieldPresenceTest extends TestCase { assertFalse(message1.equals(message2)); } + public void testLazyField() throws Exception { + // Test default constructed message. + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TestAllTypes message = builder.build(); + assertFalse(message.hasOptionalLazyMessage()); + assertEquals(0, message.getSerializedSize()); + assertEquals(ByteString.EMPTY, message.toByteString()); + + // Set default instance to the field. + builder.setOptionalLazyMessage(TestAllTypes.NestedMessage.getDefaultInstance()); + message = builder.build(); + assertTrue(message.hasOptionalLazyMessage()); + assertEquals(2, message.getSerializedSize()); + + // Test parse zero-length from wire sets the presence. + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteString()); + assertTrue(parsed.hasOptionalLazyMessage()); + assertEquals(message.getOptionalLazyMessage(), parsed.getOptionalLazyMessage()); + } + public void testFieldPresence() { // Optional non-message fields set to their default value are treated the // same way as not set. diff --git a/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java index 88a75743..0e13a598 100644 --- a/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java @@ -40,39 +40,40 @@ import java.util.Iterator; /** * Tests for {@link FloatArrayList}. - * + * * @author dweis@google.com (Daniel Weis) */ public class FloatArrayListTest extends TestCase { - - private static final FloatArrayList UNARY_LIST = newImmutableFloatArrayList(1); + + private static final FloatArrayList UNARY_LIST = + newImmutableFloatArrayList(1); private static final FloatArrayList TERTIARY_LIST = newImmutableFloatArrayList(1, 2, 3); - + private FloatArrayList list; - + @Override protected void setUp() throws Exception { list = new FloatArrayList(); } - + public void testEmptyListReturnsSameInstance() { assertSame(FloatArrayList.emptyList(), FloatArrayList.emptyList()); } - + public void testEmptyListIsImmutable() { assertImmutable(FloatArrayList.emptyList()); } - + public void testMakeImmutable() { - list.addFloat(2); + list.addFloat(3); list.addFloat(4); - list.addFloat(6); - list.addFloat(8); + list.addFloat(5); + list.addFloat(7); list.makeImmutable(); assertImmutable(list); } - + public void testModificationWithIteration() { list.addAll(asList(1F, 2F, 3F, 4F)); Iterator<Float> iterator = list.iterator(); @@ -81,7 +82,7 @@ public class FloatArrayListTest extends TestCase { assertEquals(1F, (float) iterator.next()); list.set(0, 1F); assertEquals(2F, (float) iterator.next()); - + list.remove(0); try { iterator.next(); @@ -89,7 +90,7 @@ public class FloatArrayListTest extends TestCase { } catch (ConcurrentModificationException e) { // expected } - + iterator = list.iterator(); list.add(0, 0F); try { @@ -99,19 +100,19 @@ public class FloatArrayListTest extends TestCase { // expected } } - + public void testGet() { assertEquals(1F, (float) TERTIARY_LIST.get(0)); assertEquals(2F, (float) TERTIARY_LIST.get(1)); assertEquals(3F, (float) TERTIARY_LIST.get(2)); - + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -119,19 +120,19 @@ public class FloatArrayListTest extends TestCase { // expected } } - + public void testGetFloat() { assertEquals(1F, TERTIARY_LIST.getFloat(0)); assertEquals(2F, TERTIARY_LIST.getFloat(1)); assertEquals(3F, TERTIARY_LIST.getFloat(2)); - + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -139,35 +140,35 @@ public class FloatArrayListTest extends TestCase { // expected } } - + public void testSize() { assertEquals(0, FloatArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); assertEquals(3, TERTIARY_LIST.size()); - list.addFloat(2); + list.addFloat(3); list.addFloat(4); list.addFloat(6); list.addFloat(8); assertEquals(4, list.size()); - + list.remove(0); assertEquals(3, list.size()); - - list.add(16F); + + list.add(17F); assertEquals(4, list.size()); } - + public void testSet() { list.addFloat(2); list.addFloat(4); - - assertEquals(2F, (float) list.set(0, 0F)); - assertEquals(0F, list.getFloat(0)); + + assertEquals(2F, (float) list.set(0, 3F)); + assertEquals(3F, list.getFloat(0)); assertEquals(4F, (float) list.set(1, 0F)); assertEquals(0F, list.getFloat(1)); - + try { list.set(-1, 0F); fail(); @@ -182,17 +183,17 @@ public class FloatArrayListTest extends TestCase { // expected } } - + public void testSetFloat() { - list.addFloat(2); - list.addFloat(4); - - assertEquals(2F, list.setFloat(0, 0)); + list.addFloat(1); + list.addFloat(3); + + assertEquals(1F, list.setFloat(0, 0)); assertEquals(0F, list.getFloat(0)); - assertEquals(4F, list.setFloat(1, 0)); + assertEquals(3F, list.setFloat(1, 0)); assertEquals(0F, list.getFloat(1)); - + try { list.setFloat(-1, 0); fail(); @@ -207,7 +208,7 @@ public class FloatArrayListTest extends TestCase { // expected } } - + public void testAdd() { assertEquals(0, list.size()); @@ -217,28 +218,30 @@ public class FloatArrayListTest extends TestCase { assertTrue(list.add(3F)); list.add(0, 4F); assertEquals(asList(4F, 2F, 3F), list); - + list.add(0, 1F); list.add(0, 0F); // Force a resize by getting up to 11 elements. for (int i = 0; i < 6; i++) { list.add(Float.valueOf(5 + i)); } - assertEquals(asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), list); - + assertEquals( + asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), + list); + try { list.add(-1, 5F); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.add(4, 5F); } catch (IndexOutOfBoundsException e) { // expected } } - + public void testAddFloat() { assertEquals(0, list.size()); @@ -248,7 +251,7 @@ public class FloatArrayListTest extends TestCase { list.addFloat(3); assertEquals(asList(2F, 3F), list); } - + public void testAddAll() { assertEquals(0, list.size()); @@ -256,17 +259,17 @@ public class FloatArrayListTest extends TestCase { assertEquals(1, list.size()); assertEquals(1F, (float) list.get(0)); assertEquals(1F, list.getFloat(0)); - + assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F))); assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list); - + assertTrue(list.addAll(TERTIARY_LIST)); assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F, 1F, 2F, 3F), list); assertFalse(list.addAll(Collections.<Float>emptyList())); assertFalse(list.addAll(FloatArrayList.emptyList())); } - + public void testRemove() { list.addAll(TERTIARY_LIST); assertEquals(1F, (float) list.remove(0)); @@ -280,96 +283,96 @@ public class FloatArrayListTest extends TestCase { assertEquals(2F, (float) list.remove(0)); assertEquals(asList(), list); - + try { list.remove(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.remove(0); } catch (IndexOutOfBoundsException e) { // expected } } - + private void assertImmutable(FloatArrayList list) { if (list.contains(1F)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } - + try { list.add(1F); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.add(0, 1F); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.<Float>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.singletonList(1F)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(new FloatArrayList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.singleton(1F)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.<Float>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addFloat(0); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.clear(); fail(); @@ -383,63 +386,63 @@ public class FloatArrayListTest extends TestCase { } catch (UnsupportedOperationException e) { // expected } - + try { list.remove(new Object()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.<Float>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.singleton(1F)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.<Float>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.singleton(1F)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.set(0, 0F); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.setFloat(0, 0); fail(); @@ -447,10 +450,10 @@ public class FloatArrayListTest extends TestCase { // expected } } - - private static FloatArrayList newImmutableFloatArrayList(int... elements) { + + private static FloatArrayList newImmutableFloatArrayList(float... elements) { FloatArrayList list = new FloatArrayList(); - for (int element : elements) { + for (float element : elements) { list.addFloat(element); } list.makeImmutable(); diff --git a/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java index efb8f3e2..e59e3c6e 100644 --- a/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java @@ -40,35 +40,36 @@ import java.util.Iterator; /** * Tests for {@link IntArrayList}. - * + * * @author dweis@google.com (Daniel Weis) */ public class IntArrayListTest extends TestCase { - - private static final IntArrayList UNARY_LIST = newImmutableIntArrayList(1); + + private static final IntArrayList UNARY_LIST = + newImmutableIntArrayList(1); private static final IntArrayList TERTIARY_LIST = newImmutableIntArrayList(1, 2, 3); - + private IntArrayList list; - + @Override protected void setUp() throws Exception { list = new IntArrayList(); } - + public void testEmptyListReturnsSameInstance() { assertSame(IntArrayList.emptyList(), IntArrayList.emptyList()); } - + public void testEmptyListIsImmutable() { assertImmutable(IntArrayList.emptyList()); } - + public void testMakeImmutable() { - list.addInt(2); + list.addInt(3); list.addInt(4); - list.addInt(6); - list.addInt(8); + list.addInt(5); + list.addInt(7); list.makeImmutable(); assertImmutable(list); } @@ -81,7 +82,7 @@ public class IntArrayListTest extends TestCase { assertEquals(1, (int) iterator.next()); list.set(0, 1); assertEquals(2, (int) iterator.next()); - + list.remove(0); try { iterator.next(); @@ -99,19 +100,19 @@ public class IntArrayListTest extends TestCase { // expected } } - + public void testGet() { assertEquals(1, (int) TERTIARY_LIST.get(0)); assertEquals(2, (int) TERTIARY_LIST.get(1)); assertEquals(3, (int) TERTIARY_LIST.get(2)); - + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -119,19 +120,19 @@ public class IntArrayListTest extends TestCase { // expected } } - + public void testGetInt() { assertEquals(1, TERTIARY_LIST.getInt(0)); assertEquals(2, TERTIARY_LIST.getInt(1)); assertEquals(3, TERTIARY_LIST.getInt(2)); - + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -139,35 +140,35 @@ public class IntArrayListTest extends TestCase { // expected } } - + public void testSize() { assertEquals(0, IntArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); assertEquals(3, TERTIARY_LIST.size()); - list.addInt(2); + list.addInt(3); list.addInt(4); list.addInt(6); list.addInt(8); assertEquals(4, list.size()); - + list.remove(0); assertEquals(3, list.size()); - - list.add(16); + + list.add(17); assertEquals(4, list.size()); } - + public void testSet() { list.addInt(2); list.addInt(4); - - assertEquals(2, (int) list.set(0, 0)); - assertEquals(0, list.getInt(0)); + + assertEquals(2, (int) list.set(0, 3)); + assertEquals(3, list.getInt(0)); assertEquals(4, (int) list.set(1, 0)); assertEquals(0, list.getInt(1)); - + try { list.set(-1, 0); fail(); @@ -182,17 +183,17 @@ public class IntArrayListTest extends TestCase { // expected } } - + public void testSetInt() { - list.addInt(2); - list.addInt(4); - - assertEquals(2, list.setInt(0, 0)); + list.addInt(1); + list.addInt(3); + + assertEquals(1, list.setInt(0, 0)); assertEquals(0, list.getInt(0)); - assertEquals(4, list.setInt(1, 0)); + assertEquals(3, list.setInt(1, 0)); assertEquals(0, list.getInt(1)); - + try { list.setInt(-1, 0); fail(); @@ -207,7 +208,7 @@ public class IntArrayListTest extends TestCase { // expected } } - + public void testAdd() { assertEquals(0, list.size()); @@ -217,28 +218,30 @@ public class IntArrayListTest extends TestCase { assertTrue(list.add(3)); list.add(0, 4); assertEquals(asList(4, 2, 3), list); - + list.add(0, 1); list.add(0, 0); // Force a resize by getting up to 11 elements. for (int i = 0; i < 6; i++) { - list.add(5 + i); + list.add(Integer.valueOf(5 + i)); } - assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list); - + assertEquals( + asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), + list); + try { list.add(-1, 5); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.add(4, 5); } catch (IndexOutOfBoundsException e) { // expected } } - + public void testAddInt() { assertEquals(0, list.size()); @@ -248,7 +251,7 @@ public class IntArrayListTest extends TestCase { list.addInt(3); assertEquals(asList(2, 3), list); } - + public void testAddAll() { assertEquals(0, list.size()); @@ -256,17 +259,17 @@ public class IntArrayListTest extends TestCase { assertEquals(1, list.size()); assertEquals(1, (int) list.get(0)); assertEquals(1, list.getInt(0)); - + assertTrue(list.addAll(asList(2, 3, 4, 5, 6))); assertEquals(asList(1, 2, 3, 4, 5, 6), list); - + assertTrue(list.addAll(TERTIARY_LIST)); assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list); assertFalse(list.addAll(Collections.<Integer>emptyList())); assertFalse(list.addAll(IntArrayList.emptyList())); } - + public void testRemove() { list.addAll(TERTIARY_LIST); assertEquals(1, (int) list.remove(0)); @@ -280,96 +283,96 @@ public class IntArrayListTest extends TestCase { assertEquals(2, (int) list.remove(0)); assertEquals(asList(), list); - + try { list.remove(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.remove(0); } catch (IndexOutOfBoundsException e) { // expected } } - + private void assertImmutable(IntArrayList list) { if (list.contains(1)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } - + try { list.add(1); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.add(0, 1); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.<Integer>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.singletonList(1)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(new IntArrayList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.singleton(1)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.<Integer>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addInt(0); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.clear(); fail(); @@ -383,63 +386,63 @@ public class IntArrayListTest extends TestCase { } catch (UnsupportedOperationException e) { // expected } - + try { list.remove(new Object()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.<Integer>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.singleton(1)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.<Integer>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.singleton(1)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.set(0, 0); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.setInt(0, 0); fail(); @@ -447,7 +450,7 @@ public class IntArrayListTest extends TestCase { // expected } } - + private static IntArrayList newImmutableIntArrayList(int... elements) { IntArrayList list = new IntArrayList(); for (int element : elements) { diff --git a/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java index afe0fffd..e5b11cf1 100644 --- a/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java @@ -251,6 +251,23 @@ public class LazyMessageLiteTest extends TestCase { assertEquals(42, merged.getOneofInner().getNumWithDefault()); } + // Regression test for b/28198805. + public void testMergeOneofMessages() throws Exception { + LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder().build(); + LazyMessageLite outer = LazyMessageLite.newBuilder().setOneofInner(inner).build(); + ByteString data1 = outer.toByteString(); + + // The following should not alter the content of the 'outer' message. + LazyMessageLite.Builder merged = LazyMessageLite.newBuilder().mergeFrom(outer); + LazyInnerMessageLite anotherInner = LazyInnerMessageLite.newBuilder().setNum(12345).build(); + merged.setOneofInner(anotherInner); + + // Check that the 'outer' stays the same. + ByteString data2 = outer.toByteString(); + assertEquals(data1, data2); + assertEquals(0, outer.getOneofInner().getNum()); + } + public void testSerialize() throws InvalidProtocolBufferException { LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder() .setNum(3) diff --git a/java/core/src/test/java/com/google/protobuf/LiteTest.java b/java/core/src/test/java/com/google/protobuf/LiteTest.java index 88c3e0b2..b3a246dc 100644 --- a/java/core/src/test/java/com/google/protobuf/LiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/LiteTest.java @@ -1630,7 +1630,7 @@ public class LiteTest extends TestCase { fail(); } catch (InvalidProtocolBufferException expected) {} } - + public void testMergeFrom_sanity() throws Exception { TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build(); byte[] bytes = one.toByteArray(); @@ -1642,7 +1642,19 @@ public class LiteTest extends TestCase { assertEquals(two, one); assertEquals(one.hashCode(), two.hashCode()); } - + + public void testMergeFromNoLazyFieldSharing() throws Exception { + TestAllTypesLite.Builder sourceBuilder = TestAllTypesLite.newBuilder().setOptionalLazyMessage( + TestAllTypesLite.NestedMessage.newBuilder().setBb(1)); + TestAllTypesLite.Builder targetBuilder = + TestAllTypesLite.newBuilder().mergeFrom(sourceBuilder.build()); + assertEquals(1, sourceBuilder.getOptionalLazyMessage().getBb()); + // now change the sourceBuilder, and target value shouldn't be affected. + sourceBuilder.setOptionalLazyMessage( + TestAllTypesLite.NestedMessage.newBuilder().setBb(2)); + assertEquals(1, targetBuilder.getOptionalLazyMessage().getBb()); + } + public void testEquals_notEqual() throws Exception { TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build(); byte[] bytes = one.toByteArray(); @@ -2202,6 +2214,21 @@ public class LiteTest extends TestCase { assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields); assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields); } + + public void testEqualsAndHashCodeWithExtensions() throws InvalidProtocolBufferException { + Foo fooWithOnlyValue = Foo.newBuilder() + .setValue(1) + .build(); + + Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder() + .setValue(1) + .setExtension(Bar.fooExt, Bar.newBuilder() + .setName("name") + .build()) + .build(); + + assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndExtension); + } // Test to ensure we avoid a class cast exception with oneofs. public void testEquals_oneOfMessages() { diff --git a/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java index 0a8f9ed2..6aaf85d7 100644 --- a/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java @@ -40,48 +40,49 @@ import java.util.Iterator; /** * Tests for {@link LongArrayList}. - * + * * @author dweis@google.com (Daniel Weis) */ public class LongArrayListTest extends TestCase { - - private static final LongArrayList UNARY_LIST = newImmutableLongArrayList(1); + + private static final LongArrayList UNARY_LIST = + newImmutableLongArrayList(1); private static final LongArrayList TERTIARY_LIST = newImmutableLongArrayList(1, 2, 3); - + private LongArrayList list; - + @Override protected void setUp() throws Exception { list = new LongArrayList(); } - + public void testEmptyListReturnsSameInstance() { assertSame(LongArrayList.emptyList(), LongArrayList.emptyList()); } - + public void testEmptyListIsImmutable() { assertImmutable(LongArrayList.emptyList()); } - + public void testMakeImmutable() { - list.addLong(2); + list.addLong(3); list.addLong(4); - list.addLong(6); - list.addLong(8); + list.addLong(5); + list.addLong(7); list.makeImmutable(); assertImmutable(list); } - + public void testModificationWithIteration() { list.addAll(asList(1L, 2L, 3L, 4L)); Iterator<Long> iterator = list.iterator(); assertEquals(4, list.size()); - assertEquals(1, (long) list.get(0)); - assertEquals(1, (long) iterator.next()); + assertEquals(1L, (long) list.get(0)); + assertEquals(1L, (long) iterator.next()); list.set(0, 1L); - assertEquals(2, (long) iterator.next()); - + assertEquals(2L, (long) iterator.next()); + list.remove(0); try { iterator.next(); @@ -89,7 +90,7 @@ public class LongArrayListTest extends TestCase { } catch (ConcurrentModificationException e) { // expected } - + iterator = list.iterator(); list.add(0, 0L); try { @@ -99,19 +100,19 @@ public class LongArrayListTest extends TestCase { // expected } } - + public void testGet() { - assertEquals(1, (long) TERTIARY_LIST.get(0)); - assertEquals(2, (long) TERTIARY_LIST.get(1)); - assertEquals(3, (long) TERTIARY_LIST.get(2)); - + assertEquals(1L, (long) TERTIARY_LIST.get(0)); + assertEquals(2L, (long) TERTIARY_LIST.get(1)); + assertEquals(3L, (long) TERTIARY_LIST.get(2)); + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -119,19 +120,19 @@ public class LongArrayListTest extends TestCase { // expected } } - + public void testGetLong() { - assertEquals(1, TERTIARY_LIST.getLong(0)); - assertEquals(2, TERTIARY_LIST.getLong(1)); - assertEquals(3, TERTIARY_LIST.getLong(2)); - + assertEquals(1L, TERTIARY_LIST.getLong(0)); + assertEquals(2L, TERTIARY_LIST.getLong(1)); + assertEquals(3L, TERTIARY_LIST.getLong(2)); + try { TERTIARY_LIST.get(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { TERTIARY_LIST.get(3); fail(); @@ -139,35 +140,35 @@ public class LongArrayListTest extends TestCase { // expected } } - + public void testSize() { assertEquals(0, LongArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); assertEquals(3, TERTIARY_LIST.size()); - list.addLong(2); + list.addLong(3); list.addLong(4); list.addLong(6); list.addLong(8); assertEquals(4, list.size()); - + list.remove(0); assertEquals(3, list.size()); - - list.add(16L); + + list.add(17L); assertEquals(4, list.size()); } - + public void testSet() { list.addLong(2); list.addLong(4); - - assertEquals(2, (long) list.set(0, 0L)); - assertEquals(0, list.getLong(0)); - assertEquals(4, (long) list.set(1, 0L)); - assertEquals(0, list.getLong(1)); - + assertEquals(2L, (long) list.set(0, 3L)); + assertEquals(3L, list.getLong(0)); + + assertEquals(4L, (long) list.set(1, 0L)); + assertEquals(0L, list.getLong(1)); + try { list.set(-1, 0L); fail(); @@ -182,17 +183,17 @@ public class LongArrayListTest extends TestCase { // expected } } - + public void testSetLong() { - list.addLong(2); - list.addLong(4); - - assertEquals(2, list.setLong(0, 0)); - assertEquals(0, list.getLong(0)); + list.addLong(1); + list.addLong(3); + + assertEquals(1L, list.setLong(0, 0)); + assertEquals(0L, list.getLong(0)); + + assertEquals(3L, list.setLong(1, 0)); + assertEquals(0L, list.getLong(1)); - assertEquals(4, list.setLong(1, 0)); - assertEquals(0, list.getLong(1)); - try { list.setLong(-1, 0); fail(); @@ -207,7 +208,7 @@ public class LongArrayListTest extends TestCase { // expected } } - + public void testAdd() { assertEquals(0, list.size()); @@ -217,28 +218,30 @@ public class LongArrayListTest extends TestCase { assertTrue(list.add(3L)); list.add(0, 4L); assertEquals(asList(4L, 2L, 3L), list); - + list.add(0, 1L); list.add(0, 0L); // Force a resize by getting up to 11 elements. for (int i = 0; i < 6; i++) { list.add(Long.valueOf(5 + i)); } - assertEquals(asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), list); - + assertEquals( + asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), + list); + try { list.add(-1, 5L); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.add(4, 5L); } catch (IndexOutOfBoundsException e) { // expected } } - + public void testAddLong() { assertEquals(0, list.size()); @@ -248,128 +251,128 @@ public class LongArrayListTest extends TestCase { list.addLong(3); assertEquals(asList(2L, 3L), list); } - + public void testAddAll() { assertEquals(0, list.size()); assertTrue(list.addAll(Collections.singleton(1L))); assertEquals(1, list.size()); - assertEquals(1, (long) list.get(0)); - assertEquals(1, list.getLong(0)); - + assertEquals(1L, (long) list.get(0)); + assertEquals(1L, list.getLong(0)); + assertTrue(list.addAll(asList(2L, 3L, 4L, 5L, 6L))); assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L), list); - + assertTrue(list.addAll(TERTIARY_LIST)); assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L), list); assertFalse(list.addAll(Collections.<Long>emptyList())); assertFalse(list.addAll(LongArrayList.emptyList())); } - + public void testRemove() { list.addAll(TERTIARY_LIST); - assertEquals(1, (long) list.remove(0)); + assertEquals(1L, (long) list.remove(0)); assertEquals(asList(2L, 3L), list); - assertTrue(list.remove(3L)); + assertTrue(list.remove(Long.valueOf(3))); assertEquals(asList(2L), list); - assertFalse(list.remove(3L)); + assertFalse(list.remove(Long.valueOf(3))); assertEquals(asList(2L), list); - assertEquals(2, (long) list.remove(0)); + assertEquals(2L, (long) list.remove(0)); assertEquals(asList(), list); - + try { list.remove(-1); fail(); } catch (IndexOutOfBoundsException e) { // expected } - + try { list.remove(0); } catch (IndexOutOfBoundsException e) { // expected } } - + private void assertImmutable(LongArrayList list) { if (list.contains(1L)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } - + try { list.add(1L); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.add(0, 1L); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.<Long>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.singletonList(1L)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(new LongArrayList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.singleton(1L)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.<Long>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addLong(0); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.clear(); fail(); @@ -383,63 +386,63 @@ public class LongArrayListTest extends TestCase { } catch (UnsupportedOperationException e) { // expected } - + try { list.remove(new Object()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.<Long>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.singleton(1L)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.<Long>emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.singleton(1L)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.set(0, 0L); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.setLong(0, 0); fail(); @@ -447,7 +450,7 @@ public class LongArrayListTest extends TestCase { // expected } } - + private static LongArrayList newImmutableLongArrayList(long... elements) { LongArrayList list = new LongArrayList(); for (long element : elements) { diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java index d79d0029..04d58006 100644 --- a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java @@ -30,12 +30,16 @@ package com.google.protobuf; +import map_lite_test.MapForProto2TestProto.BizarroTestMap; import map_lite_test.MapForProto2TestProto.TestMap; import map_lite_test.MapForProto2TestProto.TestMap.MessageValue; +import map_lite_test.MapForProto2TestProto.TestMapOrBuilder; import map_lite_test.MapForProto2TestProto.TestUnknownEnumValue; import junit.framework.TestCase; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -44,34 +48,40 @@ import java.util.Map; /** * Unit tests for map fields. */ -public class MapForProto2LiteTest extends TestCase { +public final class MapForProto2LiteTest extends TestCase { + private void setMapValues(TestMap.Builder builder) { - builder.getMutableInt32ToInt32Field().put(1, 11); - builder.getMutableInt32ToInt32Field().put(2, 22); - builder.getMutableInt32ToInt32Field().put(3, 33); - - builder.getMutableInt32ToStringField().put(1, "11"); - builder.getMutableInt32ToStringField().put(2, "22"); - builder.getMutableInt32ToStringField().put(3, "33"); - - builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11")); - builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22")); - builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33")); - - builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO); - builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR); - builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ); - - builder.getMutableInt32ToMessageField().put( - 1, MessageValue.newBuilder().setValue(11).build()); - builder.getMutableInt32ToMessageField().put( - 2, MessageValue.newBuilder().setValue(22).build()); - builder.getMutableInt32ToMessageField().put( - 3, MessageValue.newBuilder().setValue(33).build()); - - builder.getMutableStringToInt32Field().put("1", 11); - builder.getMutableStringToInt32Field().put("2", 22); - builder.getMutableStringToInt32Field().put("3", 33); + builder + .putInt32ToInt32Field(1, 11) + .putInt32ToInt32Field(2, 22) + .putInt32ToInt32Field(3, 33) + + .putInt32ToStringField(1, "11") + .putInt32ToStringField(2, "22") + .putInt32ToStringField(3, "33") + + .putInt32ToBytesField(1, TestUtil.toBytes("11")) + .putInt32ToBytesField(2, TestUtil.toBytes("22")) + .putInt32ToBytesField(3, TestUtil.toBytes("33")) + + .putInt32ToEnumField(1, TestMap.EnumValue.FOO) + .putInt32ToEnumField(2, TestMap.EnumValue.BAR) + .putInt32ToEnumField(3, TestMap.EnumValue.BAZ) + + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build()) + .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build()) + .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build()) + + .putStringToInt32Field("1", 11) + .putStringToInt32Field("2", 22) + .putStringToInt32Field("3", 33); + } + + public void testSetMapValues() { + TestMap.Builder mapBuilder = TestMap.newBuilder(); + setMapValues(mapBuilder); + TestMap map = mapBuilder.build(); + assertMapValuesSet(map); } private void copyMapValues(TestMap source, TestMap.Builder destination) { @@ -94,22 +104,22 @@ public class MapForProto2LiteTest extends TestCase { assertEquals("11", message.getInt32ToStringField().get(1)); assertEquals("22", message.getInt32ToStringField().get(2)); assertEquals("33", message.getInt32ToStringField().get(3)); - + assertEquals(3, message.getInt32ToBytesField().size()); assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1)); assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2)); assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - + assertEquals(3, message.getInt32ToEnumField().size()); assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1)); assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2)); assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - + assertEquals(3, message.getInt32ToMessageField().size()); assertEquals(11, message.getInt32ToMessageField().get(1).getValue()); assertEquals(22, message.getInt32ToMessageField().get(2).getValue()); assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - + assertEquals(3, message.getStringToInt32Field().size()); assertEquals(11, message.getStringToInt32Field().get("1").intValue()); assertEquals(22, message.getStringToInt32Field().get("2").intValue()); @@ -117,31 +127,42 @@ public class MapForProto2LiteTest extends TestCase { } private void updateMapValues(TestMap.Builder builder) { - builder.getMutableInt32ToInt32Field().put(1, 111); - builder.getMutableInt32ToInt32Field().remove(2); - builder.getMutableInt32ToInt32Field().put(4, 44); - - builder.getMutableInt32ToStringField().put(1, "111"); - builder.getMutableInt32ToStringField().remove(2); - builder.getMutableInt32ToStringField().put(4, "44"); - - builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111")); - builder.getMutableInt32ToBytesField().remove(2); - builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44")); - - builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR); - builder.getMutableInt32ToEnumField().remove(2); - builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX); - - builder.getMutableInt32ToMessageField().put( - 1, MessageValue.newBuilder().setValue(111).build()); - builder.getMutableInt32ToMessageField().remove(2); - builder.getMutableInt32ToMessageField().put( - 4, MessageValue.newBuilder().setValue(44).build()); - - builder.getMutableStringToInt32Field().put("1", 111); - builder.getMutableStringToInt32Field().remove("2"); - builder.getMutableStringToInt32Field().put("4", 44); + builder + .putInt32ToInt32Field(1, 111) + .removeInt32ToInt32Field(2) + .putInt32ToInt32Field(4, 44) + + .putInt32ToStringField(1, "111") + .removeInt32ToStringField(2) + .putInt32ToStringField(4, "44") + + .putInt32ToBytesField(1, TestUtil.toBytes("111")) + .removeInt32ToBytesField(2) + .putInt32ToBytesField(4, TestUtil.toBytes("44")) + + .putInt32ToEnumField(1, TestMap.EnumValue.BAR) + .removeInt32ToEnumField(2) + .putInt32ToEnumField(4, TestMap.EnumValue.QUX) + + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build()) + .removeInt32ToMessageField(2) + .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build()) + + .putStringToInt32Field("1", 111) + .removeStringToInt32Field("2") + .putStringToInt32Field("4", 44); + } + + public void testUpdateMapValues() { + TestMap.Builder mapBuilder = TestMap.newBuilder(); + setMapValues(mapBuilder); + TestMap map = mapBuilder.build(); + assertMapValuesSet(map); + + mapBuilder = map.toBuilder(); + updateMapValues(mapBuilder); + map = mapBuilder.build(); + assertMapValuesUpdated(map); } private void assertMapValuesUpdated(TestMap message) { @@ -154,188 +175,149 @@ public class MapForProto2LiteTest extends TestCase { assertEquals("111", message.getInt32ToStringField().get(1)); assertEquals("33", message.getInt32ToStringField().get(3)); assertEquals("44", message.getInt32ToStringField().get(4)); - + assertEquals(3, message.getInt32ToBytesField().size()); assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); - + assertEquals(3, message.getInt32ToEnumField().size()); assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); - + assertEquals(3, message.getInt32ToMessageField().size()); assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); - + assertEquals(3, message.getStringToInt32Field().size()); assertEquals(111, message.getStringToInt32Field().get("1").intValue()); assertEquals(33, message.getStringToInt32Field().get("3").intValue()); assertEquals(44, message.getStringToInt32Field().get("4").intValue()); } - private void assertMapValuesCleared(TestMap message) { - assertEquals(0, message.getInt32ToInt32Field().size()); - assertEquals(0, message.getInt32ToStringField().size()); - assertEquals(0, message.getInt32ToBytesField().size()); - assertEquals(0, message.getInt32ToEnumField().size()); - assertEquals(0, message.getInt32ToMessageField().size()); - assertEquals(0, message.getStringToInt32Field().size()); + private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { + assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToStringField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount()); + assertEquals(0, testMapOrBuilder.getStringToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount()); } public void testSanityCopyOnWrite() throws InvalidProtocolBufferException { // Since builders are implemented as a thin wrapper around a message // instance, we attempt to verify that we can't cause the builder to modify // a produced message. - + TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); - Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field(); - intMap.put(1, 2); + builder.putInt32ToInt32Field(1, 2); assertTrue(message.getInt32ToInt32Field().isEmpty()); message = builder.build(); - try { - intMap.put(2, 3); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); - builder.getMutableInt32ToInt32Field().put(2, 3); + builder.putInt32ToInt32Field(2, 3); assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); } - - public void testMutableMapLifecycle() { + + public void testGetMapIsImmutable() { TestMap.Builder builder = TestMap.newBuilder(); - Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field(); - intMap.put(1, 2); - assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + assertMapsAreImmutable(builder); + assertMapsAreImmutable(builder.build()); + + setMapValues(builder); + assertMapsAreImmutable(builder); + assertMapsAreImmutable(builder.build()); + } + + private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) { + assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2); + assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2"); + assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2")); + assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO); + assertImmutable( + testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance()); + assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2); + } + + private <K, V> void assertImmutable(Map<K, V> map, K key, V value) { try { - intMap.put(2, 3); + map.put(key, value); fail(); } catch (UnsupportedOperationException e) { // expected } + if (!map.isEmpty()) { + try { + map.entrySet().remove(map.entrySet().iterator().next()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + } + + public void testMutableMapLifecycle() { + TestMap.Builder builder = TestMap.newBuilder() + .putInt32ToInt32Field(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); - builder.getMutableInt32ToInt32Field().put(2, 3); + builder.putInt32ToInt32Field(2, 3); assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); - Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField(); - enumMap.put(1, TestMap.EnumValue.BAR); + builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR); assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); - try { - enumMap.put(2, TestMap.EnumValue.FOO); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField()); - builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO); + builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO); assertEquals( newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), builder.getInt32ToEnumField()); - - Map<Integer, String> stringMap = builder.getMutableInt32ToStringField(); - stringMap.put(1, "1"); + + builder.putInt32ToStringField(1, "1"); assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); - try { - stringMap.put(2, "2"); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } assertEquals(newMap(1, "1"), builder.getInt32ToStringField()); - builder.getMutableInt32ToStringField().put(2, "2"); - assertEquals( - newMap(1, "1", 2, "2"), - builder.getInt32ToStringField()); - - Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField(); - messageMap.put(1, TestMap.MessageValue.getDefaultInstance()); + builder.putInt32ToStringField(2, "2"); + assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringField()); + + builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance()); assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.build().getInt32ToMessageField()); - try { - messageMap.put(2, TestMap.MessageValue.getDefaultInstance()); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageField()); - builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance()); + builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance()); assertEquals( newMap(1, TestMap.MessageValue.getDefaultInstance(), 2, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageField()); } - public void testMutableMapLifecycle_collections() { - TestMap.Builder builder = TestMap.newBuilder(); - Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field(); - intMap.put(1, 2); - assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); - try { - intMap.remove(2); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } - try { - intMap.entrySet().remove(new Object()); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } - try { - intMap.entrySet().iterator().remove(); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } - try { - intMap.keySet().remove(new Object()); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } - try { - intMap.values().remove(new Object()); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } - try { - intMap.values().iterator().remove(); - fail(); - } catch (UnsupportedOperationException e) { - // expected - } - assertEquals(newMap(1, 2), intMap); - assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); - assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); - } - public void testGettersAndSetters() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); assertMapValuesCleared(message); - + builder = message.toBuilder(); setMapValues(builder); message = builder.build(); assertMapValuesSet(message); - + builder = message.toBuilder(); updateMapValues(builder); message = builder.build(); assertMapValuesUpdated(message); - + builder = message.toBuilder(); builder.clear(); + assertMapValuesCleared(builder); message = builder.build(); assertMapValuesCleared(message); } @@ -344,12 +326,52 @@ public class MapForProto2LiteTest extends TestCase { TestMap.Builder sourceBuilder = TestMap.newBuilder(); setMapValues(sourceBuilder); TestMap source = sourceBuilder.build(); + assertMapValuesSet(source); TestMap.Builder destination = TestMap.newBuilder(); copyMapValues(source, destination); assertMapValuesSet(destination.build()); } + public void testPutChecksNullKeysAndValues() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + + try { + builder.putInt32ToStringField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToBytesField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToEnumField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToMessageField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putStringToInt32Field(null, 1); + fail(); + } catch (NullPointerException e) { + // expected. + } + } + public void testSerializeAndParse() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); setMapValues(builder); @@ -357,14 +379,14 @@ public class MapForProto2LiteTest extends TestCase { assertEquals(message.getSerializedSize(), message.toByteString().size()); message = TestMap.parser().parseFrom(message.toByteString()); assertMapValuesSet(message); - + builder = message.toBuilder(); updateMapValues(builder); message = builder.build(); assertEquals(message.getSerializedSize(), message.toByteString().size()); message = TestMap.parser().parseFrom(message.toByteString()); assertMapValuesUpdated(message); - + builder = message.toBuilder(); builder.clear(); message = builder.build(); @@ -372,12 +394,61 @@ public class MapForProto2LiteTest extends TestCase { message = TestMap.parser().parseFrom(message.toByteString()); assertMapValuesCleared(message); } - + + private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream); + bizarroMap.writeTo(output); + output.flush(); + return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray())); + } + + public void testParseError() throws Exception { + ByteString bytes = TestUtil.toBytes("SOME BYTES"); + String stringKey = "a string key"; + + TestMap map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToInt32Field(5, bytes) + .build()); + assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToStringField(stringKey, 5) + .build()); + assertEquals(map.getInt32ToStringFieldOrDefault(0, null), ""); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToBytesField(stringKey, 5) + .build()); + assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToEnumField(stringKey, bytes) + .build()); + assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO); + + try { + tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToMessageField(stringKey, bytes) + .build()); + fail(); + } catch (InvalidProtocolBufferException expected) { + assertTrue(expected.getUnfinishedMessage() instanceof TestMap); + map = (TestMap) expected.getUnfinishedMessage(); + assertTrue(map.getInt32ToMessageField().isEmpty()); + } + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putStringToInt32Field(stringKey, bytes) + .build()); + assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0); + } + public void testMergeFrom() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); setMapValues(builder); TestMap message = builder.build(); - + TestMap.Builder other = TestMap.newBuilder(); other.mergeFrom(message); assertMapValuesSet(other.build()); @@ -386,26 +457,26 @@ public class MapForProto2LiteTest extends TestCase { public void testEqualsAndHashCode() throws Exception { // Test that generated equals() and hashCode() will disregard the order // of map entries when comparing/hashing map fields. - + // We can't control the order of elements in a HashMap. The best we can do // here is to add elements in different order. - TestMap.Builder b1 = TestMap.newBuilder(); - b1.getMutableInt32ToInt32Field().put(1, 2); - b1.getMutableInt32ToInt32Field().put(3, 4); - b1.getMutableInt32ToInt32Field().put(5, 6); + TestMap.Builder b1 = TestMap.newBuilder() + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4) + .putInt32ToInt32Field(5, 6); TestMap m1 = b1.build(); - - TestMap.Builder b2 = TestMap.newBuilder(); - b2.getMutableInt32ToInt32Field().put(5, 6); - b2.getMutableInt32ToInt32Field().put(1, 2); - b2.getMutableInt32ToInt32Field().put(3, 4); + + TestMap.Builder b2 = TestMap.newBuilder() + .putInt32ToInt32Field(5, 6) + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4); TestMap m2 = b2.build(); - + assertEquals(m1, m2); assertEquals(m1.hashCode(), m2.hashCode()); - + // Make sure we did compare map fields. - b2.getMutableInt32ToInt32Field().put(1, 0); + b2.putInt32ToInt32Field(1, 0); m2 = b2.build(); assertFalse(m1.equals(m2)); // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed @@ -413,10 +484,9 @@ public class MapForProto2LiteTest extends TestCase { } public void testUnknownEnumValues() throws Exception { - TestUnknownEnumValue.Builder builder = - TestUnknownEnumValue.newBuilder(); - builder.getMutableInt32ToInt32Field().put(1, 1); - builder.getMutableInt32ToInt32Field().put(2, 54321); + TestUnknownEnumValue.Builder builder = TestUnknownEnumValue.newBuilder() + .putInt32ToInt32Field(1, 1) + .putInt32ToInt32Field(2, 54321); ByteString data = builder.build().toByteString(); TestMap message = TestMap.parseFrom(data); @@ -442,17 +512,288 @@ public class MapForProto2LiteTest extends TestCase { assertEquals(Arrays.asList("1", "2", "3"), new ArrayList<String>(message.getStringToInt32Field().keySet())); } - + private static <K, V> Map<K, V> newMap(K key1, V value1) { Map<K, V> map = new HashMap<K, V>(); map.put(key1, value1); return map; } - + private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) { Map<K, V> map = new HashMap<K, V>(); map.put(key1, value1); map.put(key2, value2); return map; } + + public void testGetMap() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + TestMap message = builder.build(); + assertEquals( + message.getStringToInt32Field(), + message.getStringToInt32FieldMap()); + assertEquals( + message.getInt32ToBytesField(), + message.getInt32ToBytesFieldMap()); + assertEquals( + message.getInt32ToEnumField(), + message.getInt32ToEnumFieldMap()); + assertEquals( + message.getInt32ToMessageField(), + message.getInt32ToMessageFieldMap()); + } + + public void testContains() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + assertMapContainsSetValues(builder); + assertMapContainsSetValues(builder.build()); + } + + private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) { + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1)); + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2)); + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3)); + assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToStringField(1)); + assertTrue(testMapOrBuilder.containsInt32ToStringField(2)); + assertTrue(testMapOrBuilder.containsInt32ToStringField(3)); + assertFalse(testMapOrBuilder.containsInt32ToStringField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToBytesField(1)); + assertTrue(testMapOrBuilder.containsInt32ToBytesField(2)); + assertTrue(testMapOrBuilder.containsInt32ToBytesField(3)); + assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToEnumField(1)); + assertTrue(testMapOrBuilder.containsInt32ToEnumField(2)); + assertTrue(testMapOrBuilder.containsInt32ToEnumField(3)); + assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToMessageField(1)); + assertTrue(testMapOrBuilder.containsInt32ToMessageField(2)); + assertTrue(testMapOrBuilder.containsInt32ToMessageField(3)); + assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1)); + + assertTrue(testMapOrBuilder.containsStringToInt32Field("1")); + assertTrue(testMapOrBuilder.containsStringToInt32Field("2")); + assertTrue(testMapOrBuilder.containsStringToInt32Field("3")); + assertFalse(testMapOrBuilder.containsStringToInt32Field("-1")); + } + + public void testCount() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + + setMapValues(builder); + assertMapCounts(3, builder); + + TestMap message = builder.build(); + assertMapCounts(3, message); + + builder = message.toBuilder().putInt32ToInt32Field(4, 44); + assertEquals(4, builder.getInt32ToInt32FieldCount()); + assertEquals(4, builder.build().getInt32ToInt32FieldCount()); + + // already present - should be unchanged + builder.putInt32ToInt32Field(4, 44); + assertEquals(4, builder.getInt32ToInt32FieldCount()); + } + + private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) { + assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount()); + } + + public void testGetOrDefault() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + setMapValues(builder); + doTestGetOrDefault(builder); + doTestGetOrDefault(builder.build()); + } + + public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) { + assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11)); + assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11)); + + assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11")); + assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null)); + + assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null)); + + assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null)); + + assertEquals(MessageValue.newBuilder().setValue(11).build(), + testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null)); + + assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11)); + assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11)); + + try { + testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + public void testGetOrThrow() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + setMapValues(builder); + doTestGetOrDefault(builder); + doTestGetOrDefault(builder.build()); + } + + public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) { + assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1)); + + try { + testMapOrBuilder.getInt32ToStringFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1)); + + try { + testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(MessageValue.newBuilder().setValue(11).build(), + testMapOrBuilder.getInt32ToMessageFieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1")); + try { + testMapOrBuilder.getStringToInt32FieldOrThrow("-1"); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + try { + testMapOrBuilder.getStringToInt32FieldOrThrow(null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + public void testPut() { + TestMap.Builder builder = TestMap.newBuilder(); + builder.putInt32ToInt32Field(1, 11); + assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); + + builder.putInt32ToStringField(1, "a"); + assertEquals("a", builder.getInt32ToStringFieldOrThrow(1)); + try { + builder.putInt32ToStringField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToBytesField(1, TestUtil.toBytes("11")); + assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1)); + try { + builder.putInt32ToBytesField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO); + assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1)); + try { + builder.putInt32ToEnumField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putStringToInt32Field("a", 1); + assertEquals(1, builder.getStringToInt32FieldOrThrow("a")); + try { + builder.putStringToInt32Field(null, -1); + } catch (NullPointerException e) { + // expected + } + } + + public void testRemove() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToInt32Field(1); + assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1)); + } + + assertEquals("11", builder.getInt32ToStringFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToStringField(1); + assertNull(builder.getInt32ToStringFieldOrDefault(1, null)); + } + + assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToBytesField(1); + assertNull(builder.getInt32ToBytesFieldOrDefault(1, null)); + } + + assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToEnumField(1); + assertNull(builder.getInt32ToEnumFieldOrDefault(1, null)); + } + + assertEquals(11, builder.getStringToInt32FieldOrThrow("1")); + for (int times = 0; times < 2; times++) { + builder.removeStringToInt32Field("1"); + assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1)); + } + + try { + builder.removeStringToInt32Field(null); + fail(); + } catch (NullPointerException e) { + // expected + } + } } diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java index 73154c0f..e8246bf6 100644 --- a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java +++ b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java @@ -31,13 +31,17 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.FieldDescriptor; +import map_test.MapForProto2TestProto.BizarroTestMap; import map_test.MapForProto2TestProto.TestMap; import map_test.MapForProto2TestProto.TestMap.MessageValue; import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields; +import map_test.MapForProto2TestProto.TestMapOrBuilder; import map_test.MapForProto2TestProto.TestRecursiveMap; import map_test.MapForProto2TestProto.TestUnknownEnumValue; import junit.framework.TestCase; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -48,7 +52,8 @@ import java.util.Map; * Unit tests for map fields in proto2 protos. */ public class MapForProto2Test extends TestCase { - private void setMapValues(TestMap.Builder builder) { + + private void setMapValuesUsingMutableMap(TestMap.Builder builder) { builder.getMutableInt32ToInt32Field().put(1, 11); builder.getMutableInt32ToInt32Field().put(2, 22); builder.getMutableInt32ToInt32Field().put(3, 33); @@ -56,27 +61,67 @@ public class MapForProto2Test extends TestCase { builder.getMutableInt32ToStringField().put(1, "11"); builder.getMutableInt32ToStringField().put(2, "22"); builder.getMutableInt32ToStringField().put(3, "33"); - + builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11")); builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22")); builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33")); - + builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO); builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR); builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ); - + builder.getMutableInt32ToMessageField().put( 1, MessageValue.newBuilder().setValue(11).build()); builder.getMutableInt32ToMessageField().put( 2, MessageValue.newBuilder().setValue(22).build()); builder.getMutableInt32ToMessageField().put( 3, MessageValue.newBuilder().setValue(33).build()); - + builder.getMutableStringToInt32Field().put("1", 11); builder.getMutableStringToInt32Field().put("2", 22); builder.getMutableStringToInt32Field().put("3", 33); } + private void setMapValuesUsingAccessors(TestMap.Builder builder) { + builder + .putInt32ToInt32Field(1, 11) + .putInt32ToInt32Field(2, 22) + .putInt32ToInt32Field(3, 33) + + .putInt32ToStringField(1, "11") + .putInt32ToStringField(2, "22") + .putInt32ToStringField(3, "33") + + .putInt32ToBytesField(1, TestUtil.toBytes("11")) + .putInt32ToBytesField(2, TestUtil.toBytes("22")) + .putInt32ToBytesField(3, TestUtil.toBytes("33")) + + .putInt32ToEnumField(1, TestMap.EnumValue.FOO) + .putInt32ToEnumField(2, TestMap.EnumValue.BAR) + .putInt32ToEnumField(3, TestMap.EnumValue.BAZ) + + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build()) + .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build()) + .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build()) + + .putStringToInt32Field("1", 11) + .putStringToInt32Field("2", 22) + .putStringToInt32Field("3", 33); + } + + public void testSetMapValues() { + TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(usingMutableMapBuilder); + TestMap usingMutableMap = usingMutableMapBuilder.build(); + assertMapValuesSet(usingMutableMap); + + TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder(); + setMapValuesUsingAccessors(usingAccessorsBuilder); + TestMap usingAccessors = usingAccessorsBuilder.build(); + assertMapValuesSet(usingAccessors); + assertEquals(usingAccessors, usingMutableMap); + } + private void copyMapValues(TestMap source, TestMap.Builder destination) { destination .putAllInt32ToInt32Field(source.getInt32ToInt32Field()) @@ -87,7 +132,7 @@ public class MapForProto2Test extends TestCase { .putAllStringToInt32Field(source.getStringToInt32Field()); } - private void assertMapValuesSet(TestMap message) { + private void assertMapValuesSet(TestMapOrBuilder message) { assertEquals(3, message.getInt32ToInt32Field().size()); assertEquals(11, message.getInt32ToInt32Field().get(1).intValue()); assertEquals(22, message.getInt32ToInt32Field().get(2).intValue()); @@ -97,29 +142,29 @@ public class MapForProto2Test extends TestCase { assertEquals("11", message.getInt32ToStringField().get(1)); assertEquals("22", message.getInt32ToStringField().get(2)); assertEquals("33", message.getInt32ToStringField().get(3)); - + assertEquals(3, message.getInt32ToBytesField().size()); assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1)); assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2)); assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - + assertEquals(3, message.getInt32ToEnumField().size()); assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1)); assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2)); assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - + assertEquals(3, message.getInt32ToMessageField().size()); assertEquals(11, message.getInt32ToMessageField().get(1).getValue()); assertEquals(22, message.getInt32ToMessageField().get(2).getValue()); assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - + assertEquals(3, message.getStringToInt32Field().size()); assertEquals(11, message.getStringToInt32Field().get("1").intValue()); assertEquals(22, message.getStringToInt32Field().get("2").intValue()); assertEquals(33, message.getStringToInt32Field().get("3").intValue()); } - private void updateMapValues(TestMap.Builder builder) { + private void updateMapValuesUsingMutableMap(TestMap.Builder builder) { builder.getMutableInt32ToInt32Field().put(1, 111); builder.getMutableInt32ToInt32Field().remove(2); builder.getMutableInt32ToInt32Field().put(4, 44); @@ -127,26 +172,78 @@ public class MapForProto2Test extends TestCase { builder.getMutableInt32ToStringField().put(1, "111"); builder.getMutableInt32ToStringField().remove(2); builder.getMutableInt32ToStringField().put(4, "44"); - + builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111")); builder.getMutableInt32ToBytesField().remove(2); builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44")); - + builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR); builder.getMutableInt32ToEnumField().remove(2); builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX); - + builder.getMutableInt32ToMessageField().put( 1, MessageValue.newBuilder().setValue(111).build()); builder.getMutableInt32ToMessageField().remove(2); builder.getMutableInt32ToMessageField().put( 4, MessageValue.newBuilder().setValue(44).build()); - + builder.getMutableStringToInt32Field().put("1", 111); builder.getMutableStringToInt32Field().remove("2"); builder.getMutableStringToInt32Field().put("4", 44); } + private void updateMapValuesUsingAccessors(TestMap.Builder builder) { + builder + .putInt32ToInt32Field(1, 111) + .removeInt32ToInt32Field(2) + .putInt32ToInt32Field(4, 44) + + .putInt32ToStringField(1, "111") + .removeInt32ToStringField(2) + .putInt32ToStringField(4, "44") + + .putInt32ToBytesField(1, TestUtil.toBytes("111")) + .removeInt32ToBytesField(2) + .putInt32ToBytesField(4, TestUtil.toBytes("44")) + + .putInt32ToEnumField(1, TestMap.EnumValue.BAR) + .removeInt32ToEnumField(2) + .putInt32ToEnumField(4, TestMap.EnumValue.QUX) + + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build()) + .removeInt32ToMessageField(2) + .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build()) + + .putStringToInt32Field("1", 111) + .removeStringToInt32Field("2") + .putStringToInt32Field("4", 44); + } + + public void testUpdateMapValues() { + TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(usingMutableMapBuilder); + TestMap usingMutableMap = usingMutableMapBuilder.build(); + assertMapValuesSet(usingMutableMap); + + TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder(); + setMapValuesUsingAccessors(usingAccessorsBuilder); + TestMap usingAccessors = usingAccessorsBuilder.build(); + assertMapValuesSet(usingAccessors); + assertEquals(usingAccessors, usingMutableMap); + + usingMutableMapBuilder = usingMutableMap.toBuilder(); + updateMapValuesUsingMutableMap(usingMutableMapBuilder); + usingMutableMap = usingMutableMapBuilder.build(); + assertMapValuesUpdated(usingMutableMap); + + usingAccessorsBuilder = usingAccessors.toBuilder(); + updateMapValuesUsingAccessors(usingAccessorsBuilder); + usingAccessors = usingAccessorsBuilder.build(); + assertMapValuesUpdated(usingAccessors); + + assertEquals(usingAccessors, usingMutableMap); + } + private void assertMapValuesUpdated(TestMap message) { assertEquals(3, message.getInt32ToInt32Field().size()); assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); @@ -157,37 +254,72 @@ public class MapForProto2Test extends TestCase { assertEquals("111", message.getInt32ToStringField().get(1)); assertEquals("33", message.getInt32ToStringField().get(3)); assertEquals("44", message.getInt32ToStringField().get(4)); - + assertEquals(3, message.getInt32ToBytesField().size()); assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); - + assertEquals(3, message.getInt32ToEnumField().size()); assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); - + assertEquals(3, message.getInt32ToMessageField().size()); assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); - + assertEquals(3, message.getStringToInt32Field().size()); assertEquals(111, message.getStringToInt32Field().get("1").intValue()); assertEquals(33, message.getStringToInt32Field().get("3").intValue()); assertEquals(44, message.getStringToInt32Field().get("4").intValue()); } - private void assertMapValuesCleared(TestMap message) { - assertEquals(0, message.getInt32ToInt32Field().size()); - assertEquals(0, message.getInt32ToStringField().size()); - assertEquals(0, message.getInt32ToBytesField().size()); - assertEquals(0, message.getInt32ToEnumField().size()); - assertEquals(0, message.getInt32ToMessageField().size()); - assertEquals(0, message.getStringToInt32Field().size()); + private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { + assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToStringField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount()); + assertEquals(0, testMapOrBuilder.getStringToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount()); + } + + public void testGetMapIsImmutable() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapsAreImmutable(builder); + assertMapsAreImmutable(builder.build()); + + setMapValuesUsingAccessors(builder); + assertMapsAreImmutable(builder); + assertMapsAreImmutable(builder.build()); + } + + private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) { + assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2); + assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2"); + assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2")); + assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO); + assertImmutable( + testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance()); + assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2); + } + + private <K, V> void assertImmutable(Map<K, V> map, K key, V value) { + try { + map.put(key, value); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } } - + public void testMutableMapLifecycle() { TestMap.Builder builder = TestMap.newBuilder(); Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field(); @@ -217,7 +349,7 @@ public class MapForProto2Test extends TestCase { assertEquals( newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), builder.getInt32ToEnumField()); - + Map<Integer, String> stringMap = builder.getMutableInt32ToStringField(); stringMap.put(1, "1"); assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); @@ -232,7 +364,7 @@ public class MapForProto2Test extends TestCase { assertEquals( newMap(1, "1", 2, "2"), builder.getInt32ToStringField()); - + Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField(); messageMap.put(1, TestMap.MessageValue.getDefaultInstance()); assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), @@ -302,48 +434,91 @@ public class MapForProto2Test extends TestCase { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); assertMapValuesCleared(message); - + builder = message.toBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); message = builder.build(); assertMapValuesSet(message); - + builder = message.toBuilder(); - updateMapValues(builder); + updateMapValuesUsingMutableMap(builder); message = builder.build(); assertMapValuesUpdated(message); - + builder = message.toBuilder(); builder.clear(); + assertMapValuesCleared(builder); message = builder.build(); assertMapValuesCleared(message); } public void testPutAll() throws Exception { TestMap.Builder sourceBuilder = TestMap.newBuilder(); - setMapValues(sourceBuilder); + setMapValuesUsingMutableMap(sourceBuilder); TestMap source = sourceBuilder.build(); + assertMapValuesSet(source); TestMap.Builder destination = TestMap.newBuilder(); copyMapValues(source, destination); assertMapValuesSet(destination.build()); + + assertEquals(3, destination.getInt32ToEnumFieldCount()); + } + + public void testPutChecksNullKeysAndValues() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + + try { + builder.putInt32ToStringField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToBytesField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToEnumField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToMessageField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putStringToInt32Field(null, 1); + fail(); + } catch (NullPointerException e) { + // expected. + } } public void testSerializeAndParse() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); assertEquals(message.getSerializedSize(), message.toByteString().size()); message = TestMap.parser().parseFrom(message.toByteString()); assertMapValuesSet(message); - + builder = message.toBuilder(); - updateMapValues(builder); + updateMapValuesUsingMutableMap(builder); message = builder.build(); assertEquals(message.getSerializedSize(), message.toByteString().size()); message = TestMap.parser().parseFrom(message.toByteString()); assertMapValuesUpdated(message); - + builder = message.toBuilder(); builder.clear(); message = builder.build(); @@ -351,12 +526,61 @@ public class MapForProto2Test extends TestCase { message = TestMap.parser().parseFrom(message.toByteString()); assertMapValuesCleared(message); } - + + private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream); + bizarroMap.writeTo(output); + output.flush(); + return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray())); + } + + public void testParseError() throws Exception { + ByteString bytes = TestUtil.toBytes("SOME BYTES"); + String stringKey = "a string key"; + + TestMap map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToInt32Field(5, bytes) + .build()); + assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToStringField(stringKey, 5) + .build()); + assertEquals(map.getInt32ToStringFieldOrDefault(0, null), ""); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToBytesField(stringKey, 5) + .build()); + assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToEnumField(stringKey, bytes) + .build()); + assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO); + + try { + tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToMessageField(stringKey, bytes) + .build()); + fail(); + } catch (InvalidProtocolBufferException expected) { + assertTrue(expected.getUnfinishedMessage() instanceof TestMap); + map = (TestMap) expected.getUnfinishedMessage(); + assertTrue(map.getInt32ToMessageField().isEmpty()); + } + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putStringToInt32Field(stringKey, bytes) + .build()); + assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0); + } + public void testMergeFrom() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); - + TestMap.Builder other = TestMap.newBuilder(); other.mergeFrom(message); assertMapValuesSet(other.build()); @@ -365,7 +589,7 @@ public class MapForProto2Test extends TestCase { public void testEqualsAndHashCode() throws Exception { // Test that generated equals() and hashCode() will disregard the order // of map entries when comparing/hashing map fields. - + // We can't control the order of elements in a HashMap. The best we can do // here is to add elements in different order. TestMap.Builder b1 = TestMap.newBuilder(); @@ -373,16 +597,16 @@ public class MapForProto2Test extends TestCase { b1.getMutableInt32ToInt32Field().put(3, 4); b1.getMutableInt32ToInt32Field().put(5, 6); TestMap m1 = b1.build(); - + TestMap.Builder b2 = TestMap.newBuilder(); b2.getMutableInt32ToInt32Field().put(5, 6); b2.getMutableInt32ToInt32Field().put(1, 2); b2.getMutableInt32ToInt32Field().put(3, 4); TestMap m2 = b2.build(); - + assertEquals(m1, m2); assertEquals(m1.hashCode(), m2.hashCode()); - + // Make sure we did compare map fields. b2.getMutableInt32ToInt32Field().put(1, 0); m2 = b2.build(); @@ -390,26 +614,26 @@ public class MapForProto2Test extends TestCase { // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed // to be different. } - - + + // The following methods are used to test reflection API. - + private static FieldDescriptor f(String name) { return TestMap.getDescriptor().findFieldByName(name); } - + private static Object getFieldValue(Message mapEntry, String name) { FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name); return mapEntry.getField(field); } - + private static Message.Builder setFieldValue( Message.Builder mapEntry, String name, Object value) { FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name); mapEntry.setField(field, value); return mapEntry; } - + private static void assertHasMapValues(Message message, String name, Map<?, ?> values) { FieldDescriptor field = f(name); for (Object entry : (List<?>) message.getField(field)) { @@ -428,7 +652,7 @@ public class MapForProto2Test extends TestCase { assertEquals(value, values.get(key)); } } - + private static <KeyType, ValueType> Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) { FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name); @@ -439,7 +663,7 @@ public class MapForProto2Test extends TestCase { entryBuilder.setField(valueField, value); return entryBuilder.build(); } - + private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) { List<Message> entryList = new ArrayList<Message>(); for (Map.Entry<?, ?> entry : values.entrySet()) { @@ -448,9 +672,8 @@ public class MapForProto2Test extends TestCase { FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name); builder.setField(field, entryList); } - - private static <KeyType, ValueType> - Map<KeyType, ValueType> mapForValues( + + private static <KeyType, ValueType> Map<KeyType, ValueType> mapForValues( KeyType key1, ValueType value1, KeyType key2, ValueType value2) { Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>(); map.put(key1, value1); @@ -476,14 +699,14 @@ public class MapForProto2Test extends TestCase { mapForValues( 11, MessageValue.newBuilder().setValue(22).build(), 33, MessageValue.newBuilder().setValue(44).build())); - + // Test clearField() builder.clearField(f("int32_to_int32_field")); builder.clearField(f("int32_to_message_field")); message = builder.build(); assertEquals(0, message.getInt32ToInt32Field().size()); assertEquals(0, message.getInt32ToMessageField().size()); - + // Test setField() setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44)); @@ -496,7 +719,7 @@ public class MapForProto2Test extends TestCase { assertEquals(44, message.getInt32ToInt32Field().get(33).intValue()); assertEquals(222, message.getInt32ToMessageField().get(111).getValue()); assertEquals(444, message.getInt32ToMessageField().get(333).getValue()); - + // Test addRepeatedField builder.addRepeatedField(f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 66)); @@ -516,7 +739,7 @@ public class MapForProto2Test extends TestCase { message = builder.build(); assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); assertEquals(555, message.getInt32ToMessageField().get(555).getValue()); - + // Test setRepeatedField for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) { Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i); @@ -533,35 +756,35 @@ public class MapForProto2Test extends TestCase { assertEquals(33, message.getInt32ToInt32Field().get(44).intValue()); assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); } - + public void testTextFormat() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); - + String textData = TextFormat.printToString(message); - + builder = TestMap.newBuilder(); TextFormat.merge(textData, builder); message = builder.build(); - + assertMapValuesSet(message); } - + public void testDynamicMessage() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); - + Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); Message dynamicMessage = dynamicDefaultInstance .newBuilderForType().mergeFrom(message.toByteString()).build(); - + assertEquals(message, dynamicMessage); assertEquals(message.hashCode(), dynamicMessage.hashCode()); } - + public void testReflectionEqualsAndHashCode() throws Exception { // Test that generated equals() and hashCode() will disregard the order // of map entries when comparing/hashing map fields. @@ -570,22 +793,22 @@ public class MapForProto2Test extends TestCase { Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); FieldDescriptor field = f("int32_to_int32_field"); - + Message.Builder b1 = dynamicDefaultInstance.newBuilderForType(); b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2)); b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4)); b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6)); Message m1 = b1.build(); - + Message.Builder b2 = dynamicDefaultInstance.newBuilderForType(); b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6)); b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2)); b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4)); Message m2 = b2.build(); - + assertEquals(m1, m2); assertEquals(m1.hashCode(), m2.hashCode()); - + // Make sure we did compare map fields. b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0)); m2 = b2.build(); @@ -593,7 +816,7 @@ public class MapForProto2Test extends TestCase { // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed // to be different. } - + public void testUnknownEnumValues() throws Exception { TestUnknownEnumValue.Builder builder = TestUnknownEnumValue.newBuilder(); @@ -646,13 +869,266 @@ public class MapForProto2Test extends TestCase { public void testIterationOrder() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); assertEquals(Arrays.asList("1", "2", "3"), new ArrayList<String>(message.getStringToInt32Field().keySet())); } + public void testContains() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(builder); + assertMapContainsSetValues(builder); + assertMapContainsSetValues(builder.build()); + } + + private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) { + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1)); + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2)); + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3)); + assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToStringField(1)); + assertTrue(testMapOrBuilder.containsInt32ToStringField(2)); + assertTrue(testMapOrBuilder.containsInt32ToStringField(3)); + assertFalse(testMapOrBuilder.containsInt32ToStringField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToBytesField(1)); + assertTrue(testMapOrBuilder.containsInt32ToBytesField(2)); + assertTrue(testMapOrBuilder.containsInt32ToBytesField(3)); + assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToEnumField(1)); + assertTrue(testMapOrBuilder.containsInt32ToEnumField(2)); + assertTrue(testMapOrBuilder.containsInt32ToEnumField(3)); + assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToMessageField(1)); + assertTrue(testMapOrBuilder.containsInt32ToMessageField(2)); + assertTrue(testMapOrBuilder.containsInt32ToMessageField(3)); + assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1)); + + assertTrue(testMapOrBuilder.containsStringToInt32Field("1")); + assertTrue(testMapOrBuilder.containsStringToInt32Field("2")); + assertTrue(testMapOrBuilder.containsStringToInt32Field("3")); + assertFalse(testMapOrBuilder.containsStringToInt32Field("-1")); + } + + public void testCount() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + + setMapValuesUsingMutableMap(builder); + assertMapCounts(3, builder); + + TestMap message = builder.build(); + assertMapCounts(3, message); + + builder = message.toBuilder().putInt32ToInt32Field(4, 44); + assertEquals(4, builder.getInt32ToInt32FieldCount()); + assertEquals(4, builder.build().getInt32ToInt32FieldCount()); + + // already present - should be unchanged + builder.putInt32ToInt32Field(4, 44); + assertEquals(4, builder.getInt32ToInt32FieldCount()); + } + + private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) { + assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount()); + } + + public void testGetOrDefault() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + setMapValuesUsingAccessors(builder); + doTestGetOrDefault(builder); + doTestGetOrDefault(builder.build()); + } + + public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) { + assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11)); + assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11)); + + assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11")); + assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null)); + + assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null)); + + assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null)); + + assertEquals(MessageValue.newBuilder().setValue(11).build(), + testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null)); + + assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11)); + assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11)); + + try { + testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + public void testGetOrThrow() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + setMapValuesUsingAccessors(builder); + doTestGetOrDefault(builder); + doTestGetOrDefault(builder.build()); + } + + public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) { + assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1)); + + try { + testMapOrBuilder.getInt32ToStringFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1)); + + try { + testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(MessageValue.newBuilder().setValue(11).build(), + testMapOrBuilder.getInt32ToMessageFieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1")); + try { + testMapOrBuilder.getStringToInt32FieldOrThrow("-1"); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + try { + testMapOrBuilder.getStringToInt32FieldOrThrow(null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + public void testPut() { + TestMap.Builder builder = TestMap.newBuilder(); + builder.putInt32ToInt32Field(1, 11); + assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); + + builder.putInt32ToStringField(1, "a"); + assertEquals("a", builder.getInt32ToStringFieldOrThrow(1)); + try { + builder.putInt32ToStringField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToBytesField(1, TestUtil.toBytes("11")); + assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1)); + try { + builder.putInt32ToBytesField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO); + assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1)); + try { + builder.putInt32ToEnumField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putStringToInt32Field("a", 1); + assertEquals(1, builder.getStringToInt32FieldOrThrow("a")); + try { + builder.putStringToInt32Field(null, -1); + } catch (NullPointerException e) { + // expected + } + } + + public void testRemove() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(builder); + assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToInt32Field(1); + assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1)); + } + + assertEquals("11", builder.getInt32ToStringFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToStringField(1); + assertNull(builder.getInt32ToStringFieldOrDefault(1, null)); + } + + assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToBytesField(1); + assertNull(builder.getInt32ToBytesFieldOrDefault(1, null)); + } + + assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToEnumField(1); + assertNull(builder.getInt32ToEnumFieldOrDefault(1, null)); + } + + assertEquals(11, builder.getStringToInt32FieldOrThrow("1")); + for (int times = 0; times < 2; times++) { + builder.removeStringToInt32Field("1"); + assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1)); + } + + try { + builder.removeStringToInt32Field(null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + // Regression test for b/20494788 public void testMapInitializationOrder() throws Exception { assertEquals("RedactAllTypes", map_test.RedactAllTypes @@ -666,18 +1142,36 @@ public class MapForProto2Test extends TestCase { message.getDescriptorForType().findFieldByName("map_field"), 0); assertEquals(2, mapEntry.getAllFields().size()); } - + private static <K, V> Map<K, V> newMap(K key1, V value1) { Map<K, V> map = new HashMap<K, V>(); map.put(key1, value1); return map; } - + private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) { Map<K, V> map = new HashMap<K, V>(); map.put(key1, value1); map.put(key2, value2); return map; } -} + public void testGetMap() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValuesUsingAccessors(builder); + assertMapValuesSet(builder); + TestMap message = builder.build(); + assertEquals( + message.getStringToInt32Field(), + message.getStringToInt32FieldMap()); + assertEquals( + message.getInt32ToBytesField(), + message.getInt32ToBytesFieldMap()); + assertEquals( + message.getInt32ToEnumField(), + message.getInt32ToEnumFieldMap()); + assertEquals( + message.getInt32ToMessageField(), + message.getInt32ToMessageFieldMap()); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/MapTest.java b/java/core/src/test/java/com/google/protobuf/MapTest.java index 1dc5787d..caef246b 100644 --- a/java/core/src/test/java/com/google/protobuf/MapTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapTest.java @@ -30,15 +30,20 @@ package com.google.protobuf; + import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import map_test.MapTestProto.BizarroTestMap; import map_test.MapTestProto.TestMap; import map_test.MapTestProto.TestMap.MessageValue; +import map_test.MapTestProto.TestMapOrBuilder; import map_test.MapTestProto.TestOnChangeEventPropagation; import junit.framework.TestCase; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -49,7 +54,8 @@ import java.util.Map; * Unit tests for map fields. */ public class MapTest extends TestCase { - private void setMapValues(TestMap.Builder builder) { + + private void setMapValuesUsingMutableMap(TestMap.Builder builder) { builder.getMutableInt32ToInt32Field().put(1, 11); builder.getMutableInt32ToInt32Field().put(2, 22); builder.getMutableInt32ToInt32Field().put(3, 33); @@ -78,6 +84,46 @@ public class MapTest extends TestCase { builder.getMutableStringToInt32Field().put("3", 33); } + private void setMapValuesUsingAccessors(TestMap.Builder builder) { + builder + .putInt32ToInt32Field(1, 11) + .putInt32ToInt32Field(2, 22) + .putInt32ToInt32Field(3, 33) + + .putInt32ToStringField(1, "11") + .putInt32ToStringField(2, "22") + .putInt32ToStringField(3, "33") + + .putInt32ToBytesField(1, TestUtil.toBytes("11")) + .putInt32ToBytesField(2, TestUtil.toBytes("22")) + .putInt32ToBytesField(3, TestUtil.toBytes("33")) + + .putInt32ToEnumField(1, TestMap.EnumValue.FOO) + .putInt32ToEnumField(2, TestMap.EnumValue.BAR) + .putInt32ToEnumField(3, TestMap.EnumValue.BAZ) + + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build()) + .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build()) + .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build()) + + .putStringToInt32Field("1", 11) + .putStringToInt32Field("2", 22) + .putStringToInt32Field("3", 33); + } + + public void testSetMapValues() { + TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(usingMutableMapBuilder); + TestMap usingMutableMap = usingMutableMapBuilder.build(); + assertMapValuesSet(usingMutableMap); + + TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder(); + setMapValuesUsingAccessors(usingAccessorsBuilder); + TestMap usingAccessors = usingAccessorsBuilder.build(); + assertMapValuesSet(usingAccessors); + assertEquals(usingAccessors, usingMutableMap); + } + private void copyMapValues(TestMap source, TestMap.Builder destination) { destination .putAllInt32ToInt32Field(source.getInt32ToInt32Field()) @@ -120,7 +166,7 @@ public class MapTest extends TestCase { assertEquals(33, message.getStringToInt32Field().get("3").intValue()); } - private void updateMapValues(TestMap.Builder builder) { + private void updateMapValuesUsingMutableMap(TestMap.Builder builder) { builder.getMutableInt32ToInt32Field().put(1, 111); builder.getMutableInt32ToInt32Field().remove(2); builder.getMutableInt32ToInt32Field().put(4, 44); @@ -148,6 +194,58 @@ public class MapTest extends TestCase { builder.getMutableStringToInt32Field().put("4", 44); } + private void updateMapValuesUsingAccessors(TestMap.Builder builder) { + builder + .putInt32ToInt32Field(1, 111) + .removeInt32ToInt32Field(2) + .putInt32ToInt32Field(4, 44) + + .putInt32ToStringField(1, "111") + .removeInt32ToStringField(2) + .putInt32ToStringField(4, "44") + + .putInt32ToBytesField(1, TestUtil.toBytes("111")) + .removeInt32ToBytesField(2) + .putInt32ToBytesField(4, TestUtil.toBytes("44")) + + .putInt32ToEnumField(1, TestMap.EnumValue.BAR) + .removeInt32ToEnumField(2) + .putInt32ToEnumField(4, TestMap.EnumValue.QUX) + + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build()) + .removeInt32ToMessageField(2) + .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build()) + + .putStringToInt32Field("1", 111) + .removeStringToInt32Field("2") + .putStringToInt32Field("4", 44); + } + + public void testUpdateMapValues() { + TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(usingMutableMapBuilder); + TestMap usingMutableMap = usingMutableMapBuilder.build(); + assertMapValuesSet(usingMutableMap); + + TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder(); + setMapValuesUsingAccessors(usingAccessorsBuilder); + TestMap usingAccessors = usingAccessorsBuilder.build(); + assertMapValuesSet(usingAccessors); + assertEquals(usingAccessors, usingMutableMap); + + usingMutableMapBuilder = usingMutableMap.toBuilder(); + updateMapValuesUsingMutableMap(usingMutableMapBuilder); + usingMutableMap = usingMutableMapBuilder.build(); + assertMapValuesUpdated(usingMutableMap); + + usingAccessorsBuilder = usingAccessors.toBuilder(); + updateMapValuesUsingAccessors(usingAccessorsBuilder); + usingAccessors = usingAccessorsBuilder.build(); + assertMapValuesUpdated(usingAccessors); + + assertEquals(usingAccessors, usingMutableMap); + } + private void assertMapValuesUpdated(TestMap message) { assertEquals(3, message.getInt32ToInt32Field().size()); assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); @@ -180,15 +278,50 @@ public class MapTest extends TestCase { assertEquals(44, message.getStringToInt32Field().get("4").intValue()); } - private void assertMapValuesCleared(TestMap message) { - assertEquals(0, message.getInt32ToInt32Field().size()); - assertEquals(0, message.getInt32ToStringField().size()); - assertEquals(0, message.getInt32ToBytesField().size()); - assertEquals(0, message.getInt32ToEnumField().size()); - assertEquals(0, message.getInt32ToMessageField().size()); - assertEquals(0, message.getStringToInt32Field().size()); + private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { + assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToStringField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount()); + assertEquals(0, testMapOrBuilder.getStringToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount()); + } + + public void testGetMapIsImmutable() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapsAreImmutable(builder); + assertMapsAreImmutable(builder.build()); + + setMapValuesUsingAccessors(builder); + assertMapsAreImmutable(builder); + assertMapsAreImmutable(builder.build()); + } + + private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) { + assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2); + assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2"); + assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2")); + assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO); + assertImmutable( + testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance()); + assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2); } - + + private <K, V> void assertImmutable(Map<K, V> map, K key, V value) { + try { + map.put(key, value); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + public void testMutableMapLifecycle() { TestMap.Builder builder = TestMap.newBuilder(); Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field(); @@ -218,7 +351,7 @@ public class MapTest extends TestCase { assertEquals( newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), builder.getInt32ToEnumField()); - + Map<Integer, String> stringMap = builder.getMutableInt32ToStringField(); stringMap.put(1, "1"); assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); @@ -233,7 +366,7 @@ public class MapTest extends TestCase { assertEquals( newMap(1, "1", 2, "2"), builder.getInt32ToStringField()); - + Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField(); messageMap.put(1, TestMap.MessageValue.getDefaultInstance()); assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), @@ -298,32 +431,34 @@ public class MapTest extends TestCase { assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); } - + public void testGettersAndSetters() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); assertMapValuesCleared(message); builder = message.toBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); message = builder.build(); assertMapValuesSet(message); builder = message.toBuilder(); - updateMapValues(builder); + updateMapValuesUsingMutableMap(builder); message = builder.build(); assertMapValuesUpdated(message); builder = message.toBuilder(); builder.clear(); + assertMapValuesCleared(builder); message = builder.build(); assertMapValuesCleared(message); } public void testPutAll() throws Exception { TestMap.Builder sourceBuilder = TestMap.newBuilder(); - setMapValues(sourceBuilder); + setMapValuesUsingMutableMap(sourceBuilder); TestMap source = sourceBuilder.build(); + assertMapValuesSet(source); TestMap.Builder destination = TestMap.newBuilder(); copyMapValues(source, destination); @@ -344,18 +479,76 @@ public class MapTest extends TestCase { assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue()); assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue()); assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(3, destination.getInt32ToEnumFieldCount()); + } + + public void testPutForUnknownEnumValues() throws Exception { + TestMap.Builder builder = TestMap.newBuilder() + .putInt32ToEnumFieldValue(0, 0) + .putInt32ToEnumFieldValue(1, 1); + + try { + builder.putInt32ToEnumFieldValue(2, 1000); // unknown value. + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + TestMap message = builder.build(); + assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0)); + assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1)); + assertEquals(2, message.getInt32ToEnumFieldCount()); + } + + public void testPutChecksNullKeysAndValues() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + + try { + builder.putInt32ToStringField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToBytesField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToEnumField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToMessageField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putStringToInt32Field(null, 1); + fail(); + } catch (NullPointerException e) { + // expected. + } } public void testSerializeAndParse() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); assertEquals(message.getSerializedSize(), message.toByteString().size()); message = TestMap.parser().parseFrom(message.toByteString()); assertMapValuesSet(message); builder = message.toBuilder(); - updateMapValues(builder); + updateMapValuesUsingMutableMap(builder); message = builder.build(); assertEquals(message.getSerializedSize(), message.toByteString().size()); message = TestMap.parser().parseFrom(message.toByteString()); @@ -369,9 +562,58 @@ public class MapTest extends TestCase { assertMapValuesCleared(message); } + private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream); + bizarroMap.writeTo(output); + output.flush(); + return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray())); + } + + public void testParseError() throws Exception { + ByteString bytes = TestUtil.toBytes("SOME BYTES"); + String stringKey = "a string key"; + + TestMap map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToInt32Field(5, bytes) + .build()); + assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToStringField(stringKey, 5) + .build()); + assertEquals(map.getInt32ToStringFieldOrDefault(0, null), ""); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToBytesField(stringKey, 5) + .build()); + assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY); + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToEnumField(stringKey, bytes) + .build()); + assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO); + + try { + tryParseTestMap(BizarroTestMap.newBuilder() + .putInt32ToMessageField(stringKey, bytes) + .build()); + fail(); + } catch (InvalidProtocolBufferException expected) { + assertTrue(expected.getUnfinishedMessage() instanceof TestMap); + map = (TestMap) expected.getUnfinishedMessage(); + assertTrue(map.getInt32ToMessageField().isEmpty()); + } + + map = tryParseTestMap(BizarroTestMap.newBuilder() + .putStringToInt32Field(stringKey, bytes) + .build()); + assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0); + } + public void testMergeFrom() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); TestMap.Builder other = TestMap.newBuilder(); @@ -629,7 +871,7 @@ public class MapTest extends TestCase { public void testTextFormat() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); String textData = TextFormat.printToString(message); @@ -643,7 +885,7 @@ public class MapTest extends TestCase { public void testDynamicMessage() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); Message dynamicDefaultInstance = @@ -760,19 +1002,317 @@ public class MapTest extends TestCase { public void testIterationOrder() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); - setMapValues(builder); + setMapValuesUsingMutableMap(builder); TestMap message = builder.build(); assertEquals(Arrays.asList("1", "2", "3"), new ArrayList<String>(message.getStringToInt32Field().keySet())); } - + + public void testGetMap() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(builder); + TestMap message = builder.build(); + assertEquals( + message.getStringToInt32Field(), + message.getStringToInt32FieldMap()); + assertEquals( + message.getInt32ToBytesField(), + message.getInt32ToBytesFieldMap()); + assertEquals( + message.getInt32ToEnumField(), + message.getInt32ToEnumFieldMap()); + assertEquals( + message.getInt32ToEnumFieldValue(), + message.getInt32ToEnumFieldValueMap()); + assertEquals( + message.getInt32ToMessageField(), + message.getInt32ToMessageFieldMap()); + } + + public void testContains() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(builder); + assertMapContainsSetValues(builder); + assertMapContainsSetValues(builder.build()); + } + + private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) { + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1)); + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2)); + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3)); + assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToStringField(1)); + assertTrue(testMapOrBuilder.containsInt32ToStringField(2)); + assertTrue(testMapOrBuilder.containsInt32ToStringField(3)); + assertFalse(testMapOrBuilder.containsInt32ToStringField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToBytesField(1)); + assertTrue(testMapOrBuilder.containsInt32ToBytesField(2)); + assertTrue(testMapOrBuilder.containsInt32ToBytesField(3)); + assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToEnumField(1)); + assertTrue(testMapOrBuilder.containsInt32ToEnumField(2)); + assertTrue(testMapOrBuilder.containsInt32ToEnumField(3)); + assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToMessageField(1)); + assertTrue(testMapOrBuilder.containsInt32ToMessageField(2)); + assertTrue(testMapOrBuilder.containsInt32ToMessageField(3)); + assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1)); + + assertTrue(testMapOrBuilder.containsStringToInt32Field("1")); + assertTrue(testMapOrBuilder.containsStringToInt32Field("2")); + assertTrue(testMapOrBuilder.containsStringToInt32Field("3")); + assertFalse(testMapOrBuilder.containsStringToInt32Field("-1")); + } + + public void testCount() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + + setMapValuesUsingMutableMap(builder); + assertMapCounts(3, builder); + + TestMap message = builder.build(); + assertMapCounts(3, message); + + builder = message.toBuilder().putInt32ToInt32Field(4, 44); + assertEquals(4, builder.getInt32ToInt32FieldCount()); + assertEquals(4, builder.build().getInt32ToInt32FieldCount()); + + // already present - should be unchanged + builder.putInt32ToInt32Field(4, 44); + assertEquals(4, builder.getInt32ToInt32FieldCount()); + } + + private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) { + assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount()); + } + + public void testGetOrDefault() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + setMapValuesUsingAccessors(builder); + doTestGetOrDefault(builder); + doTestGetOrDefault(builder.build()); + } + + public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) { + assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11)); + assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11)); + + assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11")); + assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null)); + + assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null)); + + assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null)); + + assertEquals( + TestMap.EnumValue.BAR.getNumber(), + (int) testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(2, -1)); + assertEquals(-1, testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(-1000, -1)); + + assertEquals(MessageValue.newBuilder().setValue(11).build(), + testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null)); + + assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11)); + assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11)); + + try { + testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + public void testGetOrThrow() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + setMapValuesUsingAccessors(builder); + doTestGetOrDefault(builder); + doTestGetOrDefault(builder.build()); + } + + public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) { + assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1)); + + try { + testMapOrBuilder.getInt32ToStringFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1)); + + try { + testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals( + TestMap.EnumValue.BAR.getNumber(), testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(2)); + try { + testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(MessageValue.newBuilder().setValue(11).build(), + testMapOrBuilder.getInt32ToMessageFieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1")); + try { + testMapOrBuilder.getStringToInt32FieldOrThrow("-1"); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + try { + testMapOrBuilder.getStringToInt32FieldOrThrow(null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + public void testPut() { + TestMap.Builder builder = TestMap.newBuilder(); + builder.putInt32ToInt32Field(1, 11); + assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); + + builder.putInt32ToStringField(1, "a"); + assertEquals("a", builder.getInt32ToStringFieldOrThrow(1)); + try { + builder.putInt32ToStringField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToBytesField(1, TestUtil.toBytes("11")); + assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1)); + try { + builder.putInt32ToBytesField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO); + assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1)); + try { + builder.putInt32ToEnumField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToEnumFieldValue(1, TestMap.EnumValue.BAR.getNumber()); + assertEquals( + TestMap.EnumValue.BAR.getNumber(), builder.getInt32ToEnumFieldValueOrThrow(1)); + try { + builder.putInt32ToEnumFieldValue(1, -1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + builder.putStringToInt32Field("a", 1); + assertEquals(1, builder.getStringToInt32FieldOrThrow("a")); + try { + builder.putStringToInt32Field(null, -1); + } catch (NullPointerException e) { + // expected + } + } + + public void testRemove() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValuesUsingMutableMap(builder); + assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToInt32Field(1); + assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1)); + } + + assertEquals("11", builder.getInt32ToStringFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToStringField(1); + assertNull(builder.getInt32ToStringFieldOrDefault(1, null)); + } + + assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToBytesField(1); + assertNull(builder.getInt32ToBytesFieldOrDefault(1, null)); + } + + assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToEnumField(1); + assertNull(builder.getInt32ToEnumFieldOrDefault(1, null)); + } + + assertEquals(11, builder.getStringToInt32FieldOrThrow("1")); + for (int times = 0; times < 2; times++) { + builder.removeStringToInt32Field("1"); + assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1)); + } + + try { + builder.removeStringToInt32Field(null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + private static <K, V> Map<K, V> newMap(K key1, V value1) { Map<K, V> map = new HashMap<K, V>(); map.put(key1, value1); return map; } - + private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) { Map<K, V> map = new HashMap<K, V>(); map.put(key1, value1); diff --git a/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java new file mode 100644 index 00000000..241a4354 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java @@ -0,0 +1,190 @@ +// 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; + +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; + +import junit.framework.TestCase; + +import java.util.Collections; +import java.util.List; + +/** + * Tests for {@link RepeatedFieldBuilderV3}. This tests basic functionality. + * More extensive testing is provided via other tests that exercise the + * builder. + * + * @author jonp@google.com (Jon Perlow) + */ +public class RepeatedFieldBuilderV3Test extends TestCase { + + public void testBasicUse() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> builder = newRepeatedFieldBuilderV3(mockParent); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + + List<TestAllTypes> list = builder.build(); + assertEquals(2, list.size()); + assertEquals(0, list.get(0).getOptionalInt32()); + assertEquals(1, list.get(1).getOptionalInt32()); + assertIsUnmodifiable(list); + + // Make sure it doesn't change. + List<TestAllTypes> list2 = builder.build(); + assertSame(list, list2); + assertEquals(0, mockParent.getInvalidationCount()); + } + + public void testGoingBackAndForth() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> builder = newRepeatedFieldBuilderV3(mockParent); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + + // Convert to list + List<TestAllTypes> list = builder.build(); + assertEquals(2, list.size()); + assertEquals(0, list.get(0).getOptionalInt32()); + assertEquals(1, list.get(1).getOptionalInt32()); + assertIsUnmodifiable(list); + + // Update 0th item + assertEquals(0, mockParent.getInvalidationCount()); + builder.getBuilder(0).setOptionalString("foo"); + assertEquals(1, mockParent.getInvalidationCount()); + list = builder.build(); + assertEquals(2, list.size()); + assertEquals(0, list.get(0).getOptionalInt32()); + assertEquals("foo", list.get(0).getOptionalString()); + assertEquals(1, list.get(1).getOptionalInt32()); + assertIsUnmodifiable(list); + assertEquals(1, mockParent.getInvalidationCount()); + } + + public void testVariousMethods() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> builder = newRepeatedFieldBuilderV3(mockParent); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build()); + builder.addBuilder(0, TestAllTypes.getDefaultInstance()) + .setOptionalInt32(0); + builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3); + + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + assertEquals(2, builder.getMessage(2).getOptionalInt32()); + assertEquals(3, builder.getMessage(3).getOptionalInt32()); + + assertEquals(0, mockParent.getInvalidationCount()); + List<TestAllTypes> messages = builder.build(); + assertEquals(4, messages.size()); + assertSame(messages, builder.build()); // expect same list + + // Remove a message. + builder.remove(2); + assertEquals(1, mockParent.getInvalidationCount()); + assertEquals(3, builder.getCount()); + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + assertEquals(3, builder.getMessage(2).getOptionalInt32()); + + // Remove a builder. + builder.remove(0); + assertEquals(1, mockParent.getInvalidationCount()); + assertEquals(2, builder.getCount()); + assertEquals(1, builder.getMessage(0).getOptionalInt32()); + assertEquals(3, builder.getMessage(1).getOptionalInt32()); + + // Test clear. + builder.clear(); + assertEquals(1, mockParent.getInvalidationCount()); + assertEquals(0, builder.getCount()); + assertTrue(builder.isEmpty()); + } + + public void testLists() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> builder = newRepeatedFieldBuilderV3(mockParent); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); + builder.addMessage(0, + TestAllTypes.newBuilder().setOptionalInt32(0).build()); + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + + // Use list of builders. + List<TestAllTypes.Builder> builders = builder.getBuilderList(); + assertEquals(0, builders.get(0).getOptionalInt32()); + assertEquals(1, builders.get(1).getOptionalInt32()); + builders.get(0).setOptionalInt32(10); + builders.get(1).setOptionalInt32(11); + + // Use list of protos + List<TestAllTypes> protos = builder.getMessageList(); + assertEquals(10, protos.get(0).getOptionalInt32()); + assertEquals(11, protos.get(1).getOptionalInt32()); + + // Add an item to the builders and verify it's updated in both + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build()); + assertEquals(3, builders.size()); + assertEquals(3, protos.size()); + } + + private void assertIsUnmodifiable(List<?> list) { + if (list == Collections.emptyList()) { + // OKAY -- Need to check this b/c EmptyList allows you to call clear. + } else { + try { + list.clear(); + fail("List wasn't immutable"); + } catch (UnsupportedOperationException e) { + // good + } + } + } + + private RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> + newRepeatedFieldBuilderV3(GeneratedMessage.BuilderParent parent) { + return new RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false, + parent, false); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java new file mode 100644 index 00000000..e3a8d4f4 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java @@ -0,0 +1,155 @@ +// 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; + +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; + +import junit.framework.TestCase; + +/** + * Tests for {@link SingleFieldBuilderV3}. This tests basic functionality. + * More extensive testing is provided via other tests that exercise the + * builder. + * + * @author jonp@google.com (Jon Perlow) + */ +public class SingleFieldBuilderV3Test extends TestCase { + + public void testBasicUseAndInvalidations() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> builder = + new SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder>( + TestAllTypes.getDefaultInstance(), + mockParent, + false); + assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + assertEquals(TestAllTypes.getDefaultInstance(), + builder.getBuilder().buildPartial()); + assertEquals(0, mockParent.getInvalidationCount()); + + builder.getBuilder().setOptionalInt32(10); + assertEquals(0, mockParent.getInvalidationCount()); + TestAllTypes message = builder.build(); + assertEquals(10, message.getOptionalInt32()); + + // Test that we receive invalidations now that build has been called. + assertEquals(0, mockParent.getInvalidationCount()); + builder.getBuilder().setOptionalInt32(20); + assertEquals(1, mockParent.getInvalidationCount()); + + // Test that we don't keep getting invalidations on every change + builder.getBuilder().setOptionalInt32(30); + assertEquals(1, mockParent.getInvalidationCount()); + + } + + public void testSetMessage() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> builder = + new SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder>( + TestAllTypes.getDefaultInstance(), + mockParent, + false); + builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); + assertEquals(0, builder.getMessage().getOptionalInt32()); + + // Update message using the builder + builder.getBuilder().setOptionalInt32(1); + assertEquals(0, mockParent.getInvalidationCount()); + assertEquals(1, builder.getBuilder().getOptionalInt32()); + assertEquals(1, builder.getMessage().getOptionalInt32()); + builder.build(); + builder.getBuilder().setOptionalInt32(2); + assertEquals(2, builder.getBuilder().getOptionalInt32()); + assertEquals(2, builder.getMessage().getOptionalInt32()); + + // Make sure message stays cached + assertSame(builder.getMessage(), builder.getMessage()); + } + + public void testClear() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> builder = + new SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder>( + TestAllTypes.getDefaultInstance(), + mockParent, + false); + builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); + assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + builder.clear(); + assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + + builder.getBuilder().setOptionalInt32(1); + assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + builder.clear(); + assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + } + + public void testMerge() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder> builder = + new SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder, + TestAllTypesOrBuilder>( + TestAllTypes.getDefaultInstance(), + mockParent, + false); + + // Merge into default field. + builder.mergeFrom(TestAllTypes.getDefaultInstance()); + assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + + // Merge into non-default field on existing builder. + builder.getBuilder().setOptionalInt32(2); + builder.mergeFrom(TestAllTypes.newBuilder() + .setOptionalDouble(4.0) + .buildPartial()); + assertEquals(2, builder.getMessage().getOptionalInt32()); + assertEquals(4.0, builder.getMessage().getOptionalDouble()); + + // Merge into non-default field on existing message + builder.setMessage(TestAllTypes.newBuilder() + .setOptionalInt32(10) + .buildPartial()); + builder.mergeFrom(TestAllTypes.newBuilder() + .setOptionalDouble(5.0) + .buildPartial()); + assertEquals(10, builder.getMessage().getOptionalInt32()); + assertEquals(5.0, builder.getMessage().getOptionalDouble()); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/TestUtil.java b/java/core/src/test/java/com/google/protobuf/TestUtil.java index 08b2a76d..d94f99e3 100644 --- a/java/core/src/test/java/com/google/protobuf/TestUtil.java +++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java @@ -3764,7 +3764,8 @@ public final class TestUtil { private static File getTestDataDir() { // Search each parent directory looking for "src/google/protobuf". - File ancestor = new File("."); + File ancestor = new File(System.getProperty("protobuf.dir", ".")); + String initialPath = ancestor.getAbsolutePath(); try { ancestor = ancestor.getCanonicalFile(); } catch (IOException e) { @@ -3781,7 +3782,7 @@ public final class TestUtil { throw new RuntimeException( "Could not find golden files. This test must be run from within the " + "protobuf source package so that it can read test data files from the " + - "C++ source tree."); + "C++ source tree: " + initialPath); } /** diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java index 63c17cd0..14783b0a 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java @@ -522,15 +522,16 @@ public class TextFormatTest extends TestCase { "optional_string: \"ueoauaoe\n" + "optional_int32: 123"); assertParseError( - "1:2: Extension \"nosuchext\" not found in the ExtensionRegistry.", + "1:2: Input contains unknown fields and/or extensions:\n" + + "1:2:\tprotobuf_unittest.TestAllTypes.[nosuchext]", "[nosuchext]: 123"); assertParseError( "1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " + "not extend message type \"protobuf_unittest.TestAllTypes\".", "[protobuf_unittest.optional_int32_extension]: 123"); assertParseError( - "1:1: Message type \"protobuf_unittest.TestAllTypes\" has no field " + - "named \"nosuchfield\".", + "1:1: Input contains unknown fields and/or extensions:\n" + + "1:1:\tprotobuf_unittest.TestAllTypes.nosuchfield", "nosuchfield: 123"); assertParseError( "1:21: Expected \">\".", diff --git a/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto b/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto index 8f3ca8c6..86cdd286 100644 --- a/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto @@ -54,6 +54,7 @@ message TestAllTypes { NestedEnum optional_nested_enum = 4; NestedMessage optional_nested_message = 5; protobuf_unittest.TestRequired optional_proto2_message = 6; + NestedMessage optional_lazy_message = 7 [lazy=true]; oneof oneof_field { int32 oneof_int32 = 11; @@ -81,6 +82,7 @@ message TestOptionalFieldsOnly { TestAllTypes.NestedEnum optional_nested_enum = 4; TestAllTypes.NestedMessage optional_nested_message = 5; protobuf_unittest.TestRequired optional_proto2_message = 6; + TestAllTypes.NestedMessage optional_lazy_message = 7 [lazy=true]; } message TestRepeatedFieldsOnly { diff --git a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto index d5418f28..de3336a5 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto @@ -70,6 +70,17 @@ message TestRecursiveMap { optional int32 value = 1; map<int32, TestRecursiveMap> recursive_map_field = 2; } + + +// a decoy of TestMap for testing parsing errors +message BizarroTestMap { + map<int32, bytes> int32_to_int32_field = 1; // same key type, different value + map<string, int32> int32_to_string_field = 2; // different key and value types + map<string, int32> int32_to_bytes_field = 3; // different key types, same value + map<string, bytes> int32_to_enum_field = 4; // different key and value types + map<string, bytes> int32_to_message_field = 5; // different key and value types + map<string, bytes> string_to_int32_field = 6; // same key type, different value +} package map_for_proto2_lite_test; option java_package = "map_lite_test"; option optimize_for = LITE_RUNTIME; diff --git a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto index a9be5166..0c92b0ae 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto @@ -72,3 +72,14 @@ message TestRecursiveMap { optional int32 value = 1; map<int32, TestRecursiveMap> recursive_map_field = 2; } + + +// a decoy of TestMap for testing parsing errors +message BizarroTestMap { + map<int32, bytes> int32_to_int32_field = 1; // same key type, different value + map<string, int32> int32_to_string_field = 2; // different key and value types + map<string, int32> int32_to_bytes_field = 3; // different key types, same value + map<string, bytes> int32_to_enum_field = 4; // different key and value types + map<string, bytes> int32_to_message_field = 5; // different key and value types + map<string, bytes> string_to_int32_field = 6; // same key type, different value +} diff --git a/java/core/src/test/proto/com/google/protobuf/map_test.proto b/java/core/src/test/proto/com/google/protobuf/map_test.proto index 2280ac03..9eb63fc3 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_test.proto @@ -55,9 +55,19 @@ message TestMap { map<string, int32> string_to_int32_field = 6; } -// Used to test that a nested bulider containing map fields will properly +// Used to test that a nested builder containing map fields will properly // propagate the onChange event and mark its parent dirty when a change // is made to a map field. message TestOnChangeEventPropagation { TestMap optional_message = 1; } + +// a decoy of TestMap for testing parsing errors +message BizarroTestMap { + map<int32, bytes> int32_to_int32_field = 1; // same key type, different value + map<string, int32> int32_to_string_field = 2; // different key and value types + map<string, int32> int32_to_bytes_field = 3; // different key types, same value + map<string, bytes> int32_to_enum_field = 4; // different key and value types + map<string, bytes> int32_to_message_field = 5; // different key and value types + map<string, bytes> string_to_int32_field = 6; // same key type, different value +} |