blob: b443f3c088236ce802b66d7376cd9c0683763f72 [file] [log] [blame]
/*
* Copyright 2016 The gRPC Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc.testing;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.truth.Fact.fact;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import com.google.common.truth.ComparableSubject;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.Subject;
import io.grpc.Deadline;
import java.math.BigInteger;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Propositions for {@link Deadline} subjects.
*/
public final class DeadlineSubject extends ComparableSubject<DeadlineSubject, Deadline> {
private static final Subject.Factory<DeadlineSubject, Deadline> deadlineFactory =
new Factory();
public static Subject.Factory<DeadlineSubject, Deadline> deadline() {
return deadlineFactory;
}
private final Deadline actual;
private DeadlineSubject(FailureMetadata metadata, Deadline subject) {
super(metadata, subject);
this.actual = subject;
}
/**
* Prepares for a check that the subject is deadline within the given tolerance of an
* expected value that will be provided in the next call in the fluent chain.
*/
@CheckReturnValue
public TolerantDeadlineComparison isWithin(final long delta, final TimeUnit timeUnit) {
return new TolerantDeadlineComparison() {
@Override
public void of(Deadline expected) {
Deadline actual = DeadlineSubject.this.actual;
checkNotNull(actual, "actual value cannot be null. expected=%s", expected);
// This is probably overkill, but easier than thinking about overflow.
BigInteger actualTimeRemaining = BigInteger.valueOf(actual.timeRemaining(NANOSECONDS));
BigInteger expectedTimeRemaining = BigInteger.valueOf(expected.timeRemaining(NANOSECONDS));
BigInteger deltaNanos = BigInteger.valueOf(timeUnit.toNanos(delta));
if (actualTimeRemaining.subtract(expectedTimeRemaining).abs().compareTo(deltaNanos) > 0) {
failWithoutActual(
fact("expected", expected),
fact("but was", actual),
fact("outside tolerance in ns", deltaNanos));
}
}
};
}
// TODO(carl-mastrangelo): Add a isNotWithin method once there is need for one. Currently there
// is no such method since there is no code that uses it, and would lower our coverage numbers.
/**
* A partially specified proposition about an approximate relationship to a {@code deadline}
* subject using a tolerance.
*/
public abstract static class TolerantDeadlineComparison {
private TolerantDeadlineComparison() {}
/**
* Fails if the subject was expected to be within the tolerance of the given value but was not
* <i>or</i> if it was expected <i>not</i> to be within the tolerance but was. The expectation,
* subject, and tolerance are all specified earlier in the fluent call chain.
*/
public abstract void of(Deadline expectedDeadline);
/**
* Do not call this method.
*
* @throws UnsupportedOperationException always
* @deprecated {@link Object#equals(Object)} is not supported on TolerantDeadlineComparison
* If you meant to compare deadlines, use {@link #of(Deadline)} instead.
*/
// Deprecation used to signal visual warning in IDE for the unaware users.
// This method is created as a precaution and won't be removed as part of deprecation policy.
@Deprecated
@Override
public boolean equals(@Nullable Object o) {
throw new UnsupportedOperationException(
"If you meant to compare deadlines, use .of(Deadline) instead.");
}
/**
* Do not call this method.
*
* @throws UnsupportedOperationException always
* @deprecated {@link Object#hashCode()} is not supported on TolerantDeadlineComparison
*/
// Deprecation used to signal visual warning in IDE for the unaware users.
// This method is created as a precaution and won't be removed as part of deprecation policy.
@Deprecated
@Override
public int hashCode() {
throw new UnsupportedOperationException("Subject.hashCode() is not supported.");
}
}
private static final class Factory implements Subject.Factory<DeadlineSubject, Deadline> {
@Override
public DeadlineSubject createSubject(FailureMetadata metadata, Deadline that) {
return new DeadlineSubject(metadata, that);
}
}
}