aboutsummaryrefslogtreecommitdiff
path: root/context
diff options
context:
space:
mode:
authorEric Anderson <ejona@google.com>2017-11-21 13:20:54 -0800
committerEric Anderson <ejona@google.com>2017-11-22 17:57:46 -0800
commit2bde25d2d9de8922d3f2e05fb7bd1d9f693f5881 (patch)
tree5e5943ab1472059e56546643194db5a75f05706c /context
parent6c6538648ba518eef3230e8e2ab6f39746a8b76b (diff)
downloadgrpc-grpc-java-2bde25d2d9de8922d3f2e05fb7bd1d9f693f5881.tar.gz
testing: Remove DeadlineSubject
The class is still used internally, so we move it to context's tests for it to be reused. To avoid a circular dependency with context's tests depending on core's tests, StaticTestingClassLoader was also moved to context's tests. This is driven by a need to modernize DeadlineSubject for newer versions of Truth, but the newer versions of Truth update Guava. To avoid leaking the Guava update to all users of grpc-testing, we're removing the Subject. In our internal tests we can update the Truth dependency with less issue.
Diffstat (limited to 'context')
-rw-r--r--context/build.gradle3
-rw-r--r--context/src/test/java/io/grpc/StaticTestingClassLoader.java76
-rw-r--r--context/src/test/java/io/grpc/testing/DeadlineSubject.java129
3 files changed, 206 insertions, 2 deletions
diff --git a/context/build.gradle b/context/build.gradle
index 67c5e1d32..e13dfe46b 100644
--- a/context/build.gradle
+++ b/context/build.gradle
@@ -1,7 +1,6 @@
description = 'gRPC: Context'
dependencies {
- testCompile project(':grpc-testing')
- testCompile project(':grpc-core').sourceSets.test.output
+ testCompile libraries.jsr305
signature "org.codehaus.mojo.signature:java16:1.1@signature"
}
diff --git a/context/src/test/java/io/grpc/StaticTestingClassLoader.java b/context/src/test/java/io/grpc/StaticTestingClassLoader.java
new file mode 100644
index 000000000..590a7c0da
--- /dev/null
+++ b/context/src/test/java/io/grpc/StaticTestingClassLoader.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017, gRPC Authors All rights reserved.
+ *
+ * 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;
+
+import com.google.common.base.Preconditions;
+import com.google.common.io.ByteStreams;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.regex.Pattern;
+
+/**
+ * A class loader that can be used to repeatedly trigger static initialization of a class. A new
+ * instance is required per test.
+ */
+public final class StaticTestingClassLoader extends ClassLoader {
+ private final Pattern classesToDefine;
+
+ public StaticTestingClassLoader(ClassLoader parent, Pattern classesToDefine) {
+ super(parent);
+ this.classesToDefine = Preconditions.checkNotNull(classesToDefine, "classesToDefine");
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (!classesToDefine.matcher(name).matches()) {
+ throw new ClassNotFoundException(name);
+ }
+ InputStream is = getResourceAsStream(name.replace('.', '/') + ".class");
+ if (is == null) {
+ throw new ClassNotFoundException(name);
+ }
+ byte[] b;
+ try {
+ b = ByteStreams.toByteArray(is);
+ } catch (IOException ex) {
+ throw new ClassNotFoundException(name, ex);
+ }
+ return defineClass(name, b, 0, b.length);
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ // Reverse normal loading order; check this class loader before its parent
+ synchronized (getClassLoadingLock(name)) {
+ Class<?> klass = findLoadedClass(name);
+ if (klass == null) {
+ try {
+ klass = findClass(name);
+ } catch (ClassNotFoundException e) {
+ // This ClassLoader doesn't know a class with that name; that's part of normal operation
+ }
+ }
+ if (klass == null) {
+ klass = super.loadClass(name, false);
+ }
+ if (resolve) {
+ resolveClass(klass);
+ }
+ return klass;
+ }
+ }
+}
diff --git a/context/src/test/java/io/grpc/testing/DeadlineSubject.java b/context/src/test/java/io/grpc/testing/DeadlineSubject.java
new file mode 100644
index 000000000..3d425a9dc
--- /dev/null
+++ b/context/src/test/java/io/grpc/testing/DeadlineSubject.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2016, gRPC Authors All rights reserved.
+ *
+ * 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 java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import com.google.common.truth.ComparableSubject;
+import com.google.common.truth.FailureStrategy;
+import com.google.common.truth.SubjectFactory;
+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 SubjectFactory<DeadlineSubject, Deadline> deadlineFactory =
+ new DeadlineSubjectFactory();
+
+ public static SubjectFactory<DeadlineSubject, Deadline> deadline() {
+ return deadlineFactory;
+ }
+
+ private DeadlineSubject(FailureStrategy failureStrategy, Deadline subject) {
+ super(failureStrategy, 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 = getSubject();
+ 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) {
+ failWithRawMessage(
+ "%s and <%s> should have been within <%sns> of each other",
+ getDisplaySubject(),
+ expected,
+ 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 DeadlineSubjectFactory
+ extends SubjectFactory<DeadlineSubject, Deadline> {
+ @Override
+ public DeadlineSubject getSubject(FailureStrategy fs, Deadline that) {
+ return new DeadlineSubject(fs, that);
+ }
+ }
+}