/*
* 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.twill.yarn;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import org.apache.twill.api.AbstractTwillRunnable;
import org.apache.twill.api.EventHandler;
import org.apache.twill.api.EventHandlerContext;
import org.apache.twill.api.ResourceSpecification;
import org.apache.twill.api.TwillApplication;
import org.apache.twill.api.TwillController;
import org.apache.twill.api.TwillRunner;
import org.apache.twill.api.TwillSpecification;
import org.apache.twill.api.logging.PrinterLogHandler;
import org.apache.twill.common.Services;
import org.junit.Test;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
*
*/
public final class ProvisionTimeoutTestRun extends BaseYarnTest {
@Test
public void testProvisionTimeout() throws InterruptedException, ExecutionException, TimeoutException {
TwillRunner runner = YarnTestUtils.getTwillRunner();
TwillController controller = runner.prepare(new TimeoutApplication())
.addLogHandler(new PrinterLogHandler(new PrintWriter(System.out, true)))
.start();
// The provision should failed in 30 seconds after AM started, which AM could took a while to start.
// Hence we give 90 seconds max time here.
try {
Services.getCompletionFuture(controller).get(90, TimeUnit.SECONDS);
} finally {
// If it timeout, kill the app as cleanup.
controller.kill();
}
}
/**
* The handler for testing timeout handling.
*/
public static final class Handler extends EventHandler {
private boolean abort;
@Override
protected Map<String, String> getConfigs() {
return ImmutableMap.of("abort", "true");
}
@Override
public void initialize(EventHandlerContext context) {
this.abort = Boolean.parseBoolean(context.getSpecification().getConfigs().get("abort"));
}
@Override
public TimeoutAction launchTimeout(Iterable<TimeoutEvent> timeoutEvents) {
if (abort) {
return TimeoutAction.abort();
} else {
return TimeoutAction.recheck(10, TimeUnit.SECONDS);
}
}
}
/**
* Testing application for timeout.
*/
public static final class TimeoutApplication implements TwillApplication {
@Override
public TwillSpecification configure() {
return TwillSpecification.Builder.with()
.setName("TimeoutApplication")
.withRunnable()
.add(new TimeoutRunnable(),
ResourceSpecification.Builder.with()
.setVirtualCores(1)
.setMemory(8, ResourceSpecification.SizeUnit.GIGA).build())
.noLocalFiles()
.anyOrder()
.withEventHandler(new Handler())
.build();
}
}
/**
* A runnable that do nothing, as it's not expected to get provisioned.
*/
public static final class TimeoutRunnable extends AbstractTwillRunnable {
private final CountDownLatch latch = new CountDownLatch(1);
@Override
public void stop() {
latch.countDown();
}
@Override
public void run() {
// Simply block here
try {
latch.await();
} catch (InterruptedException e) {
throw Throwables.propagate(e);
}
}
}
}