1 /* 2 * Copyright (C) 2010 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.testing; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import com.google.common.annotations.GwtCompatible; 22 import junit.framework.TestCase; 23 import org.checkerframework.checker.nullness.qual.Nullable; 24 25 /** @author Luiz-Otavio "Z" Zorzella */ 26 @GwtCompatible 27 public class TearDownStackTest extends TestCase { 28 29 private TearDownStack tearDownStack = new TearDownStack(); 30 testSingleTearDown()31 public void testSingleTearDown() throws Exception { 32 final TearDownStack stack = buildTearDownStack(); 33 34 final SimpleTearDown tearDown = new SimpleTearDown(); 35 stack.addTearDown(tearDown); 36 37 assertEquals(false, tearDown.ran); 38 39 stack.runTearDown(); 40 41 assertEquals("tearDown should have run", true, tearDown.ran); 42 } 43 testMultipleTearDownsHappenInOrder()44 public void testMultipleTearDownsHappenInOrder() throws Exception { 45 final TearDownStack stack = buildTearDownStack(); 46 47 final SimpleTearDown tearDownOne = new SimpleTearDown(); 48 stack.addTearDown(tearDownOne); 49 50 final Callback callback = 51 new Callback() { 52 @Override 53 public void run() { 54 assertEquals( 55 "tearDownTwo should have been run before tearDownOne", false, tearDownOne.ran); 56 } 57 }; 58 59 final SimpleTearDown tearDownTwo = new SimpleTearDown(callback); 60 stack.addTearDown(tearDownTwo); 61 62 assertEquals(false, tearDownOne.ran); 63 assertEquals(false, tearDownTwo.ran); 64 65 stack.runTearDown(); 66 67 assertEquals("tearDownOne should have run", true, tearDownOne.ran); 68 assertEquals("tearDownTwo should have run", true, tearDownTwo.ran); 69 } 70 testThrowingTearDown()71 public void testThrowingTearDown() throws Exception { 72 final TearDownStack stack = buildTearDownStack(); 73 74 final ThrowingTearDown tearDownOne = new ThrowingTearDown("one"); 75 stack.addTearDown(tearDownOne); 76 77 final ThrowingTearDown tearDownTwo = new ThrowingTearDown("two"); 78 stack.addTearDown(tearDownTwo); 79 80 assertEquals(false, tearDownOne.ran); 81 assertEquals(false, tearDownTwo.ran); 82 83 try { 84 stack.runTearDown(); 85 fail("runTearDown should have thrown an exception"); 86 } catch (ClusterException expected) { 87 assertThat(expected).hasCauseThat().hasMessageThat().isEqualTo("two"); 88 } catch (RuntimeException e) { 89 throw new RuntimeException( 90 "A ClusterException should have been thrown, rather than a " + e.getClass().getName(), e); 91 } 92 93 assertEquals(true, tearDownOne.ran); 94 assertEquals(true, tearDownTwo.ran); 95 } 96 97 @Override runBare()98 public final void runBare() throws Throwable { 99 try { 100 setUp(); 101 runTest(); 102 } finally { 103 tearDown(); 104 } 105 } 106 107 @Override tearDown()108 protected void tearDown() { 109 tearDownStack.runTearDown(); 110 } 111 112 /** Builds a {@link TearDownStack} that makes sure it's clear by the end of this test. */ buildTearDownStack()113 private TearDownStack buildTearDownStack() { 114 final TearDownStack result = new TearDownStack(); 115 tearDownStack.addTearDown( 116 new TearDown() { 117 118 @Override 119 public void tearDown() throws Exception { 120 synchronized (result.lock) { 121 assertEquals( 122 "The test should have cleared the stack (say, by virtue of running runTearDown)", 123 0, 124 result.stack.size()); 125 } 126 } 127 }); 128 return result; 129 } 130 131 private static final class ThrowingTearDown implements TearDown { 132 133 private final String id; 134 boolean ran = false; 135 ThrowingTearDown(String id)136 ThrowingTearDown(String id) { 137 this.id = id; 138 } 139 140 @Override tearDown()141 public void tearDown() throws Exception { 142 ran = true; 143 throw new RuntimeException(id); 144 } 145 } 146 147 private static final class SimpleTearDown implements TearDown { 148 149 boolean ran = false; 150 @Nullable Callback callback = null; 151 SimpleTearDown()152 public SimpleTearDown() {} 153 SimpleTearDown(Callback callback)154 public SimpleTearDown(Callback callback) { 155 this.callback = callback; 156 } 157 158 @Override tearDown()159 public void tearDown() throws Exception { 160 if (callback != null) { 161 callback.run(); 162 } 163 ran = true; 164 } 165 } 166 167 private interface Callback { run()168 void run(); 169 } 170 } 171