Skip to content

Commit

Permalink
Merge pull request #10984 from protocolbuffers/googleberg-patch-neste…
Browse files Browse the repository at this point in the history
…d-builder-fix

Fix stale cached submessages by marking nested builder as clean after clear is called
  • Loading branch information
googleberg authored Nov 14, 2022
2 parents 4f393bd + 736e9b8 commit 3c3e66a
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ public SingleFieldBuilderV3<MType, BType, IType> clear() {
builder = null;
}
onChanged();
// After clearing, parent is dirty, but this field builder is now clean and any changes should
// trickle up.
isClean = true;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import static com.google.common.truth.Truth.assertThat;

import protobuf_unittest.Engine;
import protobuf_unittest.TimingBelt;
import protobuf_unittest.Vehicle;
import protobuf_unittest.Wheel;
import java.util.ArrayList;
Expand All @@ -48,6 +49,27 @@
@RunWith(JUnit4.class)
public class NestedBuildersTest {

@Test
public void test3LayerPropagationWithIntermediateClear() {
Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
vehicleBuilder.getEngineBuilder().getTimingBeltBuilder();

// This step detaches the TimingBelt.Builder (though it leaves a SingleFieldBuilder in place)
vehicleBuilder.getEngineBuilder().clear();

// These steps build the middle and top level messages, it used to leave the vestigial
// TimingBelt.Builder in a state where further changes didn't propagate anymore
Object unused = vehicleBuilder.getEngineBuilder().build();
unused = vehicleBuilder.build();

TimingBelt expected = TimingBelt.newBuilder().setNumberOfTeeth(124).build();
vehicleBuilder.getEngineBuilder().setTimingBelt(expected);
// Testing that b/254158939 is fixed. It used to be that the setTimingBelt call above didn't
// propagate a change notification and the call below would return a stale version of the timing
// belt.
assertThat(vehicleBuilder.getEngine().getTimingBelt()).isEqualTo(expected);
}

@Test
public void testMessagesAndBuilders() {
Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ message Vehicle {
message Engine {
optional int32 cylinder = 1;
optional int32 liters = 2;
optional TimingBelt timing_belt = 3;
}

message TimingBelt {
optional int32 number_of_teeth = 1;
}

message Wheel {
Expand Down

0 comments on commit 3c3e66a

Please sign in to comment.