diff options
Diffstat (limited to 'src/test/java/com')
5 files changed, 218 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD index a5944fac08..33748a634f 100644 --- a/src/test/java/com/google/devtools/build/lib/BUILD +++ b/src/test/java/com/google/devtools/build/lib/BUILD @@ -62,6 +62,7 @@ filegroup( "//src/test/java/com/google/devtools/build/lib/skylarkdebug/server:srcs", "//src/test/java/com/google/devtools/build/lib/skylarkinterface/processor:srcs", "//src/test/java/com/google/devtools/build/lib/unsafe:srcs", + "//src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit:srcs", ], visibility = ["//src:__pkg__"], ) @@ -1559,6 +1560,7 @@ java_test( "//third_party:guava", "//third_party:jsr305", "//third_party:junit4", + "//third_party:truth", ], ) diff --git a/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/BUILD b/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/BUILD new file mode 100644 index 0000000000..1f81853fec --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/BUILD @@ -0,0 +1,29 @@ +java_test( + name = "TimeoutTestWatcherTest", + srcs = [ + "TimeoutTestWatcher.java", + "TimeoutTestWatcherBaseTest.java", + "TimeoutTestWatcherTest.java", + ], + visibility = ["//visibility:public"], + deps = [ + "//third_party:guava", + "//third_party:junit4", + "//third_party:truth", + ], +) + +filegroup( + name = "srcs", + srcs = glob(["**/*"]), + visibility = ["//src/test/java/com/google/devtools/build/lib:__pkg__"], +) + +java_library( + name = "timeout_watcher", + srcs = ["TimeoutTestWatcher.java"], + visibility = ["//visibility:public"], + deps = [ + "//third_party:junit4", + ], +) diff --git a/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcher.java b/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcher.java new file mode 100644 index 0000000000..c0e87f7093 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcher.java @@ -0,0 +1,94 @@ +// Copyright 2018 The Bazel 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 com.google.devtools.build.lib.integration.blackbox.framework.junit; + +import java.util.concurrent.TimeoutException; +import org.junit.rules.TestWatcher; +import org.junit.rules.Timeout; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Test watcher, which sets a timeout for the JUnit test and allows to execute some action on + * timeout. Uses JUnit's org.junit.rules.Timeout rule to set up a timeout; catches timeout exception + * thrown fromTimeout rule, calls the {@link onTimeout} method, and re-throws the exception. + * + * <p>Useful to dump test state information before failing on timeout. + */ +public abstract class TimeoutTestWatcher extends TestWatcher { + private String name; + + protected abstract long getTimeoutMillis(); + + protected abstract boolean onTimeout(); + + @Override + protected void starting(Description description) { + name = description.getMethodName(); + } + + @Override + protected void finished(Description description) { + name = null; + } + + public String getName() { + return name; + } + + @Override + public Statement apply(Statement base, Description description) { + // we are using exception wrapping, because unfortunately JUnit's Timeout throws + // java.util.Exception on timeout, which is hard to distinguish from other cases + Statement wrapper = + new Statement() { + @Override + public void evaluate() throws Throwable { + try { + base.evaluate(); + } catch (Throwable th) { + throw new ExceptionWrapper(th); + } + } + }; + + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + new Timeout((int) getTimeoutMillis()).apply(wrapper, description).evaluate(); + } catch (ExceptionWrapper wrapper) { + // original test exception + throw wrapper.getCause(); + } catch (Exception e) { + // timeout exception + if (!onTimeout()) { + throw new TimeoutException(e.getMessage()); + } + } + } + }; + } + + /** + * Exception wrapper wrap-and-caught any exception from the test; this guarantees that we + * differentiate timeout exception thrown just as java.util.Exception from the test exceptions + */ + private static class ExceptionWrapper extends Throwable { + ExceptionWrapper(Throwable cause) { + super(cause); + } + } +} diff --git a/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcherBaseTest.java b/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcherBaseTest.java new file mode 100644 index 0000000000..9c61301904 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcherBaseTest.java @@ -0,0 +1,42 @@ +// Copyright 2018 The Bazel 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 com.google.devtools.build.lib.integration.blackbox.framework.junit; + +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Base test class for testing {@link TimeoutTestWatcher}; it is a base class since we want to + * imitate the usage of test watcher from the base class. + */ +@RunWith(JUnit4.class) +public abstract class TimeoutTestWatcherBaseTest { + boolean timeoutCaught = false; + + @Rule + public TimeoutTestWatcher testWatcher = + new TimeoutTestWatcher() { + @Override + protected long getTimeoutMillis() { + return 100; + } + + @Override + protected boolean onTimeout() { + return timeoutCaught = true; + } + }; +} diff --git a/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcherTest.java b/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcherTest.java new file mode 100644 index 0000000000..c5f41bfc99 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/integration/blackbox/framework/junit/TimeoutTestWatcherTest.java @@ -0,0 +1,51 @@ +// Copyright 2018 The Bazel 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 com.google.devtools.build.lib.integration.blackbox.framework.junit; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Test for {@link TimeoutTestWatcher}. Tests both that the timeout was intercepted, and the + * assertion from the test was not blocked. + */ +@RunWith(JUnit4.class) +public class TimeoutTestWatcherTest extends TimeoutTestWatcherBaseTest { + @After + public void tearDown() { + if ("testTimeoutCaught".equals(testWatcher.getName())) { + assertThat(timeoutCaught).isTrue(); + } + } + + /** Test that timeout handler is called */ + @Test + public void testTimeoutCaught() throws Exception { + for (int i = 0; i < 10; i++) { + Thread.sleep(500); + } + } + + /** Test that normal test failures are not blocked */ + @Test(expected = AssertionError.class) + public void testFailure() { + Assert.fail(); + } +} |