diff --git a/core/src/main/java/io/grpc/CallOptions.java b/core/src/main/java/io/grpc/CallOptions.java index 1b8efb2ff1..eb7787a27f 100644 --- a/core/src/main/java/io/grpc/CallOptions.java +++ b/core/src/main/java/io/grpc/CallOptions.java @@ -326,7 +326,7 @@ public final class CallOptions { newOptions.customOptions[customOptions.length] = new Object[] {key, value}; } else { // Replace an existing option - newOptions.customOptions[existingIdx][1] = value; + newOptions.customOptions[existingIdx] = new Object[] {key, value}; } return newOptions; diff --git a/core/src/test/java/io/grpc/CallOptionsTest.java b/core/src/test/java/io/grpc/CallOptionsTest.java index 2a54e406ab..4f37e4fff8 100644 --- a/core/src/test/java/io/grpc/CallOptionsTest.java +++ b/core/src/test/java/io/grpc/CallOptionsTest.java @@ -196,6 +196,17 @@ public class CallOptionsTest { assertThat(opts.getOption(OPTION_2)).isEqualTo("v2"); } + @Test + public void withOptionDoesNotMutateOriginal() { + CallOptions defaultOpt = CallOptions.DEFAULT; + CallOptions opt1 = defaultOpt.withOption(OPTION_1, "v1"); + CallOptions opt2 = opt1.withOption(OPTION_1, "v2"); + + assertThat(defaultOpt.getOption(OPTION_1)).isEqualTo("default"); + assertThat(opt1.getOption(OPTION_1)).isEqualTo("v1"); + assertThat(opt2.getOption(OPTION_1)).isEqualTo("v2"); + } + @Test public void withStreamTracerFactory() { CallOptions opts1 = CallOptions.DEFAULT.withStreamTracerFactory(tracerFactory1);