• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.util.concurrent;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
21 import static org.junit.Assert.assertThrows;
22 
23 import com.google.common.collect.Lists;
24 import java.util.List;
25 import java.util.concurrent.Executor;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.TimeoutException;
28 import junit.framework.TestCase;
29 
30 /**
31  * Tests for {@link AbstractIdleService}.
32  *
33  * @author Chris Nokleberg
34  * @author Ben Yu
35  */
36 public class AbstractIdleServiceTest extends TestCase {
testStart()37   public void testStart() {
38     TestService service = new TestService();
39     assertEquals(0, service.startUpCalled);
40     service.startAsync().awaitRunning();
41     assertEquals(1, service.startUpCalled);
42     assertEquals(Service.State.RUNNING, service.state());
43     assertThat(service.transitionStates).containsExactly(Service.State.STARTING);
44   }
45 
testStart_failed()46   public void testStart_failed() {
47     final Exception exception = new Exception("deliberate");
48     TestService service =
49         new TestService() {
50           @Override
51           protected void startUp() throws Exception {
52             super.startUp();
53             throw exception;
54           }
55         };
56     assertEquals(0, service.startUpCalled);
57     RuntimeException e =
58         assertThrows(RuntimeException.class, () -> service.startAsync().awaitRunning());
59     assertThat(e).hasCauseThat().isSameInstanceAs(exception);
60     assertEquals(1, service.startUpCalled);
61     assertEquals(Service.State.FAILED, service.state());
62     assertThat(service.transitionStates).containsExactly(Service.State.STARTING);
63   }
64 
testStop_withoutStart()65   public void testStop_withoutStart() {
66     TestService service = new TestService();
67     service.stopAsync().awaitTerminated();
68     assertEquals(0, service.startUpCalled);
69     assertEquals(0, service.shutDownCalled);
70     assertEquals(Service.State.TERMINATED, service.state());
71     assertThat(service.transitionStates).isEmpty();
72   }
73 
testStop_afterStart()74   public void testStop_afterStart() {
75     TestService service = new TestService();
76     service.startAsync().awaitRunning();
77     assertEquals(1, service.startUpCalled);
78     assertEquals(0, service.shutDownCalled);
79     service.stopAsync().awaitTerminated();
80     assertEquals(1, service.startUpCalled);
81     assertEquals(1, service.shutDownCalled);
82     assertEquals(Service.State.TERMINATED, service.state());
83     assertThat(service.transitionStates)
84         .containsExactly(Service.State.STARTING, Service.State.STOPPING)
85         .inOrder();
86   }
87 
testStop_failed()88   public void testStop_failed() {
89     final Exception exception = new Exception("deliberate");
90     TestService service =
91         new TestService() {
92           @Override
93           protected void shutDown() throws Exception {
94             super.shutDown();
95             throw exception;
96           }
97         };
98     service.startAsync().awaitRunning();
99     assertEquals(1, service.startUpCalled);
100     assertEquals(0, service.shutDownCalled);
101     RuntimeException e =
102         assertThrows(RuntimeException.class, () -> service.stopAsync().awaitTerminated());
103     assertThat(e).hasCauseThat().isSameInstanceAs(exception);
104     assertEquals(1, service.startUpCalled);
105     assertEquals(1, service.shutDownCalled);
106     assertEquals(Service.State.FAILED, service.state());
107     assertThat(service.transitionStates)
108         .containsExactly(Service.State.STARTING, Service.State.STOPPING)
109         .inOrder();
110   }
111 
testServiceToString()112   public void testServiceToString() {
113     AbstractIdleService service = new TestService();
114     assertEquals("TestService [NEW]", service.toString());
115     service.startAsync().awaitRunning();
116     assertEquals("TestService [RUNNING]", service.toString());
117     service.stopAsync().awaitTerminated();
118     assertEquals("TestService [TERMINATED]", service.toString());
119   }
120 
testTimeout()121   public void testTimeout() throws Exception {
122     // Create a service whose executor will never run its commands
123     Service service =
124         new TestService() {
125           @Override
126           protected Executor executor() {
127             return new Executor() {
128               @Override
129               public void execute(Runnable command) {}
130             };
131           }
132 
133           @Override
134           protected String serviceName() {
135             return "Foo";
136           }
137         };
138     TimeoutException e =
139         assertThrows(
140             TimeoutException.class,
141             () -> service.startAsync().awaitRunning(1, TimeUnit.MILLISECONDS));
142     assertThat(e)
143         .hasMessageThat()
144         .isEqualTo("Timed out waiting for Foo [STARTING] to reach the RUNNING state.");
145   }
146 
147   private static class TestService extends AbstractIdleService {
148     int startUpCalled = 0;
149     int shutDownCalled = 0;
150     final List<State> transitionStates = Lists.newArrayList();
151 
152     @Override
startUp()153     protected void startUp() throws Exception {
154       assertEquals(0, startUpCalled);
155       assertEquals(0, shutDownCalled);
156       startUpCalled++;
157       assertEquals(State.STARTING, state());
158     }
159 
160     @Override
shutDown()161     protected void shutDown() throws Exception {
162       assertEquals(1, startUpCalled);
163       assertEquals(0, shutDownCalled);
164       shutDownCalled++;
165       assertEquals(State.STOPPING, state());
166     }
167 
168     @Override
executor()169     protected Executor executor() {
170       transitionStates.add(state());
171       return directExecutor();
172     }
173   }
174 
175   // Functional tests using real thread. We only verify publicly visible state.
176   // Interaction assertions are done by the single-threaded unit tests.
177 
178   private static class DefaultService extends AbstractIdleService {
179     @Override
startUp()180     protected void startUp() throws Exception {}
181 
182     @Override
shutDown()183     protected void shutDown() throws Exception {}
184   }
185 
testFunctionalServiceStartStop()186   public void testFunctionalServiceStartStop() {
187     AbstractIdleService service = new DefaultService();
188     service.startAsync().awaitRunning();
189     assertEquals(Service.State.RUNNING, service.state());
190     service.stopAsync().awaitTerminated();
191     assertEquals(Service.State.TERMINATED, service.state());
192   }
193 
testFunctionalStart_failed()194   public void testFunctionalStart_failed() {
195     final Exception exception = new Exception("deliberate");
196     AbstractIdleService service =
197         new DefaultService() {
198           @Override
199           protected void startUp() throws Exception {
200             throw exception;
201           }
202         };
203     RuntimeException e =
204         assertThrows(RuntimeException.class, () -> service.startAsync().awaitRunning());
205     assertThat(e).hasCauseThat().isSameInstanceAs(exception);
206     assertEquals(Service.State.FAILED, service.state());
207   }
208 
testFunctionalStop_failed()209   public void testFunctionalStop_failed() {
210     final Exception exception = new Exception("deliberate");
211     AbstractIdleService service =
212         new DefaultService() {
213           @Override
214           protected void shutDown() throws Exception {
215             throw exception;
216           }
217         };
218     service.startAsync().awaitRunning();
219     RuntimeException e =
220         assertThrows(RuntimeException.class, () -> service.stopAsync().awaitTerminated());
221     assertThat(e).hasCauseThat().isSameInstanceAs(exception);
222     assertEquals(Service.State.FAILED, service.state());
223   }
224 }
225