GrpcCallContext implements ApiCallContext { @BetaApi("The surface for extra headers is not stable yet and may change in the future.") @Override public GrpcCallContext withExtraHeaders(Map<String, List<String>> extraHeaders) { Preconditions.checkNotNull(extraHeaders); ImmutableMap<String, List<String>> newExtraHeaders = Headers.mergeHeaders(this.extraHeaders, extraHeaders); return new GrpcCallContext( channel, callOptions, timeout, streamWaitTimeout, streamIdleTimeout, channelAffinity, newExtraHeaders); } private  GrpcCallContext(
      Channel channel,
      CallOptions callOptions,
      @Nullable Duration timeout,
      @Nullable Duration streamWaitTimeout,
      @Nullable Duration streamIdleTimeout,
      @Nullable Integer channelAffinity,
      ImmutableMap<String, List<String>> extraHeaders); static GrpcCallContext createDefault(); static GrpcCallContext of(Channel channel, CallOptions callOptions); @Override GrpcCallContext nullToSelf(ApiCallContext inputContext); @Override GrpcCallContext withCredentials(Credentials newCredentials); @Override GrpcCallContext withTransportChannel(TransportChannel inputChannel); @Override GrpcCallContext withTimeout(@Nullable Duration timeout); @Nullable @Override Duration getTimeout(); @Override GrpcCallContext withStreamWaitTimeout(@Nullable Duration streamWaitTimeout); @Override GrpcCallContext withStreamIdleTimeout(@Nullable Duration streamIdleTimeout); @BetaApi("The surface for channel affinity is not stable yet and may change in the future.") GrpcCallContext withChannelAffinity(@Nullable Integer affinity); @BetaApi("The surface for extra headers is not stable yet and may change in the future.") @Override GrpcCallContext withExtraHeaders(Map<String, List<String>> extraHeaders); @Override ApiCallContext merge(ApiCallContext inputCallContext); Channel getChannel(); CallOptions getCallOptions(); @BetaApi("The surface for streaming is not stable yet and may change in the future.") @Nullable Duration getStreamWaitTimeout(); @BetaApi("The surface for streaming is not stable yet and may change in the future.") @Nullable Duration getStreamIdleTimeout(); @BetaApi("The surface for channel affinity is not stable yet and may change in the future.") @Nullable Integer getChannelAffinity(); @BetaApi("The surface for extra headers is not stable yet and may change in the future.") @Override Map<String, List<String>> getExtraHeaders(); GrpcCallContext withChannel(Channel newChannel); GrpcCallContext withCallOptions(CallOptions newCallOptions); GrpcCallContext withRequestParamsDynamicHeaderOption(String requestParams); @Override @Nonnull ApiTracer getTracer(); @Override GrpcCallContext withTracer(@Nonnull ApiTracer tracer); @Override int hashCode(); @Override boolean equals(Object o);  }
@Test public void testWithExtraHeaders() { Map<String, List<String>> extraHeaders = createTestExtraHeaders("key1", "value1", "key1", "value2"); GrpcCallContext ctx = GrpcCallContext.createDefault().withExtraHeaders(extraHeaders); Map<String, List<String>> moreExtraHeaders = createTestExtraHeaders("key1", "value2", "key2", "value2"); ctx = ctx.withExtraHeaders(moreExtraHeaders); Map<String, List<String>> gotExtraHeaders = ctx.getExtraHeaders(); Map<String, List<String>> expectedExtraHeaders = createTestExtraHeaders( "key1", "value1", "key1", "value2", "key1", "value2", "key2", "value2"); Truth.assertThat(gotExtraHeaders).containsExactlyEntriesIn(expectedExtraHeaders); }