• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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.testing;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.base.Strings.lenientFormat;
21 import static com.google.common.truth.Fact.simpleFact;
22 import static java.util.concurrent.TimeUnit.NANOSECONDS;
23 
24 import com.google.common.truth.ComparableSubject;
25 import com.google.common.truth.FailureMetadata;
26 import com.google.common.truth.Subject;
27 import io.grpc.Deadline;
28 import java.math.BigInteger;
29 import java.util.concurrent.TimeUnit;
30 import javax.annotation.CheckReturnValue;
31 import javax.annotation.Nullable;
32 
33 /**
34  * Propositions for {@link Deadline} subjects.
35  */
36 public final class DeadlineSubject extends ComparableSubject<DeadlineSubject, Deadline> {
37   private static final Subject.Factory<DeadlineSubject, Deadline> deadlineFactory =
38       new Factory();
39 
deadline()40   public static Subject.Factory<DeadlineSubject, Deadline> deadline() {
41     return deadlineFactory;
42   }
43 
DeadlineSubject(FailureMetadata metadata, Deadline subject)44   private DeadlineSubject(FailureMetadata metadata, Deadline subject) {
45     super(metadata, subject);
46   }
47 
48   /**
49    * Prepares for a check that the subject is deadline within the given tolerance of an
50    * expected value that will be provided in the next call in the fluent chain.
51    */
52   @CheckReturnValue
isWithin(final long delta, final TimeUnit timeUnit)53   public TolerantDeadlineComparison isWithin(final long delta, final TimeUnit timeUnit) {
54     return new TolerantDeadlineComparison() {
55       @Override
56       public void of(Deadline expected) {
57         Deadline actual = actual();
58         checkNotNull(actual, "actual value cannot be null. expected=%s", expected);
59 
60         // This is probably overkill, but easier than thinking about overflow.
61         BigInteger actualTimeRemaining = BigInteger.valueOf(actual.timeRemaining(NANOSECONDS));
62         BigInteger expectedTimeRemaining = BigInteger.valueOf(expected.timeRemaining(NANOSECONDS));
63         BigInteger deltaNanos = BigInteger.valueOf(timeUnit.toNanos(delta));
64         if (actualTimeRemaining.subtract(expectedTimeRemaining).abs().compareTo(deltaNanos) > 0) {
65           failWithoutActual(
66               simpleFact(
67                   lenientFormat(
68                       "%s and <%s> should have been within <%sns> of each other",
69                       actualAsString(), expected, deltaNanos)));
70         }
71       }
72     };
73   }
74 
75   // TODO(carl-mastrangelo):  Add a isNotWithin method once there is need for one.  Currently there
76   // is no such method since there is no code that uses it, and would lower our coverage numbers.
77 
78   /**
79    * A partially specified proposition about an approximate relationship to a {@code deadline}
80    * subject using a tolerance.
81    */
82   public abstract static class TolerantDeadlineComparison {
83 
84     private TolerantDeadlineComparison() {}
85 
86     /**
87      * Fails if the subject was expected to be within the tolerance of the given value but was not
88      * <i>or</i> if it was expected <i>not</i> to be within the tolerance but was. The expectation,
89      * subject, and tolerance are all specified earlier in the fluent call chain.
90      */
91     public abstract void of(Deadline expectedDeadline);
92 
93     /**
94      * Do not call this method.
95      *
96      * @throws UnsupportedOperationException always
97      * @deprecated {@link Object#equals(Object)} is not supported on TolerantDeadlineComparison
98      *     If you meant to compare deadlines, use {@link #of(Deadline)} instead.
99      */
100     // Deprecation used to signal visual warning in IDE for the unaware users.
101     // This method is created as a precaution and won't be removed as part of deprecation policy.
102     @Deprecated
103     @Override
104     public boolean equals(@Nullable Object o) {
105       throw new UnsupportedOperationException(
106           "If you meant to compare deadlines, use .of(Deadline) instead.");
107     }
108 
109     /**
110      * Do not call this method.
111      *
112      * @throws UnsupportedOperationException always
113      * @deprecated {@link Object#hashCode()} is not supported on TolerantDeadlineComparison
114      */
115     // Deprecation used to signal visual warning in IDE for the unaware users.
116     // This method is created as a precaution and won't be removed as part of deprecation policy.
117     @Deprecated
118     @Override
119     public int hashCode() {
120       throw new UnsupportedOperationException("Subject.hashCode() is not supported.");
121     }
122   }
123 
124   private static final class Factory implements Subject.Factory<DeadlineSubject, Deadline>  {
125     @Override
126     public DeadlineSubject createSubject(FailureMetadata metadata, Deadline that) {
127       return new DeadlineSubject(metadata, that);
128     }
129   }
130 }
131