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 com.google.common.annotations.GwtCompatible; 20 21 import junit.framework.TestCase; 22 23 /** 24 * @author Luiz-Otavio "Z" Zorzella 25 */ 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 = new Callback() { 51 @Override 52 public void run() { 53 assertEquals("tearDownTwo should have been run before tearDownOne", 54 false, tearDownOne.ran); 55 } 56 }; 57 58 final SimpleTearDown tearDownTwo = new SimpleTearDown(callback); 59 stack.addTearDown(tearDownTwo); 60 61 assertEquals(false, tearDownOne.ran); 62 assertEquals(false, tearDownTwo.ran); 63 64 stack.runTearDown(); 65 66 assertEquals("tearDownOne should have run", true, tearDownOne.ran); 67 assertEquals("tearDownTwo should have run", true, tearDownTwo.ran); 68 } 69 testThrowingTearDown()70 public void testThrowingTearDown() throws Exception { 71 final TearDownStack stack = buildTearDownStack(); 72 73 final ThrowingTearDown tearDownOne = new ThrowingTearDown("one"); 74 stack.addTearDown(tearDownOne); 75 76 final ThrowingTearDown tearDownTwo = new ThrowingTearDown("two"); 77 stack.addTearDown(tearDownTwo); 78 79 assertEquals(false, tearDownOne.ran); 80 assertEquals(false, tearDownTwo.ran); 81 82 try { 83 stack.runTearDown(); 84 fail("runTearDown should have thrown an exception"); 85 } catch (ClusterException expected) { 86 assertEquals("two", expected.getCause().getMessage()); 87 } catch (RuntimeException e) { 88 throw new RuntimeException( 89 "A ClusterException should have been thrown, rather than a " + e.getClass().getName(), e); 90 } 91 92 assertEquals(true, tearDownOne.ran); 93 assertEquals(true, tearDownTwo.ran); 94 } 95 runBare()96 @Override public final void runBare() throws Throwable { 97 try { 98 setUp(); 99 runTest(); 100 } finally { 101 tearDown(); 102 } 103 } 104 tearDown()105 @Override protected void tearDown() { 106 tearDownStack.runTearDown(); 107 } 108 109 /** 110 * Builds a {@link TearDownStack} that makes sure it's clear by the end of 111 * this test. 112 */ buildTearDownStack()113 private TearDownStack buildTearDownStack() { 114 final TearDownStack result = new TearDownStack(); 115 tearDownStack.addTearDown(new TearDown() { 116 117 @Override 118 public void tearDown() throws Exception { 119 assertEquals( 120 "The test should have cleared the stack (say, by virtue of running runTearDown)", 121 0, result.stack.size()); 122 } 123 }); 124 return result; 125 } 126 127 private static final class ThrowingTearDown implements TearDown { 128 129 private final String id; 130 boolean ran = false; 131 ThrowingTearDown(String id)132 ThrowingTearDown(String id) { 133 this.id = id; 134 } 135 136 @Override tearDown()137 public void tearDown() throws Exception { 138 ran = true; 139 throw new RuntimeException(id); 140 } 141 } 142 143 private static final class SimpleTearDown implements TearDown { 144 145 boolean ran = false; 146 Callback callback = null; 147 SimpleTearDown()148 public SimpleTearDown() {} 149 SimpleTearDown(Callback callback)150 public SimpleTearDown(Callback callback) { 151 this.callback = callback; 152 } 153 154 @Override tearDown()155 public void tearDown() throws Exception { 156 if (callback != null) { 157 callback.run(); 158 } 159 ran = true; 160 } 161 } 162 163 private interface Callback { run()164 void run(); 165 } 166 } 167