Home | History | Annotate | Download | only in concurrent
      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