Code review comment: you can't guarantee this in the `finally` block. (for example if submitJobDetached failed but the job is actually running)

Code before review:
public void testDuplicateRegistrationFailsJob() throws Exception {
final Deadline deadline = TEST_TIMEOUT.fromNow();
final int numKeys = 256;
JobID jobId = null;
try {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStateBackend(stateBackend);
env.setParallelism(maxParallelism);
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(Integer.MAX_VALUE, 1000L));
DataStream<Tuple2<Integer, Long>> source = env
.addSource(new TestKeyRangeSource(numKeys));
ReducingStateDescriptor<Tuple2<Integer, Long>> reducingState = new ReducingStateDescriptor<>(
"any-name",
new SumReduce(),
source.getType());
final String queryName = "duplicate-me";
final QueryableStateStream<Integer, Tuple2<Integer, Long>> queryableState =
source.keyBy(new KeySelector<Tuple2<Integer, Long>, Integer>() {
private static final long serialVersionUID = -4126824763829132959L;
@Override
public Integer getKey(Tuple2<Integer, Long> value) throws Exception {
return value.f0;
}
}).asQueryableState(queryName, reducingState);
final QueryableStateStream<Integer, Tuple2<Integer, Long>> duplicate =
source.keyBy(new KeySelector<Tuple2<Integer, Long>, Integer>() {
private static final long serialVersionUID = -6265024000462809436L;
@Override
public Integer getKey(Tuple2<Integer, Long> value) throws Exception {
return value.f0;
}
}).asQueryableState(queryName);
JobGraph jobGraph = env.getStreamGraph().getJobGraph();
jobId = jobGraph.getJobID();
final CompletableFuture<TestingJobManagerMessages.JobStatusIs> failedFuture =
notifyWhenJobStatusIs(jobId, JobStatus.FAILED, deadline);
cluster.submitJobDetached(jobGraph);
TestingJobManagerMessages.JobStatusIs jobStatus =
failedFuture.get(deadline.timeLeft().toMillis(), TimeUnit.MILLISECONDS);
assertEquals(JobStatus.FAILED, jobStatus.state());
JobManagerMessages.JobFound jobFound = FutureUtils.toJava(
cluster.getLeaderGateway(deadline.timeLeft())
.ask(new JobManagerMessages.RequestJob(jobId), deadline.timeLeft())
.mapTo(ClassTag$.MODULE$.<JobManagerMessages.JobFound>apply(JobManagerMessages.JobFound.class)))
.get(deadline.timeLeft().toMillis(), TimeUnit.MILLISECONDS);
String failureCause = jobFound.executionGraph().getFailureCause().getExceptionAsString();
assertTrue("Not instance of SuppressRestartsException", failureCause.startsWith("org.apache.flink.runtime.execution.SuppressRestartsException"));
int causedByIndex = failureCause.indexOf("Caused by: ");
String subFailureCause = failureCause.substring(causedByIndex + "Caused by: ".length());
assertTrue("Not caused by IllegalStateException", subFailureCause.startsWith("java.lang.IllegalStateException"));
assertTrue("Exception does not contain registration name", subFailureCause.contains(queryName));
} finally {
if (jobId != null) {
cluster.getLeaderGateway(deadline.timeLeft())
.ask(new JobManagerMessages.CancelJob(jobId), deadline.timeLeft())
.mapTo(ClassTag$.MODULE$.<CancellationSuccess>apply(CancellationSuccess.class));
}
}
}

Line under review: cluster.getLeaderGateway(deadline.timeLeft())

Code after addressing the review:
public void testDuplicateRegistrationFailsJob() throws Exception {
final Deadline deadline = TEST_TIMEOUT.fromNow();
final int numKeys = 256;
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStateBackend(stateBackend);
env.setParallelism(maxParallelism);
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(Integer.MAX_VALUE, 1000L));
DataStream<Tuple2<Integer, Long>> source = env.addSource(new TestKeyRangeSource(numKeys));
ReducingStateDescriptor<Tuple2<Integer, Long>> reducingState = new ReducingStateDescriptor<>(
"any-name",
new SumReduce(),
source.getType());
final String queryName = "duplicate-me";
final QueryableStateStream<Integer, Tuple2<Integer, Long>> queryableState =
source.keyBy(new KeySelector<Tuple2<Integer, Long>, Integer>() {
private static final long serialVersionUID = -4126824763829132959L;
@Override
public Integer getKey(Tuple2<Integer, Long> value) {
return value.f0;
}
}).asQueryableState(queryName, reducingState);
final QueryableStateStream<Integer, Tuple2<Integer, Long>> duplicate =
source.keyBy(new KeySelector<Tuple2<Integer, Long>, Integer>() {
private static final long serialVersionUID = -6265024000462809436L;
@Override
public Integer getKey(Tuple2<Integer, Long> value) {
return value.f0;
}
}).asQueryableState(queryName);
final JobGraph jobGraph = env.getStreamGraph().getJobGraph();
final JobID jobId = jobGraph.getJobID();
final CompletableFuture<TestingJobManagerMessages.JobStatusIs> failedFuture =
notifyWhenJobStatusIs(jobId, JobStatus.FAILED, deadline);
final CompletableFuture<TestingJobManagerMessages.JobStatusIs> cancellationFuture =
notifyWhenJobStatusIs(jobId, JobStatus.CANCELED, deadline);
cluster.submitJobDetached(jobGraph);
try {
final TestingJobManagerMessages.JobStatusIs jobStatus =
failedFuture.get(deadline.timeLeft().toMillis(), TimeUnit.MILLISECONDS);
assertEquals(JobStatus.FAILED, jobStatus.state());
} catch (Exception e) {
if (jobId != null) {
cluster.getLeaderGateway(deadline.timeLeft())
.ask(new JobManagerMessages.CancelJob(jobId), deadline.timeLeft())
.mapTo(ClassTag$.MODULE$.<CancellationSuccess>apply(CancellationSuccess.class));
cancellationFuture.get(deadline.timeLeft().toMillis(), TimeUnit.MILLISECONDS);
}
throw e;
}
JobManagerMessages.JobFound jobFound = FutureUtils.toJava(
cluster.getLeaderGateway(deadline.timeLeft())
.ask(new JobManagerMessages.RequestJob(jobId), deadline.timeLeft())
.mapTo(ClassTag$.MODULE$.<JobManagerMessages.JobFound>apply(JobManagerMessages.JobFound.class)))
.get(deadline.timeLeft().toMillis(), TimeUnit.MILLISECONDS);
String failureCause = jobFound.executionGraph().getFailureCause().getExceptionAsString();
assertEquals(JobStatus.FAILED, jobFound.executionGraph().getState());
assertTrue("Not instance of SuppressRestartsException", failureCause.startsWith("org.apache.flink.runtime.execution.SuppressRestartsException"));
int causedByIndex = failureCause.indexOf("Caused by: ");
String subFailureCause = failureCause.substring(causedByIndex + "Caused by: ".length());
assertTrue("Not caused by IllegalStateException", subFailureCause.startsWith("java.lang.IllegalStateException"));
assertTrue("Exception does not contain registration name", subFailureCause.contains(queryName));
}