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