1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import static com.google.common.truth.Truth.assertThat; 11 12 import protobuf_unittest.Engine; 13 import protobuf_unittest.TimingBelt; 14 import protobuf_unittest.Vehicle; 15 import protobuf_unittest.Wheel; 16 import java.util.ArrayList; 17 import java.util.List; 18 import org.junit.Test; 19 import org.junit.runner.RunWith; 20 import org.junit.runners.JUnit4; 21 22 /** 23 * Test cases that exercise end-to-end use cases involving {@link SingleFieldBuilder} and {@link 24 * RepeatedFieldBuilder}. 25 */ 26 @RunWith(JUnit4.class) 27 public class NestedBuildersTest { 28 29 @Test test3LayerPropagationWithIntermediateClear()30 public void test3LayerPropagationWithIntermediateClear() { 31 Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); 32 vehicleBuilder.getEngineBuilder().getTimingBeltBuilder(); 33 34 // This step detaches the TimingBelt.Builder (though it leaves a SingleFieldBuilder in place) 35 vehicleBuilder.getEngineBuilder().clear(); 36 37 // These steps build the middle and top level messages, it used to leave the vestigial 38 // TimingBelt.Builder in a state where further changes didn't propagate anymore 39 Object unused = vehicleBuilder.getEngineBuilder().build(); 40 unused = vehicleBuilder.build(); 41 42 TimingBelt expected = TimingBelt.newBuilder().setNumberOfTeeth(124).build(); 43 vehicleBuilder.getEngineBuilder().setTimingBelt(expected); 44 // Testing that b/254158939 is fixed. It used to be that the setTimingBelt call above didn't 45 // propagate a change notification and the call below would return a stale version of the timing 46 // belt. 47 assertThat(vehicleBuilder.getEngine().getTimingBelt()).isEqualTo(expected); 48 } 49 50 @Test testMessagesAndBuilders()51 public void testMessagesAndBuilders() { 52 Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); 53 vehicleBuilder.addWheelBuilder().setRadius(4).setWidth(1); 54 vehicleBuilder.addWheelBuilder().setRadius(4).setWidth(2); 55 vehicleBuilder.addWheelBuilder().setRadius(4).setWidth(3); 56 vehicleBuilder.addWheelBuilder().setRadius(4).setWidth(4); 57 vehicleBuilder.getEngineBuilder().setLiters(10); 58 59 Vehicle vehicle = vehicleBuilder.build(); 60 assertThat(vehicle.getWheelCount()).isEqualTo(4); 61 for (int i = 0; i < 4; i++) { 62 Wheel wheel = vehicle.getWheel(i); 63 assertThat(wheel.getRadius()).isEqualTo(4); 64 assertThat(wheel.getWidth()).isEqualTo(i + 1); 65 } 66 assertThat(vehicle.getEngine().getLiters()).isEqualTo(10); 67 68 for (int i = 0; i < 4; i++) { 69 vehicleBuilder.getWheelBuilder(i).setRadius(5).setWidth(i + 10); 70 } 71 Engine.Builder engineBuilder = vehicleBuilder.getEngineBuilder().setLiters(20); 72 73 vehicle = vehicleBuilder.build(); 74 for (int i = 0; i < 4; i++) { 75 Wheel wheel = vehicle.getWheel(i); 76 assertThat(wheel.getRadius()).isEqualTo(5); 77 assertThat(wheel.getWidth()).isEqualTo(i + 10); 78 } 79 assertThat(vehicle.getEngine().getLiters()).isEqualTo(20); 80 assertThat(vehicle.hasEngine()).isTrue(); 81 82 engineBuilder.setLiters(50); 83 assertThat(vehicleBuilder.getEngine().getLiters()).isEqualTo(50); 84 } 85 86 @Test testMessagesAreCached()87 public void testMessagesAreCached() { 88 Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); 89 vehicleBuilder.addWheelBuilder().setRadius(1).setWidth(2); 90 vehicleBuilder.addWheelBuilder().setRadius(3).setWidth(4); 91 vehicleBuilder.addWheelBuilder().setRadius(5).setWidth(6); 92 vehicleBuilder.addWheelBuilder().setRadius(7).setWidth(8); 93 94 // Make sure messages are cached. 95 List<Wheel> wheels = new ArrayList<Wheel>(vehicleBuilder.getWheelList()); 96 for (int i = 0; i < wheels.size(); i++) { 97 assertThat(wheels.get(i)).isSameInstanceAs(vehicleBuilder.getWheel(i)); 98 } 99 100 // Now get builders and check they didn't change. 101 for (int i = 0; i < wheels.size(); i++) { 102 vehicleBuilder.getWheel(i); 103 } 104 for (int i = 0; i < wheels.size(); i++) { 105 assertThat(wheels.get(i)).isSameInstanceAs(vehicleBuilder.getWheel(i)); 106 } 107 108 // Change just one 109 vehicleBuilder.getWheelBuilder(3).setRadius(20).setWidth(20); 110 111 // Now get wheels and check that only that one changed 112 for (int i = 0; i < wheels.size(); i++) { 113 if (i < 3) { 114 assertThat(wheels.get(i)).isSameInstanceAs(vehicleBuilder.getWheel(i)); 115 } else { 116 assertThat(wheels.get(i)).isNotSameInstanceAs(vehicleBuilder.getWheel(i)); 117 } 118 } 119 } 120 121 @Test testRemove_WithNestedBuilders()122 public void testRemove_WithNestedBuilders() { 123 Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); 124 vehicleBuilder.addWheelBuilder().setRadius(1).setWidth(1); 125 vehicleBuilder.addWheelBuilder().setRadius(2).setWidth(2); 126 vehicleBuilder.removeWheel(0); 127 128 assertThat(vehicleBuilder.getWheelCount()).isEqualTo(1); 129 assertThat(vehicleBuilder.getWheel(0).getRadius()).isEqualTo(2); 130 } 131 132 @Test testRemove_WithNestedMessages()133 public void testRemove_WithNestedMessages() { 134 Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); 135 vehicleBuilder.addWheel(Wheel.newBuilder().setRadius(1).setWidth(1)); 136 vehicleBuilder.addWheel(Wheel.newBuilder().setRadius(2).setWidth(2)); 137 vehicleBuilder.removeWheel(0); 138 139 assertThat(vehicleBuilder.getWheelCount()).isEqualTo(1); 140 assertThat(vehicleBuilder.getWheel(0).getRadius()).isEqualTo(2); 141 } 142 143 @Test testMerge()144 public void testMerge() { 145 Vehicle vehicle1 = 146 Vehicle.newBuilder() 147 .addWheel(Wheel.newBuilder().setRadius(1).build()) 148 .addWheel(Wheel.newBuilder().setRadius(2).build()) 149 .build(); 150 151 Vehicle vehicle2 = Vehicle.newBuilder().mergeFrom(vehicle1).build(); 152 // List should be the same -- no allocation 153 assertThat(vehicle1.getWheelList()).isSameInstanceAs(vehicle2.getWheelList()); 154 155 Vehicle vehicle3 = vehicle1.toBuilder().build(); 156 assertThat(vehicle1.getWheelList()).isSameInstanceAs(vehicle3.getWheelList()); 157 } 158 159 @Test testGettingBuilderMarksFieldAsHaving()160 public void testGettingBuilderMarksFieldAsHaving() { 161 Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); 162 vehicleBuilder.getEngineBuilder(); 163 Vehicle vehicle = vehicleBuilder.buildPartial(); 164 assertThat(vehicle.hasEngine()).isTrue(); 165 } 166 } 167