| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.hadoop.yarn.util; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.fail; |
| |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.yarn.YarnException; |
| import org.apache.hadoop.yarn.service.CompositeService; |
| import org.apache.hadoop.yarn.service.Service.STATE; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| public class TestCompositeService { |
| |
| private static final int NUM_OF_SERVICES = 5; |
| |
| private static final int FAILED_SERVICE_SEQ_NUMBER = 2; |
| |
| @Before |
| public void setup() { |
| CompositeServiceImpl.resetCounter(); |
| } |
| |
| @Test |
| public void testCallSequence() { |
| ServiceManager serviceManager = new ServiceManager("ServiceManager"); |
| |
| // Add services |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| CompositeServiceImpl service = new CompositeServiceImpl(i); |
| serviceManager.addTestService(service); |
| } |
| |
| CompositeServiceImpl[] services = serviceManager.getServices().toArray( |
| new CompositeServiceImpl[0]); |
| |
| assertEquals("Number of registered services ", NUM_OF_SERVICES, |
| services.length); |
| |
| Configuration conf = new Configuration(); |
| // Initialise the composite service |
| serviceManager.init(conf); |
| |
| // Verify the init() call sequence numbers for every service |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| assertEquals("For " + services[i] |
| + " service, init() call sequence number should have been ", i, |
| services[i].getCallSequenceNumber()); |
| } |
| |
| // Reset the call sequence numbers |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| services[i].reset(); |
| } |
| |
| serviceManager.start(); |
| |
| // Verify the start() call sequence numbers for every service |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| assertEquals("For " + services[i] |
| + " service, start() call sequence number should have been ", i, |
| services[i].getCallSequenceNumber()); |
| } |
| |
| // Reset the call sequence numbers |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| services[i].reset(); |
| } |
| |
| serviceManager.stop(); |
| |
| // Verify the stop() call sequence numbers for every service |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| assertEquals("For " + services[i] |
| + " service, stop() call sequence number should have been ", |
| ((NUM_OF_SERVICES - 1) - i), services[i].getCallSequenceNumber()); |
| } |
| |
| // Try to stop again. This should be a no-op. |
| serviceManager.stop(); |
| // Verify that stop() call sequence numbers for every service don't change. |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| assertEquals("For " + services[i] |
| + " service, stop() call sequence number should have been ", |
| ((NUM_OF_SERVICES - 1) - i), services[i].getCallSequenceNumber()); |
| } |
| } |
| |
| @Test |
| public void testServiceStartup() { |
| ServiceManager serviceManager = new ServiceManager("ServiceManager"); |
| |
| // Add services |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| CompositeServiceImpl service = new CompositeServiceImpl(i); |
| if (i == FAILED_SERVICE_SEQ_NUMBER) { |
| service.setThrowExceptionOnStart(true); |
| } |
| serviceManager.addTestService(service); |
| } |
| |
| CompositeServiceImpl[] services = serviceManager.getServices().toArray( |
| new CompositeServiceImpl[0]); |
| |
| Configuration conf = new Configuration(); |
| |
| // Initialise the composite service |
| serviceManager.init(conf); |
| |
| // Start the composite service |
| try { |
| serviceManager.start(); |
| fail("Exception should have been thrown due to startup failure of last service"); |
| } catch (YarnException e) { |
| for (int i = 0; i < NUM_OF_SERVICES - 1; i++) { |
| if (i >= FAILED_SERVICE_SEQ_NUMBER) { |
| // Failed service state should be INITED |
| assertEquals("Service state should have been ", STATE.INITED, |
| services[NUM_OF_SERVICES - 1].getServiceState()); |
| } else { |
| assertEquals("Service state should have been ", STATE.STOPPED, |
| services[i].getServiceState()); |
| } |
| } |
| |
| } |
| } |
| |
| @Test |
| public void testServiceStop() { |
| ServiceManager serviceManager = new ServiceManager("ServiceManager"); |
| |
| // Add services |
| for (int i = 0; i < NUM_OF_SERVICES; i++) { |
| CompositeServiceImpl service = new CompositeServiceImpl(i); |
| if (i == FAILED_SERVICE_SEQ_NUMBER) { |
| service.setThrowExceptionOnStop(true); |
| } |
| serviceManager.addTestService(service); |
| } |
| |
| CompositeServiceImpl[] services = serviceManager.getServices().toArray( |
| new CompositeServiceImpl[0]); |
| |
| Configuration conf = new Configuration(); |
| |
| // Initialise the composite service |
| serviceManager.init(conf); |
| |
| serviceManager.start(); |
| |
| // Stop the composite service |
| try { |
| serviceManager.stop(); |
| } catch (YarnException e) { |
| for (int i = 0; i < NUM_OF_SERVICES - 1; i++) { |
| assertEquals("Service state should have been ", STATE.STOPPED, |
| services[NUM_OF_SERVICES].getServiceState()); |
| } |
| } |
| } |
| |
| public static class CompositeServiceImpl extends CompositeService { |
| |
| private static int counter = -1; |
| |
| private int callSequenceNumber = -1; |
| |
| private boolean throwExceptionOnStart; |
| |
| private boolean throwExceptionOnStop; |
| |
| public CompositeServiceImpl(int sequenceNumber) { |
| super(Integer.toString(sequenceNumber)); |
| } |
| |
| @Override |
| public synchronized void init(Configuration conf) { |
| counter++; |
| callSequenceNumber = counter; |
| super.init(conf); |
| } |
| |
| @Override |
| public synchronized void start() { |
| if (throwExceptionOnStart) { |
| throw new YarnException("Fake service start exception"); |
| } |
| counter++; |
| callSequenceNumber = counter; |
| super.start(); |
| } |
| |
| @Override |
| public synchronized void stop() { |
| counter++; |
| callSequenceNumber = counter; |
| if (throwExceptionOnStop) { |
| throw new YarnException("Fake service stop exception"); |
| } |
| super.stop(); |
| } |
| |
| public static int getCounter() { |
| return counter; |
| } |
| |
| public int getCallSequenceNumber() { |
| return callSequenceNumber; |
| } |
| |
| public void reset() { |
| callSequenceNumber = -1; |
| counter = -1; |
| } |
| |
| public static void resetCounter() { |
| counter = -1; |
| } |
| |
| public void setThrowExceptionOnStart(boolean throwExceptionOnStart) { |
| this.throwExceptionOnStart = throwExceptionOnStart; |
| } |
| |
| public void setThrowExceptionOnStop(boolean throwExceptionOnStop) { |
| this.throwExceptionOnStop = throwExceptionOnStop; |
| } |
| |
| @Override |
| public String toString() { |
| return "Service " + getName(); |
| } |
| |
| } |
| |
| public static class ServiceManager extends CompositeService { |
| |
| public void addTestService(CompositeService service) { |
| addService(service); |
| } |
| |
| public ServiceManager(String name) { |
| super(name); |
| } |
| } |
| |
| } |