• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc;
18 
19 import static com.google.common.truth.Truth.assertAbout;
20 import static com.google.common.truth.Truth.assertThat;
21 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
22 import static io.grpc.testing.DeadlineSubject.deadline;
23 import static java.util.concurrent.TimeUnit.MILLISECONDS;
24 import static java.util.concurrent.TimeUnit.MINUTES;
25 import static java.util.concurrent.TimeUnit.NANOSECONDS;
26 import static java.util.concurrent.TimeUnit.SECONDS;
27 import static org.junit.Assert.assertNull;
28 import static org.junit.Assert.assertSame;
29 import static org.junit.Assert.fail;
30 import static org.mockito.Mockito.mock;
31 
32 import com.google.common.base.Objects;
33 import io.grpc.ClientStreamTracer.StreamInfo;
34 import io.grpc.internal.SerializingExecutor;
35 import java.util.concurrent.Executor;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.junit.runners.JUnit4;
39 
40 /** Unit tests for {@link CallOptions}. */
41 @RunWith(JUnit4.class)
42 public class CallOptionsTest {
43   private static final CallOptions.Key<String> OPTION_1
44       = CallOptions.Key.createWithDefault("option1", "default");
45   private static final CallOptions.Key<String> OPTION_2
46       = CallOptions.Key.createWithDefault("option2", "default");
47   private final String sampleAuthority = "authority";
48   private final String sampleCompressor = "compressor";
49   private final Deadline.Ticker ticker = new FakeTicker();
50   private final Deadline sampleDeadline = Deadline.after(1, NANOSECONDS, ticker);
51   private final CallCredentials sampleCreds = mock(CallCredentials.class);
52   private final ClientStreamTracer.Factory tracerFactory1 = new FakeTracerFactory("tracerFactory1");
53   private final ClientStreamTracer.Factory tracerFactory2 = new FakeTracerFactory("tracerFactory2");
54   private final CallOptions allSet = CallOptions.DEFAULT
55       .withAuthority(sampleAuthority)
56       .withDeadline(sampleDeadline)
57       .withCallCredentials(sampleCreds)
58       .withCompression(sampleCompressor)
59       .withWaitForReady()
60       .withExecutor(directExecutor())
61       .withOption(OPTION_1, "value1")
62       .withStreamTracerFactory(tracerFactory1)
63       .withOption(OPTION_2, "value2")
64       .withStreamTracerFactory(tracerFactory2);
65 
66   @Test
defaultsAreAllNull()67   public void defaultsAreAllNull() {
68     assertThat(CallOptions.DEFAULT.getDeadline()).isNull();
69     assertThat(CallOptions.DEFAULT.getAuthority()).isNull();
70     assertThat(CallOptions.DEFAULT.getExecutor()).isNull();
71     assertThat(CallOptions.DEFAULT.getCredentials()).isNull();
72     assertThat(CallOptions.DEFAULT.getCompressor()).isNull();
73     assertThat(CallOptions.DEFAULT.isWaitForReady()).isFalse();
74     assertThat(CallOptions.DEFAULT.getStreamTracerFactories()).isEmpty();
75   }
76 
77   @Test
withAndWithoutWaitForReady()78   public void withAndWithoutWaitForReady() {
79     assertThat(CallOptions.DEFAULT.withWaitForReady().isWaitForReady()).isTrue();
80     assertThat(CallOptions.DEFAULT.withWaitForReady().withoutWaitForReady().isWaitForReady())
81         .isFalse();
82   }
83 
84   @Test
allWiths()85   public void allWiths() {
86     assertThat(allSet.getAuthority()).isSameInstanceAs(sampleAuthority);
87     assertThat(allSet.getDeadline()).isSameInstanceAs(sampleDeadline);
88     assertThat(allSet.getCredentials()).isSameInstanceAs(sampleCreds);
89     assertThat(allSet.getCompressor()).isSameInstanceAs(sampleCompressor);
90     assertThat(allSet.getExecutor()).isSameInstanceAs(directExecutor());
91     assertThat(allSet.getOption(OPTION_1)).isSameInstanceAs("value1");
92     assertThat(allSet.getOption(OPTION_2)).isSameInstanceAs("value2");
93     assertThat(allSet.isWaitForReady()).isTrue();
94   }
95 
96   @Test
noStrayModifications()97   public void noStrayModifications() {
98     assertThat(equal(allSet, allSet.withAuthority("blah").withAuthority(sampleAuthority)))
99         .isTrue();
100     assertThat(
101         equal(allSet,
102             allSet.withDeadline(Deadline.after(314, NANOSECONDS)).withDeadline(sampleDeadline)))
103         .isTrue();
104     assertThat(
105         equal(allSet,
106             allSet.withCallCredentials(mock(CallCredentials.class))
107             .withCallCredentials(sampleCreds)))
108         .isTrue();
109   }
110 
111   @Test
mutation()112   public void mutation() {
113     Deadline deadline = Deadline.after(10, SECONDS);
114     CallOptions options1 = CallOptions.DEFAULT.withDeadline(deadline);
115     assertThat(CallOptions.DEFAULT.getDeadline()).isNull();
116     assertThat(deadline).isSameInstanceAs(options1.getDeadline());
117 
118     CallOptions options2 = options1.withDeadline(null);
119     assertThat(deadline).isSameInstanceAs(options1.getDeadline());
120     assertThat(options2.getDeadline()).isNull();
121   }
122 
123   @Test
mutateExecutor()124   public void mutateExecutor() {
125     Executor executor = directExecutor();
126     CallOptions options1 = CallOptions.DEFAULT.withExecutor(executor);
127     assertThat(CallOptions.DEFAULT.getExecutor()).isNull();
128     assertThat(executor).isSameInstanceAs(options1.getExecutor());
129 
130     CallOptions options2 = options1.withExecutor(null);
131     assertThat(executor).isSameInstanceAs(options1.getExecutor());
132     assertThat(options2.getExecutor()).isNull();
133   }
134 
135   @Test
withDeadlineAfter()136   public void withDeadlineAfter() {
137     Deadline actual = CallOptions.DEFAULT.withDeadlineAfter(1, MINUTES).getDeadline();
138     Deadline expected = Deadline.after(1, MINUTES);
139 
140     assertAbout(deadline()).that(actual).isWithin(10, MILLISECONDS).of(expected);
141   }
142 
143   @Test
toStringMatches_noDeadline_default()144   public void toStringMatches_noDeadline_default() {
145     String actual = allSet
146         .withDeadline(null)
147         .withExecutor(new SerializingExecutor(directExecutor()))
148         .withCallCredentials(null)
149         .withMaxInboundMessageSize(44)
150         .withMaxOutboundMessageSize(55)
151         .toString();
152 
153     assertThat(actual).contains("deadline=null");
154     assertThat(actual).contains("authority=authority");
155     assertThat(actual).contains("callCredentials=null");
156     assertThat(actual).contains("executor=class io.grpc.internal.SerializingExecutor");
157     assertThat(actual).contains("compressorName=compressor");
158     assertThat(actual).contains("customOptions=[[option1, value1], [option2, value2]]");
159     assertThat(actual).contains("waitForReady=true");
160     assertThat(actual).contains("maxInboundMessageSize=44");
161     assertThat(actual).contains("maxOutboundMessageSize=55");
162     assertThat(actual).contains("streamTracerFactories=[tracerFactory1, tracerFactory2]");
163   }
164 
165   @Test
toStringMatches_noDeadline()166   public void toStringMatches_noDeadline() {
167     String actual = CallOptions.DEFAULT.toString();
168     assertThat(actual).contains("deadline=null");
169   }
170 
171   @Test
toStringMatches_withDeadline()172   public void toStringMatches_withDeadline() {
173     assertThat(allSet.toString()).contains("0.000000001s from now");
174   }
175 
176   @Test
withCustomOptionDefault()177   public void withCustomOptionDefault() {
178     CallOptions opts = CallOptions.DEFAULT;
179     assertThat(opts.getOption(OPTION_1)).isEqualTo("default");
180   }
181 
182   @Test
withCustomOption()183   public void withCustomOption() {
184     CallOptions opts = CallOptions.DEFAULT.withOption(OPTION_1, "v1");
185     assertThat(opts.getOption(OPTION_1)).isEqualTo("v1");
186   }
187 
188   @Test
withCustomOptionLastOneWins()189   public void withCustomOptionLastOneWins() {
190     CallOptions opts = CallOptions.DEFAULT.withOption(OPTION_1, "v1").withOption(OPTION_1, "v2");
191     assertThat(opts.getOption(OPTION_1)).isEqualTo("v2");
192   }
193 
194   @Test
withMultipleCustomOption()195   public void withMultipleCustomOption() {
196     CallOptions opts = CallOptions.DEFAULT.withOption(OPTION_1, "v1").withOption(OPTION_2, "v2");
197     assertThat(opts.getOption(OPTION_1)).isEqualTo("v1");
198     assertThat(opts.getOption(OPTION_2)).isEqualTo("v2");
199   }
200 
201   @Test
withOptionDoesNotMutateOriginal()202   public void withOptionDoesNotMutateOriginal() {
203     CallOptions defaultOpt = CallOptions.DEFAULT;
204     CallOptions opt1 = defaultOpt.withOption(OPTION_1, "v1");
205     CallOptions opt2 = opt1.withOption(OPTION_1, "v2");
206 
207     assertThat(defaultOpt.getOption(OPTION_1)).isEqualTo("default");
208     assertThat(opt1.getOption(OPTION_1)).isEqualTo("v1");
209     assertThat(opt2.getOption(OPTION_1)).isEqualTo("v2");
210   }
211 
212   @Test
withStreamTracerFactory()213   public void withStreamTracerFactory() {
214     CallOptions opts1 = CallOptions.DEFAULT.withStreamTracerFactory(tracerFactory1);
215     CallOptions opts2 = opts1.withStreamTracerFactory(tracerFactory2);
216     CallOptions opts3 = opts2.withStreamTracerFactory(tracerFactory2);
217 
218     assertThat(opts1.getStreamTracerFactories()).containsExactly(tracerFactory1);
219     assertThat(opts2.getStreamTracerFactories()).containsExactly(tracerFactory1, tracerFactory2)
220         .inOrder();
221     assertThat(opts3.getStreamTracerFactories())
222         .containsExactly(tracerFactory1, tracerFactory2, tracerFactory2).inOrder();
223 
224     try {
225       CallOptions.DEFAULT.getStreamTracerFactories().add(tracerFactory1);
226       fail("Should have thrown. The list should be unmodifiable.");
227     } catch (UnsupportedOperationException e) {
228       // Expected
229     }
230 
231     try {
232       opts2.getStreamTracerFactories().clear();
233       fail("Should have thrown. The list should be unmodifiable.");
234     } catch (UnsupportedOperationException e) {
235       // Expected
236     }
237   }
238 
239   @Test
getWaitForReady()240   public void getWaitForReady() {
241     assertNull(CallOptions.DEFAULT.getWaitForReady());
242     assertSame(CallOptions.DEFAULT.withWaitForReady().getWaitForReady(), Boolean.TRUE);
243     assertSame(CallOptions.DEFAULT.withoutWaitForReady().getWaitForReady(), Boolean.FALSE);
244   }
245 
246   // Only used in noStrayModifications()
247   // TODO(carl-mastrangelo): consider making a CallOptionsSubject for Truth.
equal(CallOptions o1, CallOptions o2)248   private static boolean equal(CallOptions o1, CallOptions o2) {
249     return Objects.equal(o1.getDeadline(), o2.getDeadline())
250         && Objects.equal(o1.getAuthority(), o2.getAuthority())
251         && Objects.equal(o1.getCredentials(), o2.getCredentials());
252   }
253 
254   private static class FakeTicker extends Deadline.Ticker {
255     private long time;
256 
257     @Override
nanoTime()258     public long nanoTime() {
259       return time;
260     }
261   }
262 
263   private static class FakeTracerFactory extends ClientStreamTracer.Factory {
264     final String name;
265 
FakeTracerFactory(String name)266     FakeTracerFactory(String name) {
267       this.name = name;
268     }
269 
270     @Override
newClientStreamTracer(StreamInfo info, Metadata headers)271     public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
272       return new ClientStreamTracer() {};
273     }
274 
275     @Override
toString()276     public String toString() {
277       return name;
278     }
279   }
280 }
281