/* * 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 org.apache.geode.test.junit.rules; import static org.assertj.core.api.Assertions.assertThat; import org.apache.geode.test.junit.categories.UnitTest; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.ExternalResource; import org.junit.runner.Result; import java.util.concurrent.atomic.AtomicInteger; /** * Unit tests for {@link RuleList}. */ @Category(UnitTest.class) public class RuleListTest { private static AtomicInteger counter; private static Invocations[] invocations; @BeforeClass public static void setUpClass() { counter = new AtomicInteger(); invocations = new Invocations[] {new Invocations(counter), new Invocations(counter), new Invocations(counter)}; } @AfterClass public static void tearDownClass() { counter = null; invocations = null; ThreeRules.ruleListStatic = null; } @Test public void firstShouldBeFirstBeforeLastAfter() { Result result = TestRunner.runTest(ThreeRules.class); assertThat(result.wasSuccessful()).isTrue(); assertThat(counter.get()).isEqualTo(9); assertThat(invocations[0].beforeInvocation).isEqualTo(1); assertThat(invocations[1].beforeInvocation).isEqualTo(2); assertThat(invocations[2].beforeInvocation).isEqualTo(3); assertThat(invocations[0].testInvocation).isEqualTo(4); assertThat(invocations[1].testInvocation).isEqualTo(5); assertThat(invocations[2].testInvocation).isEqualTo(6); assertThat(invocations[2].afterInvocation).isEqualTo(7); assertThat(invocations[1].afterInvocation).isEqualTo(8); assertThat(invocations[0].afterInvocation).isEqualTo(9); } /** * Used by test {@link #firstShouldBeFirstBeforeLastAfter()} */ public static class ThreeRules { static RuleList ruleListStatic; public SpyRule ruleOne = new SpyRule("ruleOne", invocations[0]); public SpyRule ruleTwo = new SpyRule("ruleTwo", invocations[1]); public SpyRule ruleThree = new SpyRule("ruleThree", invocations[2]); @Rule public RuleList ruleList = new RuleList().add(ruleThree).add(ruleTwo).add(ruleOne); @Test public void doTest() throws Exception { ruleListStatic = ruleList; invocations[0].invokedTest(); invocations[1].invokedTest(); invocations[2].invokedTest(); } } /** * Structure of rule callback and test invocations */ public static class Invocations { private final AtomicInteger counter; int beforeInvocation = 0; int testInvocation = 0; int afterInvocation = 0; Invocations(AtomicInteger counter) { this.counter = counter; } void invokedTest() { testInvocation = counter.incrementAndGet(); } void invokedBefore() { beforeInvocation = counter.incrementAndGet(); } void invokedAfter() { afterInvocation = counter.incrementAndGet(); } @Override public String toString() { return "Invocations{" + "counter=" + counter + ", beforeInvocation=" + beforeInvocation + ", testInvocation=" + testInvocation + ", afterInvocation=" + afterInvocation + '}'; } } /** * Implementation of TestRule that records the order of callbacks invoked on it. Used by * {@link RuleListTest}. */ public static class SpyRule extends ExternalResource { static SpyRuleBuilder builder() { return new SpyRuleBuilder(); } private final String name; private final Invocations invocations; private final Throwable beforeThrowable; SpyRule(String name, Invocations invocations) { this.name = name; this.invocations = invocations; this.beforeThrowable = null; } SpyRule(SpyRuleBuilder builder) { this.name = builder.name; this.invocations = builder.invocations; this.beforeThrowable = builder.beforeThrowable; } Invocations invocations() { return this.invocations; } void test() { this.invocations.invokedTest(); } @Override protected void before() throws Throwable { this.invocations.invokedBefore(); if (this.beforeThrowable != null) { throw this.beforeThrowable; } } @Override protected void after() { this.invocations.invokedAfter(); } @Override public String toString() { return "SpyRule{" + "name='" + name + '\'' + '}'; } } /** * Builder for more control of constructing an instance of {@link SpyRule} */ public static class SpyRuleBuilder { String name; Invocations invocations; Throwable beforeThrowable; SpyRuleBuilder withName(String name) { this.name = name; return this; } SpyRuleBuilder withInvocations(Invocations invocations) { this.invocations = invocations; return this; } SpyRuleBuilder beforeThrows(Throwable throwable) { this.beforeThrowable = throwable; return this; } SpyRule build() { return new SpyRule(this); } } }