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