/* * Copyright © 2015 Cask Data, Inc. * * Licensed 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 co.cask.cdap.common.service; import com.google.common.base.Supplier; import com.google.common.util.concurrent.AbstractIdleService; import com.google.common.util.concurrent.Service; import org.apache.twill.common.Threads; import org.apache.twill.internal.ServiceListenerAdapter; import org.junit.Assert; import org.junit.Test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * */ public class RetryOnStartFailureServiceTest { @Test public void testRetrySucceed() throws InterruptedException { CountDownLatch startLatch = new CountDownLatch(1); Service service = new RetryOnStartFailureService( createServiceSupplier(3, startLatch, new CountDownLatch(1)), RetryStrategies.fixDelay(10, TimeUnit.MILLISECONDS)); service.startAndWait(); Assert.assertTrue(startLatch.await(1, TimeUnit.SECONDS)); } @Test public void testRetryFail() throws InterruptedException { CountDownLatch startLatch = new CountDownLatch(1); Service service = new RetryOnStartFailureService( createServiceSupplier(1000, startLatch, new CountDownLatch(1)), RetryStrategies.limit(10, RetryStrategies.fixDelay(10, TimeUnit.MILLISECONDS))); final CountDownLatch failureLatch = new CountDownLatch(1); service.addListener(new ServiceListenerAdapter() { @Override public void failed(Service.State from, Throwable failure) { failureLatch.countDown(); } }, Threads.SAME_THREAD_EXECUTOR); service.start(); Assert.assertTrue(failureLatch.await(1, TimeUnit.SECONDS)); Assert.assertFalse(startLatch.await(100, TimeUnit.MILLISECONDS)); } @Test (timeout = 5000) public void testFailureStop() throws InterruptedException { // This test the service can be stopped during failure retry CountDownLatch failureLatch = new CountDownLatch(1); Service service = new RetryOnStartFailureService( createServiceSupplier(1000, new CountDownLatch(1), failureLatch), RetryStrategies.fixDelay(10, TimeUnit.MILLISECONDS)); service.startAndWait(); Assert.assertTrue(failureLatch.await(1, TimeUnit.SECONDS)); service.stopAndWait(); } /** * Creates a {@link Supplier} of {@link Service} that the start() call will fail for the first {@code startFailures} * instances that it returns. */ private Supplier<Service> createServiceSupplier(final int startFailures, final CountDownLatch startLatch, final CountDownLatch failureLatch) { return new Supplier<Service>() { private int failures = 0; @Override public Service get() { return new AbstractIdleService() { @Override protected void startUp() throws Exception { if (failures++ < startFailures) { failureLatch.countDown(); throw new RuntimeException("Fail"); } startLatch.countDown(); } @Override protected void shutDown() throws Exception { // No-op } }; } }; } }