Return-Path: X-Original-To: apmail-geode-commits-archive@minotaur.apache.org Delivered-To: apmail-geode-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 043391858B for ; Thu, 21 Jan 2016 19:09:18 +0000 (UTC) Received: (qmail 35419 invoked by uid 500); 21 Jan 2016 19:09:17 -0000 Delivered-To: apmail-geode-commits-archive@geode.apache.org Received: (qmail 35382 invoked by uid 500); 21 Jan 2016 19:09:17 -0000 Mailing-List: contact commits-help@geode.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.incubator.apache.org Delivered-To: mailing list commits@geode.incubator.apache.org Received: (qmail 35373 invoked by uid 99); 21 Jan 2016 19:09:17 -0000 Received: from Unknown (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 21 Jan 2016 19:09:17 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id 3BBA8C0E80 for ; Thu, 21 Jan 2016 19:09:17 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.227 X-Spam-Level: * X-Spam-Status: No, score=1.227 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.554, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-us-west.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id iLeU-tZjYKfJ for ; Thu, 21 Jan 2016 19:08:57 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-west.apache.org (ASF Mail Server at mx1-us-west.apache.org) with SMTP id 2931E20F88 for ; Thu, 21 Jan 2016 19:08:48 +0000 (UTC) Received: (qmail 33328 invoked by uid 99); 21 Jan 2016 19:08:47 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 21 Jan 2016 19:08:47 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id BDD11E38D3; Thu, 21 Jan 2016 19:08:47 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: klund@apache.org To: commits@geode.incubator.apache.org Date: Thu, 21 Jan 2016 19:09:04 -0000 Message-Id: <9142b8f3a50b4216bb48b73f980f89ab@git.apache.org> In-Reply-To: <4a1a3f20ce0648d6aaed99edeb5f3034@git.apache.org> References: <4a1a3f20ce0648d6aaed99edeb5f3034@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [18/19] incubator-geode git commit: GEODE-772: Add custom annotations and rules for tests GEODE-772: Add custom annotations and rules for tests Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/1be4f932 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/1be4f932 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/1be4f932 Branch: refs/heads/feature/GEODE-715 Commit: 1be4f932a80f53c0588b49227e7daa518eb389c5 Parents: c0c64de Author: Kirk Lund Authored: Wed Jan 20 16:30:20 2016 -0800 Committer: Kirk Lund Committed: Thu Jan 21 10:48:44 2016 -0800 ---------------------------------------------------------------------- .../gemfire/test/junit/ConditionalIgnore.java | 49 +++ .../gemfire/test/junit/IgnoreCondition.java | 32 ++ .../gemfire/test/junit/IgnoreUntil.java | 49 +++ .../com/gemstone/gemfire/test/junit/Repeat.java | 43 +++ .../com/gemstone/gemfire/test/junit/Retry.java | 38 +++ .../test/junit/rules/ConditionalIgnoreRule.java | 123 ++++++++ .../test/junit/rules/ExpectedTimeoutRule.java | 180 +++++++++++ .../test/junit/rules/IgnoreUntilRule.java | 123 ++++++++ .../gemfire/test/junit/rules/RepeatRule.java | 81 +++++ .../gemfire/test/junit/rules/RetryRule.java | 181 +++++++++++ .../rules/SerializableExternalResource.java | 107 +++++++ .../test/junit/rules/SerializableRuleChain.java | 119 ++++++++ .../rules/SerializableTemporaryFolder.java | 70 +++++ .../test/junit/rules/SerializableTestName.java | 54 ++++ .../test/junit/rules/SerializableTestRule.java | 33 ++ .../junit/rules/SerializableTestWatcher.java | 29 ++ .../test/junit/rules/SerializableTimeout.java | 119 ++++++++ .../examples/RepeatingTestCasesExampleTest.java | 94 ++++++ .../rules/examples/RetryRuleExampleTest.java | 43 +++ .../rules/tests/ExpectedTimeoutRuleTest.java | 214 +++++++++++++ .../junit/rules/tests/IgnoreUntilRuleTest.java | 121 ++++++++ .../junit/rules/tests/JUnitRuleTestSuite.java | 33 ++ .../test/junit/rules/tests/RepeatRuleTest.java | 304 +++++++++++++++++++ .../tests/RetryRuleGlobalWithErrorTest.java | 250 +++++++++++++++ .../tests/RetryRuleGlobalWithExceptionTest.java | 254 ++++++++++++++++ .../tests/RetryRuleLocalWithErrorTest.java | 207 +++++++++++++ .../tests/RetryRuleLocalWithExceptionTest.java | 213 +++++++++++++ .../junit/rules/tests/RuleAndClassRuleTest.java | 138 +++++++++ .../test/junit/rules/tests/TestRunner.java | 37 +++ .../junit/support/DefaultIgnoreCondition.java | 57 ++++ .../IgnoreConditionEvaluationException.java | 43 +++ 31 files changed, 3438 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/ConditionalIgnore.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/ConditionalIgnore.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/ConditionalIgnore.java new file mode 100755 index 0000000..b409cb1 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/ConditionalIgnore.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.gemstone.gemfire.test.junit.support.DefaultIgnoreCondition; + +/** + * The ConditionalIgnore class is a Java Annotation used to annotated a test suite class test case method in order to + * conditionally ignore the test case for a fixed amount of time, or based on a predetermined condition provided by + * the IgnoreCondition interface. + * + * @author John Blum + * @see java.lang.annotation.Annotation + * @see com.gemstone.gemfire.test.junit.IgnoreCondition + * @see com.gemstone.gemfire.test.junit.support.DefaultIgnoreCondition + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@SuppressWarnings("unused") +public @interface ConditionalIgnore { + + Class condition() default DefaultIgnoreCondition.class; + + String until() default "1970-01-01"; + + String value() default ""; + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreCondition.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreCondition.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreCondition.java new file mode 100755 index 0000000..0caa959 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreCondition.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit; + +import org.junit.runner.Description; + +/** + * The IgnoreCondition class... + * + * @author John Blum + * @see org.junit.runner.Description + */ +@SuppressWarnings("unused") +public interface IgnoreCondition { + + boolean evaluate(Description testCaseDescription); + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreUntil.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreUntil.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreUntil.java new file mode 100755 index 0000000..5910d10 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreUntil.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.gemstone.gemfire.test.junit.support.DefaultIgnoreCondition; + +/** + * The IgnoreUntil class is a Java Annotation used to annotated a test suite class test case method in order to + * conditionally ignore the test case for a fixed amount of time, or based on a predetermined condition provided by + * the IgnoreCondition interface. + * + * @author John Blum + * @see java.lang.annotation.Annotation + * @see com.gemstone.gemfire.test.junit.IgnoreCondition + * @see com.gemstone.gemfire.test.junit.support.DefaultIgnoreCondition + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@SuppressWarnings("unused") +public @interface IgnoreUntil { + + Class condition() default DefaultIgnoreCondition.class; + + String until() default "1970-01-01"; + + String value() default ""; + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Repeat.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Repeat.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Repeat.java new file mode 100755 index 0000000..5cfa321 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Repeat.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The Repeat class is a Java Annotation enabling an annotated test suite class test case method to be repeated + * a specified number of iterations. + * + * @author John Blum + * @see java.lang.annotation.Annotation + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +@SuppressWarnings("unused") +public @interface Repeat { + + public static int DEFAULT = 1; + + int value() default DEFAULT; + + String property() default ""; +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Retry.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Retry.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Retry.java new file mode 100755 index 0000000..65f3cf6 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Retry.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Java Annotation used to annotate a test suite class test case method in order to + * retry it in case of failure up to the specified maximum attempts. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface Retry { + + public static int DEFAULT = 1; + + int value() default DEFAULT; + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ConditionalIgnoreRule.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ConditionalIgnoreRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ConditionalIgnoreRule.java new file mode 100755 index 0000000..80898b5 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ConditionalIgnoreRule.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.io.Serializable; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +import org.junit.AssumptionViolatedException; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import com.gemstone.gemfire.test.junit.ConditionalIgnore; +import com.gemstone.gemfire.test.junit.IgnoreCondition; +import com.gemstone.gemfire.test.junit.support.IgnoreConditionEvaluationException; + +/** + * The ConditionalIgnoreRule class... + * + * @author John Blum + * @see org.junit.rules.TestRule + * @see org.junit.runner.Description + * @see org.junit.runners.model.Statement + * @see com.gemstone.gemfire.test.junit.ConditionalIgnore + * @see com.gemstone.gemfire.test.junit.IgnoreCondition + */ +@SuppressWarnings({ "serial", "unused" }) +public class ConditionalIgnoreRule implements TestRule, Serializable { + + protected static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd"; + protected static final String DEFAULT_MESSAGE = "Ignoring test case (%1$s) of test class (%2$s)!"; + + protected static final DateFormat DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_PATTERN); + + @Override + public Statement apply(final Statement base, final Description description) { + return new Statement() { + @Override public void evaluate() throws Throwable { + ConditionalIgnoreRule.this.evaluate(base, description); + } + }; + } + + public final void evaluate(Statement statement, Description description) throws Throwable { + throwOnIgnoreTest(statement, description).evaluate(); + } + + protected Statement throwOnIgnoreTest(Statement statement, Description description) { + if (isTest(description)) { + boolean ignoreTest = false; + String message = ""; + + ConditionalIgnore testCaseAnnotation = description.getAnnotation(ConditionalIgnore.class); + + if (testCaseAnnotation != null) { + ignoreTest = evaluate(testCaseAnnotation, description); + message = testCaseAnnotation.value(); + } + else if (description.getTestClass().isAnnotationPresent(ConditionalIgnore.class)) { + ConditionalIgnore testClassAnnotation = description.getTestClass().getAnnotation(ConditionalIgnore.class); + + ignoreTest = evaluate(testClassAnnotation, description); + message = testClassAnnotation.value(); + } + + if (ignoreTest) { + throw new AssumptionViolatedException(format(message, description)); + } + } + + return statement; + } + + protected boolean isTest(final Description description) { + return (description.isSuite() || description.isTest()); + } + + protected String format(String message, Description description) { + message = (!message.isEmpty() ? message : DEFAULT_MESSAGE); + return String.format(message, description.getMethodName(), description.getClassName()); + } + + protected boolean evaluate(ConditionalIgnore conditionalIgnoreAnnotation, Description description) { + return (evaluateCondition(conditionalIgnoreAnnotation.condition(), description) + || evaluateUntil(conditionalIgnoreAnnotation.until())); + } + + protected boolean evaluateCondition(Class ignoreConditionType, Description description) { + try { + return ignoreConditionType.newInstance().evaluate(description); + } + catch (Exception e) { + throw new IgnoreConditionEvaluationException(String.format("failed to evaluate IgnoreCondition: %1$s", + ignoreConditionType.getName()), e); + } + } + + protected boolean evaluateUntil(String timestamp) { + try { + return DATE_FORMAT.parse(timestamp).after(Calendar.getInstance().getTime()); + } + catch (ParseException e) { + return false; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutRule.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutRule.java new file mode 100755 index 0000000..7b6d345 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutRule.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import static org.junit.Assert.assertThat; + +import java.util.concurrent.TimeUnit; + +import org.hamcrest.Matcher; +import org.junit.rules.ExpectedException; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Expect an Exception within a specified timeout. + * + * @author Kirk Lund + * @since 8.2 + */ +public class ExpectedTimeoutRule implements TestRule { + + /** + * @return a Rule that expects no timeout (identical to behavior without this Rule) + */ + public static ExpectedTimeoutRule none() { + return new ExpectedTimeoutRule(); + } + + private ExpectedException delegate; + private boolean expectsThrowable; + private long minDuration; + private long maxDuration; + private TimeUnit timeUnit; + + private ExpectedTimeoutRule() { + this.delegate = ExpectedException.none(); + } + + public ExpectedTimeoutRule expectMinimumDuration(final long minDuration) { + this.minDuration = minDuration; + return this; + } + public ExpectedTimeoutRule expectMaximumDuration(final long maxDuration) { + this.maxDuration = maxDuration; + return this; + } + public ExpectedTimeoutRule expectTimeUnit(final TimeUnit timeUnit) { + this.timeUnit = timeUnit; + return this; + } + + public ExpectedTimeoutRule handleAssertionErrors() { + this.delegate.handleAssertionErrors(); + return this; + } + + public ExpectedTimeoutRule handleAssumptionViolatedExceptions() { + this.delegate.handleAssumptionViolatedExceptions(); + return this; + } + + /** + * Adds {@code matcher} to the list of requirements for any thrown + * exception. + */ + public void expect(final Matcher matcher) { + this.delegate.expect(matcher); + } + + /** + * Adds to the list of requirements for any thrown exception that it should + * be an instance of {@code type} + */ + public void expect(final Class type) { + this.delegate.expect(type); + this.expectsThrowable = true; + } + + /** + * Adds to the list of requirements for any thrown exception that it should + * contain string {@code substring} + */ + public void expectMessage(final String substring) { + this.delegate.expectMessage(substring); + } + + /** + * Adds {@code matcher} to the list of requirements for the message returned + * from any thrown exception. + */ + public void expectMessage(final Matcher matcher) { + this.delegate.expectMessage(matcher); + } + + /** + * Adds {@code matcher} to the list of requirements for the cause of + * any thrown exception. + */ + public void expectCause(final Matcher expectedCause) { + this.delegate.expectCause(expectedCause); + } + + public boolean expectsTimeout() { + return minDuration > 0 || maxDuration > 0; + } + + public boolean expectsThrowable() { + return expectsThrowable = true; + } + + @Override + public Statement apply(final Statement base, final Description description) { + Statement next = delegate.apply(base, description); + return new ExpectedTimeoutStatement(next); + } + + private void handleTime(final Long duration) { + if (expectsTimeout()) { + assertThat(timeUnit.convert(duration, TimeUnit.NANOSECONDS), new TimeMatcher(timeUnit, minDuration, maxDuration)); + } + } + + private static class TimeMatcher extends org.hamcrest.TypeSafeMatcher { + + private final TimeUnit timeUnit; + private final long minDuration; + private final long maxDuration; + + public TimeMatcher(final TimeUnit timeUnit, final long minDuration, final long maxDuration) { + this.timeUnit = timeUnit; + this.minDuration = minDuration; + this.maxDuration = maxDuration; + } + + @Override + public boolean matchesSafely(final Long duration) { + return duration >= this.minDuration && duration <= this.maxDuration; + } + + @Override + public void describeTo(final org.hamcrest.Description description) { + description.appendText("expects duration to be greater than or equal to ") + .appendValue(this.minDuration) + .appendText(" and less than or equal to ") + .appendValue(this.maxDuration) + .appendText(" ") + .appendValue(this.timeUnit); + } + } + + private class ExpectedTimeoutStatement extends Statement { + private final Statement next; + + public ExpectedTimeoutStatement(final Statement base) { + next = base; + } + + @Override + public void evaluate() throws Throwable { + long start = System.nanoTime(); + next.evaluate(); + handleTime(System.nanoTime() - start); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/IgnoreUntilRule.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/IgnoreUntilRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/IgnoreUntilRule.java new file mode 100755 index 0000000..bf4ec3f --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/IgnoreUntilRule.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.io.Serializable; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +import org.junit.AssumptionViolatedException; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import com.gemstone.gemfire.test.junit.IgnoreUntil; +import com.gemstone.gemfire.test.junit.IgnoreCondition; +import com.gemstone.gemfire.test.junit.support.IgnoreConditionEvaluationException; + +/** + * The IgnoreUntilRule class... + * + * @author John Blum + * @see org.junit.rules.TestRule + * @see org.junit.runner.Description + * @see org.junit.runners.model.Statement + * @see com.gemstone.gemfire.test.junit.IgnoreUntil + * @see com.gemstone.gemfire.test.junit.IgnoreCondition + */ +@SuppressWarnings({ "serial", "unused" }) +public class IgnoreUntilRule implements TestRule, Serializable { + + protected static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd"; + protected static final String DEFAULT_MESSAGE = "Ignoring test case (%1$s) of test class (%2$s)!"; + + protected static final DateFormat DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_PATTERN); + + @Override + public Statement apply(final Statement base, final Description description) { + return new Statement() { + @Override public void evaluate() throws Throwable { + IgnoreUntilRule.this.evaluate(base, description); + } + }; + } + + public final void evaluate(Statement statement, Description description) throws Throwable { + throwOnIgnoreTest(statement, description).evaluate(); + } + + protected Statement throwOnIgnoreTest(Statement statement, Description description) { + if (isTest(description)) { + boolean ignoreTest = false; + String message = ""; + + IgnoreUntil testCaseAnnotation = description.getAnnotation(IgnoreUntil.class); + + if (testCaseAnnotation != null) { + ignoreTest = evaluate(testCaseAnnotation, description); + message = testCaseAnnotation.value(); + } + else if (description.getTestClass().isAnnotationPresent(IgnoreUntil.class)) { + IgnoreUntil testClassAnnotation = description.getTestClass().getAnnotation(IgnoreUntil.class); + + ignoreTest = evaluate(testClassAnnotation, description); + message = testClassAnnotation.value(); + } + + if (ignoreTest) { + throw new AssumptionViolatedException(format(message, description)); + } + } + + return statement; + } + + protected boolean isTest(final Description description) { + return (description.isSuite() || description.isTest()); + } + + protected String format(String message, Description description) { + message = (!message.isEmpty() ? message : DEFAULT_MESSAGE); + return String.format(message, description.getMethodName(), description.getClassName()); + } + + protected boolean evaluate(IgnoreUntil conditionalIgnoreAnnotation, Description description) { + return (evaluateCondition(conditionalIgnoreAnnotation.condition(), description) + || evaluateUntil(conditionalIgnoreAnnotation.until())); + } + + protected boolean evaluateCondition(Class ignoreConditionType, Description description) { + try { + return ignoreConditionType.newInstance().evaluate(description); + } + catch (Exception e) { + throw new IgnoreConditionEvaluationException(String.format("failed to evaluate IgnoreCondition: %1$s", + ignoreConditionType.getName()), e); + } + } + + protected boolean evaluateUntil(String timestamp) { + try { + return DATE_FORMAT.parse(timestamp).after(Calendar.getInstance().getTime()); + } + catch (ParseException e) { + return false; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RepeatRule.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RepeatRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RepeatRule.java new file mode 100755 index 0000000..7bfe538 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RepeatRule.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.io.Serializable; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import com.gemstone.gemfire.test.junit.Repeat; + +/** + * The RepeatRule class is a JUnit TestRule that enables an appropriately @Repeat annotated test case method + * to be repeated a specified number of times. + * + * @author John Blum + * @see org.junit.rules.TestRule + * @see org.junit.runner.Description + * @see org.junit.runners.model.Statement + */ +@SuppressWarnings({ "serial", "unused" }) +public class RepeatRule implements TestRule, Serializable { + + protected static final int DEFAULT_REPETITIONS = 1; + + @Override + public Statement apply(final Statement statement, final Description description) { + return new Statement() { + @Override public void evaluate() throws Throwable { + RepeatRule.this.evaluate(statement, description); + } + }; + } + + protected void evaluate(final Statement statement, final Description description) throws Throwable { + if (isTest(description)) { + Repeat repeat = description.getAnnotation(Repeat.class); + + for (int count = 0, repetitions = getRepetitions(repeat); count < repetitions; count++) { + statement.evaluate(); + } + } + } + + private int getRepetitions(final Repeat repeat) { + int repetitions = DEFAULT_REPETITIONS; + + if (repeat != null) { + if (!"".equals(repeat.property())) { + repetitions = Integer.getInteger(repeat.property(), DEFAULT_REPETITIONS); + } else { + repetitions = repeat.value(); + } + } + + if (repetitions < 1) { + throw new IllegalArgumentException("Repeat value must be a positive integer"); + } + + return repetitions; + } + + private boolean isTest(final Description description) { + return (description.isSuite() || description.isTest()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RetryRule.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RetryRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RetryRule.java new file mode 100755 index 0000000..4a26d5e --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RetryRule.java @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.io.Serializable; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import com.gemstone.gemfire.test.junit.Retry; + +/** + * JUnit Rule that enables retrying a failed test up to a maximum number of retries. + *

+ * RetryRule can be used globally for all tests in a test case by specifying a + * retryCount when instantiating it: + *
+ * @Rule
+ * public final RetryRule retryRule = new RetryRule(3);
+ * 
+ * @Test
+ * public void shouldBeRetriedUntilPasses() {
+ *   ...
+ * }
+ * 
+ *

+ * The above will result in 3 retries for every test in the test case. + *

+ * RetryRule can be used locally for specific tests by annotating the test + * method with @Rule and specifying a retryCount for that test: + *
+ * @Rule
+ * public final RetryRule retryRule = new RetryRule();
+ * 
+ * @Test
+ * @Retry(3)
+ * public void shouldBeRetriedUntilPasses() {
+ *   ...
+ * }
+ * 
+ *

+ * This version of RetryRule will retry a test that fails because of any kind + * of Throwable. + */ +@SuppressWarnings("serial") +public class RetryRule implements TestRule, Serializable { + + /** + * Enables printing of failures to System.err even if test passes on a retry + */ + private static final boolean LOG = false; + + private final AbstractRetryRule implementation; + + public RetryRule() { + this.implementation = new LocalRetryRule(); + } + + public RetryRule(final int retryCount) { + this.implementation = new GlobalRetryRule(retryCount); + } + + @Override + public Statement apply(final Statement base, final Description description) { + return this.implementation.apply(base, description); + } + + protected abstract class AbstractRetryRule implements TestRule { + protected AbstractRetryRule() { + } + protected void evaluate(final Statement base, final Description description, final int retryCount) throws Throwable { + if (retryCount == 0) { + + } + Throwable caughtThrowable = null; + + for (int count = 0; count < retryCount; count++) { + try { + base.evaluate(); + return; + } catch (Throwable t) { + caughtThrowable = t; + debug(description.getDisplayName() + ": run " + (count + 1) + " failed"); + } + } + + debug(description.getDisplayName() + ": giving up after " + retryCount + " failures"); + throw caughtThrowable; + } + private void debug(final String message) { + if (LOG) { + System.err.println(message); + } + } + } + + /** + * Implementation of RetryRule for all test methods in a test case + */ + protected class GlobalRetryRule extends AbstractRetryRule { + + private final int retryCount; + + protected GlobalRetryRule(final int retryCount) { + if (retryCount < 1) { + throw new IllegalArgumentException("Retry count must be greater than zero"); + } + this.retryCount = retryCount; + } + + @Override + public Statement apply(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + GlobalRetryRule.this.evaluatePerCase(base, description); + } + }; + } + + protected void evaluatePerCase(final Statement base, final Description description) throws Throwable { + evaluate(base, description, this.retryCount); + } + } + + /** + * Implementation of RetryRule for test methods annotated with Retry + */ + protected class LocalRetryRule extends AbstractRetryRule { + + protected LocalRetryRule() { + } + + @Override + public Statement apply(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + LocalRetryRule.this.evaluatePerTest(base, description); + } + }; + } + + protected void evaluatePerTest(final Statement base, final Description description) throws Throwable { + if (isTest(description)) { + Retry retry = description.getAnnotation(Retry.class); + int retryCount = getRetryCount(retry); + evaluate(base, description, retryCount); + } + } + + private int getRetryCount(final Retry retry) { + int retryCount = Retry.DEFAULT; + + if (retry != null) { + retryCount = retry.value(); + } + + return retryCount; + } + + private boolean isTest(final Description description) { + return (description.isSuite() || description.isTest()); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java new file mode 100755 index 0000000..37d8eb5 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Serializable version of ExternalResource JUnit Rule. JUnit lifecycle is not + * executed in remote JVMs. The after() callback has a throws-clause + * that matches before(). + * + * Implementation copied from org.junit.rules.ExternalResource. + * + * @author Kirk Lund + */ +@SuppressWarnings("serial") +public abstract class SerializableExternalResource implements SerializableTestRule { + + @Override + public Statement apply(final Statement base, final Description description) { + if (description.isTest()) { + return statement(base); + } else if (description.isSuite()) { + return statementClass(base); + } + return base; + } + + private Statement statement(final Statement base) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + before(); + try { + base.evaluate(); + } finally { + after(); + } + } + }; + } + + private Statement statementClass(final Statement base) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + beforeClass(); + try { + base.evaluate(); + } finally { + afterClass(); + } + } + }; + } + + /** + * Override to set up your specific external resource. + * + * @throws Throwable if setup fails (which will disable {@code after} + */ + protected void before() throws Throwable { + // do nothing + } + + /** + * Override to tear down your specific external resource. + * + * @throws Throwable if teardown fails (which will disable {@code after} + */ + protected void after() throws Throwable { + // do nothing + } + + /** + * Override to set up your specific external resource. + * + * @throws Throwable if setup fails (which will disable {@code after} + */ + protected void beforeClass() throws Throwable { + // do nothing + } + + /** + * Override to tear down your specific external resource. + * + * @throws Throwable if teardown fails (which will disable {@code after} + */ + protected void afterClass() throws Throwable { + // do nothing + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableRuleChain.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableRuleChain.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableRuleChain.java new file mode 100755 index 0000000..936345e --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableRuleChain.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Serializable version of TemporaryFolder JUnit Rule. JUnit lifecycle is not + * executed in remote JVMs. + * + * Implementation copied from org.junit.rules.RuleChain. + * + * The SerializableRuleChain rule allows ordering of TestRules. You create a + * {@code RuleChain} with {@link #outerRule(TestRule)} and subsequent calls of + * {@link #around(TestRule)}: + * + *
+ * public static class UseRuleChain {
+ *  @Rule
+ *  public RuleChain chain= RuleChain
+ *                         .outerRule(new LoggingRule("outer rule")
+ *                         .around(new LoggingRule("middle rule")
+ *                         .around(new LoggingRule("inner rule");
+ *
+ *  @Test
+ *  public void example() {
+ *    assertTrue(true);
+ *     }
+ * }
+ * 
+ * + * writes the log + * + *
+ * starting outer rule
+ * starting middle rule
+ * starting inner rule
+ * finished inner rule
+ * finished middle rule
+ * finished outer rule
+ * 
+ * + * @author Kirk Lund + */ +@SuppressWarnings("serial") +public class SerializableRuleChain implements SerializableTestRule { + private static final SerializableRuleChain EMPTY_CHAIN = new SerializableRuleChain(Collections.emptyList()); + + private transient List rulesStartingWithInnerMost; + + /** + * Returns a {@code SerializableRuleChain} without a {@link TestRule}. This method may + * be the starting point of a {@code SerializableRuleChain}. + * + * @return a {@code SerializableRuleChain} without a {@link TestRule}. + */ + public static SerializableRuleChain emptyRuleChain() { + return EMPTY_CHAIN; + } + + /** + * Returns a {@code SerializableRuleChain} with a single {@link TestRule}. This method + * is the usual starting point of a {@code SerializableRuleChain}. + * + * @param outerRule the outer rule of the {@code SerializableRuleChain}. + * @return a {@code SerializableRuleChain} with a single {@link TestRule}. + */ + public static SerializableRuleChain outerRule(TestRule outerRule) { + return emptyRuleChain().around(outerRule); + } + + private SerializableRuleChain(List rules) { + this.rulesStartingWithInnerMost = rules; + } + + /** + * Create a new {@code SerializableRuleChain}, which encloses the {@code nextRule} with + * the rules of the current {@code SerializableRuleChain}. + * + * @param enclosedRule the rule to enclose. + * @return a new {@code SerializableRuleChain}. + */ + public SerializableRuleChain around(TestRule enclosedRule) { + List rulesOfNewChain = new ArrayList(); + rulesOfNewChain.add(enclosedRule); + rulesOfNewChain.addAll(rulesStartingWithInnerMost); + return new SerializableRuleChain(rulesOfNewChain); + } + + /** + * {@inheritDoc} + */ + public Statement apply(Statement base, Description description) { + for (TestRule each : rulesStartingWithInnerMost) { + base = each.apply(base, description); + } + return base; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java new file mode 100755 index 0000000..0e796b3 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.io.File; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; + +import org.junit.rules.TemporaryFolder; + +/** + * Serializable version of TemporaryFolder JUnit Rule. JUnit lifecycle is not + * executed in remote JVMs. + * + * @author Kirk Lund + */ +@SuppressWarnings("serial") +public class SerializableTemporaryFolder extends TemporaryFolder implements SerializableTestRule { + + private void writeObject(final ObjectOutputStream out) throws Exception { + writeParentFolder(out); + writeFolder(out); + } + + private void readObject(final ObjectInputStream in) throws Exception { + readParentFolder(in); + readFolder(in); + } + + private void readParentFolder(final ObjectInputStream in) throws Exception { + final Field parentFolderField = TemporaryFolder.class.getDeclaredField("parentFolder"); + parentFolderField.setAccessible(true); + parentFolderField.set(this, (File) in.readObject()); + } + + private void readFolder(final ObjectInputStream in) throws Exception { + final Field folderField = TemporaryFolder.class.getDeclaredField("folder"); + folderField.setAccessible(true); + folderField.set(this, (File) in.readObject()); + } + + private void writeParentFolder(final ObjectOutputStream out) throws Exception { + final Field parentFolderField = TemporaryFolder.class.getDeclaredField("parentFolder"); + parentFolderField.setAccessible(true); + final File parentFolderFieldValue = (File) parentFolderField.get(this); + out.writeObject(parentFolderFieldValue); + } + + private void writeFolder(final ObjectOutputStream out) throws Exception { + final Field folderField = TemporaryFolder.class.getDeclaredField("folder"); + folderField.setAccessible(true); + final File folderFieldValue = (File) folderField.get(this); + out.writeObject(folderFieldValue); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java new file mode 100755 index 0000000..1fd255f --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; + +import org.junit.rules.TestName; + +/** + * Serializable version of TestName JUnit Rule. JUnit lifecycle is not + * executed in remote JVMs. + * + * @author Kirk Lund + */ +@SuppressWarnings("serial") +public class SerializableTestName extends TestName implements SerializableTestRule { + + private void writeObject(final ObjectOutputStream out) throws Exception { + writeName(out); + } + + private void readObject(final ObjectInputStream in) throws Exception { + readName(in); + } + + private void writeName(final ObjectOutputStream out) throws Exception { + final Field nameField = TestName.class.getDeclaredField("name"); + nameField.setAccessible(true); + final String nameValue = (String) nameField.get(this); + out.writeObject(nameValue); + } + + private void readName(final ObjectInputStream in) throws Exception { + Field nameField = TestName.class.getDeclaredField("name"); + nameField.setAccessible(true); + nameField.set(this, (String) in.readObject()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestRule.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestRule.java new file mode 100755 index 0000000..354c38a --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestRule.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.io.Serializable; + +import org.junit.rules.TestRule; + +/** + * Serializable version of JUnit TestRule. JUnit lifecycle is not + * executed in remote JVMs. + * + * The simplest way to satisfy this interface is to apply transient + * to every instance field. + * + * @author Kirk Lund + */ +public interface SerializableTestRule extends Serializable, TestRule { +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestWatcher.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestWatcher.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestWatcher.java new file mode 100755 index 0000000..5bcf686 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestWatcher.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import org.junit.rules.TestWatcher; + +/** + * Serializable version of TestWatcher JUnit Rule. JUnit lifecycle is not + * executed in remote JVMs. + * + * @author Kirk Lund + */ +@SuppressWarnings("serial") +public class SerializableTestWatcher extends TestWatcher implements SerializableTestRule { +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTimeout.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTimeout.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTimeout.java new file mode 100755 index 0000000..3136a1c --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTimeout.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; +import java.util.concurrent.TimeUnit; + +import org.junit.rules.TemporaryFolder; +import org.junit.rules.TestName; +import org.junit.rules.Timeout; + +/** + * Serializable version of Timeout JUnit Rule. JUnit lifecycle is not + * executed in remote JVMs. + * + * @author Kirk Lund + */ +@SuppressWarnings("serial") +public class SerializableTimeout extends Timeout implements SerializableTestRule { + + public static Builder builder() { + return new Builder(); + } + + public SerializableTimeout(final long timeout, final TimeUnit timeUnit) { + super(timeout, timeUnit); + } + + protected SerializableTimeout(final Builder builder) { + super(builder); + } + + public static class Builder extends Timeout.Builder { + + protected Builder() { + super(); + } + + @Override + public SerializableTimeout build() { + return new SerializableTimeout(this); + } + } + + private void writeObject(final ObjectOutputStream out) throws Exception { + writeTimeout(out); + writeTimeUnit(out); + writeLookForStuckThread(out); + } + + private void readObject(final ObjectInputStream in) throws Exception { + readTimeout(in); + readTimeUnit(in); + readLookForStuckThread(in); + } + + private void writeTimeout(final ObjectOutputStream out) throws Exception { + final Field timeoutField = TestName.class.getDeclaredField("timeout"); + timeoutField.setAccessible(true); + final Long timeoutValue = (Long) timeoutField.get(this); + out.writeLong(timeoutValue); + } + + private void writeTimeUnit(final ObjectOutputStream out) throws Exception { + final Field timeoutField = TestName.class.getDeclaredField("timeUnit"); + timeoutField.setAccessible(true); + final TimeUnit timeoutValue = (TimeUnit) timeoutField.get(this); + out.writeObject(timeoutValue); + } + + private void writeLookForStuckThread(final ObjectOutputStream out) throws Exception { + try { + final Field lookForStuckThreadField = TemporaryFolder.class.getDeclaredField("lookForStuckThread"); + lookForStuckThreadField.setAccessible(true); + final Boolean lookForStuckThreadValue = (Boolean) lookForStuckThreadField.get(this); + out.writeBoolean(lookForStuckThreadValue); + } catch (NoSuchFieldException e) { + out.writeBoolean(false); + } + } + + private void readTimeout(final ObjectInputStream in) throws Exception { + Field timeoutField = TestName.class.getDeclaredField("timeout"); + timeoutField.setAccessible(true); + timeoutField.set(this, (Long) in.readObject()); + } + + private void readTimeUnit(final ObjectInputStream in) throws Exception { + Field timeUnitField = TestName.class.getDeclaredField("timeUnit"); + timeUnitField.setAccessible(true); + timeUnitField.set(this, (TimeUnit) in.readObject()); + } + + private void readLookForStuckThread(final ObjectInputStream in) throws Exception { + try { + final Field lookForStuckThreadField = TemporaryFolder.class.getDeclaredField("lookForStuckThread"); + lookForStuckThreadField.setAccessible(true); + lookForStuckThreadField.set(this, (Boolean) in.readObject()); + } catch (NoSuchFieldException e) { + final boolean value = (Boolean) in.readObject(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/examples/RepeatingTestCasesExampleTest.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/examples/RepeatingTestCasesExampleTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/examples/RepeatingTestCasesExampleTest.java new file mode 100755 index 0000000..5ee647b --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/examples/RepeatingTestCasesExampleTest.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules.examples; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.assertThat; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.test.junit.Repeat; +import com.gemstone.gemfire.test.junit.categories.UnitTest; +import com.gemstone.gemfire.test.junit.rules.RepeatRule; + +/** + * The RepeatingTestCasesExampleTest class is a test suite of test cases testing the contract and functionality + * of the JUnit @Repeat annotation on a test suite class test case methods. + * + * @author John Blum + * @see org.junit.Test + * @see com.gemstone.gemfire.test.junit.Repeat + * @see com.gemstone.gemfire.test.junit.rules.RepeatRule + */ +@Category(UnitTest.class) +public class RepeatingTestCasesExampleTest { + + private static AtomicInteger repeatOnceCounter = new AtomicInteger(0); + private static AtomicInteger repeatOnlyOnceCounter = new AtomicInteger(0); + private static AtomicInteger repeatTenTimesCounter = new AtomicInteger(0); + private static AtomicInteger repeatTwiceCounter = new AtomicInteger(0); + + @Rule + public RepeatRule repeatRule = new RepeatRule(); + + @BeforeClass + public static void setupBeforeClass() { + System.setProperty("tdd.example.test.case.two.repetitions", "2"); + } + + @AfterClass + public static void tearDownAfterClass() { + assertThat(repeatOnceCounter.get(), is(equalTo(1))); + assertThat(repeatOnlyOnceCounter.get(), is(equalTo(1))); + assertThat(repeatTenTimesCounter.get(), is(equalTo(10))); + assertThat(repeatTwiceCounter.get(), is(equalTo(2))); + } + + @Test + @Repeat + public void repeatOnce() { + repeatOnceCounter.incrementAndGet(); + assertThat(repeatOnceCounter.get() <= 1, is(true)); + } + + @Test + @Repeat(property = "tdd.example.test.case.with.non-existing.system.property") + public void repeatOnlyOnce() { + repeatOnlyOnceCounter.incrementAndGet(); + assertThat(repeatOnlyOnceCounter.get() <= 1, is(true)); + } + + @Test + @Repeat(10) + public void repeatTenTimes() { + repeatTenTimesCounter.incrementAndGet(); + assertThat(repeatTenTimesCounter.get() <= 10, is(true)); + } + + @Test + @Repeat(property = "tdd.example.test.case.two.repetitions") + public void repeatTwiceCounter() { + repeatTwiceCounter.incrementAndGet(); + assertThat(repeatTwiceCounter.get() <= 2, is(true)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/examples/RetryRuleExampleTest.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/examples/RetryRuleExampleTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/examples/RetryRuleExampleTest.java new file mode 100755 index 0000000..f6d70a2 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/examples/RetryRuleExampleTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules.examples; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.test.junit.categories.UnitTest; +import com.gemstone.gemfire.test.junit.rules.RetryRule; + +@Category(UnitTest.class) +public class RetryRuleExampleTest { + + @Rule + public final transient RetryRule retry = new RetryRule(2); + + private static int count = 0; + + @Test + public void unreliableTestWithRaceConditions() { + count++; + if (count < 2) { + assertThat(count).isEqualTo(2); // doomed to fail + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/ExpectedTimeoutRuleTest.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/ExpectedTimeoutRuleTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/ExpectedTimeoutRuleTest.java new file mode 100755 index 0000000..b67d1eb --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/ExpectedTimeoutRuleTest.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules.tests; + +import static com.gemstone.gemfire.test.junit.rules.tests.TestRunner.*; +import static org.assertj.core.api.Assertions.*; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; + +import com.gemstone.gemfire.test.junit.categories.UnitTest; +import com.gemstone.gemfire.test.junit.rules.ExpectedTimeoutRule; + +/** + * Unit tests for ExpectedTimeout JUnit Rule. + * + * @author Kirk Lund + * @since 8.2 + */ +@Category(UnitTest.class) +public class ExpectedTimeoutRuleTest { + + @Test + public void passesUnused() { + Result result = runTest(PassingTestShouldPassWhenUnused.class); + + assertThat(result.wasSuccessful()).isTrue(); + } + + @Test + public void failsWithoutExpectedException() { + Result result = runTest(FailsWithoutExpectedException.class); + + assertThat(result.wasSuccessful()).isFalse(); + + List failures = result.getFailures(); + assertThat(failures.size()).as("Failures: " + failures).isEqualTo(1); + + Failure failure = failures.get(0); + assertThat(failure.getException()).isExactlyInstanceOf(AssertionError.class).hasMessage("Expected test to throw an instance of " + TimeoutException.class.getName()); + } + + @Test + public void failsWithoutExpectedTimeoutException() { + Result result = runTest(FailsWithoutExpectedTimeoutException.class); + + assertThat(result.wasSuccessful()).isFalse(); + + List failures = result.getFailures(); + assertThat(failures.size()).as("Failures: " + failures).isEqualTo(1); + + Failure failure = failures.get(0); + assertThat(failure.getException()).isExactlyInstanceOf(AssertionError.class).hasMessage("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWithoutExpectedTimeoutException.message + "\")"); + } + + @Test + public void failsWithExpectedTimeoutButWrongError() { + Result result = runTest(FailsWithExpectedTimeoutButWrongError.class); + + assertThat(result.wasSuccessful()).isFalse(); + + List failures = result.getFailures(); + assertThat(failures.size()).as("Failures: " + failures).isEqualTo(1); + + Failure failure = failures.get(0); + String expectedMessage = + "\n" + + "Expected: (an instance of java.util.concurrent.TimeoutException and exception with message a string containing \"this is a message for FailsWithExpectedTimeoutButWrongError\")" + + "\n" + + " " + + "but: an instance of java.util.concurrent.TimeoutException is a java.lang.NullPointerException"; + assertThat(failure.getException()).isExactlyInstanceOf(AssertionError.class).hasMessageContaining(expectedMessage); + } + + @Test + public void passesWithExpectedTimeoutAndTimeoutException() { + Result result = runTest(PassesWithExpectedTimeoutAndTimeoutException.class); + + assertThat(result.wasSuccessful()).isTrue(); + } + + @Test + public void failsWhenTimeoutIsEarly() { + Result result = runTest(FailsWhenTimeoutIsEarly.class); + + assertThat(result.wasSuccessful()).isFalse(); + + List failures = result.getFailures(); + assertThat(failures.size()).as("Failures: " + failures).isEqualTo(1); + + Failure failure = failures.get(0); + assertThat(failure.getException()).isExactlyInstanceOf(AssertionError.class).hasMessage("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWhenTimeoutIsEarly.message + "\")"); + } + + @Test + public void failsWhenTimeoutIsLate() { + Result result = runTest(FailsWhenTimeoutIsLate.class); + + assertThat(result.wasSuccessful()).isFalse(); + + List failures = result.getFailures(); + assertThat(failures.size()).as("Failures: " + failures).isEqualTo(1); + + Failure failure = failures.get(0); + assertThat(failure.getException()).isExactlyInstanceOf(AssertionError.class).hasMessage("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWhenTimeoutIsLate.message + "\")"); + } + + public static class AbstractExpectedTimeoutRuleTest { + @Rule + public ExpectedTimeoutRule timeout = ExpectedTimeoutRule.none(); + } + + public static class PassingTestShouldPassWhenUnused extends AbstractExpectedTimeoutRuleTest { + @Test + public void passesUnused() throws Exception { + } + } + + public static class FailsWithoutExpectedException extends AbstractExpectedTimeoutRuleTest { + @Test + public void failsWithoutExpectedException() throws Exception { + timeout.expect(TimeoutException.class); + } + } + + public static class FailsWithoutExpectedTimeoutException extends AbstractExpectedTimeoutRuleTest { + public static final String message = "this is a message for FailsWithoutExpectedTimeoutException"; + @Test + public void failsWithoutExpectedTimeoutAndTimeoutException() throws Exception { + timeout.expect(TimeoutException.class); + timeout.expectMessage(message); + timeout.expectMinimumDuration(10); + timeout.expectMaximumDuration(1000); + timeout.expectTimeUnit(TimeUnit.MILLISECONDS); + Thread.sleep(100); + } + } + + public static class FailsWithExpectedTimeoutButWrongError extends AbstractExpectedTimeoutRuleTest { + public static final String message = "this is a message for FailsWithExpectedTimeoutButWrongError"; + @Test + public void failsWithExpectedTimeoutButWrongError() throws Exception { + timeout.expect(TimeoutException.class); + timeout.expectMessage(message); + timeout.expectMinimumDuration(10); + timeout.expectMaximumDuration(1000); + timeout.expectTimeUnit(TimeUnit.MILLISECONDS); + Thread.sleep(100); + throw new NullPointerException(); + } + } + + public static class PassesWithExpectedTimeoutAndTimeoutException extends AbstractExpectedTimeoutRuleTest { + public static final String message = "this is a message for PassesWithExpectedTimeoutAndTimeoutException"; + public static final Class exceptionClass = TimeoutException.class; + @Test + public void passesWithExpectedTimeoutAndTimeoutException() throws Exception { + timeout.expect(exceptionClass); + timeout.expectMessage(message); + timeout.expectMinimumDuration(10); + timeout.expectMaximumDuration(1000); + timeout.expectTimeUnit(TimeUnit.MILLISECONDS); + Thread.sleep(100); + throw new TimeoutException(message); + } + } + + public static class FailsWhenTimeoutIsEarly extends AbstractExpectedTimeoutRuleTest { + public static final String message = "this is a message for FailsWhenTimeoutIsEarly"; + @Test + public void failsWhenTimeoutIsEarly() throws Exception { + timeout.expect(TimeoutException.class); + timeout.expectMessage(message); + timeout.expectMinimumDuration(1000); + timeout.expectMaximumDuration(2000); + timeout.expectTimeUnit(TimeUnit.MILLISECONDS); + Thread.sleep(10); + } + } + + public static class FailsWhenTimeoutIsLate extends AbstractExpectedTimeoutRuleTest { + public static final String message = "this is a message for FailsWhenTimeoutIsLate"; + @Test + public void failsWhenTimeoutIsLate() throws Exception { + timeout.expect(TimeoutException.class); + timeout.expectMessage(message); + timeout.expectMinimumDuration(10); + timeout.expectMaximumDuration(20); + timeout.expectTimeUnit(TimeUnit.MILLISECONDS); + Thread.sleep(100); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/IgnoreUntilRuleTest.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/IgnoreUntilRuleTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/IgnoreUntilRuleTest.java new file mode 100755 index 0000000..a984d1d --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/IgnoreUntilRuleTest.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules.tests; + +import static com.gemstone.gemfire.test.junit.rules.tests.TestRunner.*; +import static org.assertj.core.api.Assertions.*; + +import java.util.List; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; + +import com.gemstone.gemfire.test.junit.IgnoreUntil; +import com.gemstone.gemfire.test.junit.categories.UnitTest; +import com.gemstone.gemfire.test.junit.rules.IgnoreUntilRule; + +/** + * Unit tests for IgnoreUntil JUnit Rule + * + * @author Kirk Lund + */ +@Category(UnitTest.class) +public class IgnoreUntilRuleTest { + + private static final String ASSERTION_ERROR_MESSAGE = "failing test"; + + @Test + public void shouldIgnoreWhenUntilIsInFuture() { + Result result = runTest(ShouldIgnoreWhenUntilIsInFuture.class); + + assertThat(result.wasSuccessful()).isTrue(); + assertThat(ShouldIgnoreWhenUntilIsInFuture.count).isEqualTo(0); + } + + @Test + public void shouldExecuteWhenUntilIsInPast() { + Result result = runTest(ShouldExecuteWhenUntilIsInPast.class); + + assertThat(result.wasSuccessful()).isFalse(); + + List failures = result.getFailures(); + assertThat(failures.size()).as("Failures: " + failures).isEqualTo(1); + + Failure failure = failures.get(0); + assertThat(failure.getException()).isExactlyInstanceOf(AssertionError.class).hasMessage(ASSERTION_ERROR_MESSAGE); + assertThat(ShouldExecuteWhenUntilIsInPast.count).isEqualTo(1); + } + + @Test + public void shouldExecuteWhenUntilIsDefault() { + Result result = runTest(ShouldExecuteWhenUntilIsDefault.class); + + assertThat(result.wasSuccessful()).isFalse(); + + List failures = result.getFailures(); + assertThat(failures.size()).as("Failures: " + failures).isEqualTo(1); + + Failure failure = failures.get(0); + assertThat(failure.getException()).isExactlyInstanceOf(AssertionError.class).hasMessage(ASSERTION_ERROR_MESSAGE); + assertThat(ShouldExecuteWhenUntilIsDefault.count).isEqualTo(1); + } + + public static class ShouldIgnoreWhenUntilIsInFuture { + private static int count; + + @Rule + public final IgnoreUntilRule ignoreUntilRule = new IgnoreUntilRule(); + + @Test + @IgnoreUntil(value = "description", until = "3000-01-01") + public void doTest() throws Exception { + count++; + fail(ASSERTION_ERROR_MESSAGE); + } + } + + public static class ShouldExecuteWhenUntilIsInPast { + private static int count; + + @Rule + public final IgnoreUntilRule ignoreUntilRule = new IgnoreUntilRule(); + + @Test + @IgnoreUntil(value = "description", until = "1980-01-01") + public void doTest() throws Exception { + count++; + fail(ASSERTION_ERROR_MESSAGE); + } + } + + public static class ShouldExecuteWhenUntilIsDefault { + private static int count; + + @Rule + public final IgnoreUntilRule ignoreUntilRule = new IgnoreUntilRule(); + + @Test + @IgnoreUntil(value = "description") + public void doTest() throws Exception { + count++; + fail(ASSERTION_ERROR_MESSAGE); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1be4f932/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/JUnitRuleTestSuite.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/JUnitRuleTestSuite.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/JUnitRuleTestSuite.java new file mode 100755 index 0000000..4c9e315 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/JUnitRuleTestSuite.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gemstone.gemfire.test.junit.rules.tests; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + ExpectedTimeoutRuleTest.class, + IgnoreUntilRuleTest.class, + RepeatRuleTest.class, + RetryRuleGlobalWithErrorTest.class, + RetryRuleGlobalWithExceptionTest.class, + RetryRuleLocalWithErrorTest.class, + RetryRuleLocalWithExceptionTest.class, +}) +public class JUnitRuleTestSuite { +}