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