/*****************************************************************************
* ------------------------------------------------------------------------- *
* 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 com.google.mu.util;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import com.google.common.testing.ClassSanityTester;
import com.google.mu.util.ExceptionPlan;
import com.google.mu.util.Maybe;
@RunWith(JUnit4.class)
public class ExceptionPlanTest {
@Test public void emptyPlan_errorPropagation() {
ExceptionPlan<String> plan = new ExceptionPlan<>();
MyError error = new MyError();
Maybe<ExceptionPlan.Execution<String>, MyError> maybe = plan.execute(error);
assertSame(error, assertThrows(MyError.class, () -> maybe.orElseThrow(e -> e)));
}
@Test public void emptyPlan_uncheckedPropagation() {
ExceptionPlan<String> plan = new ExceptionPlan<>();
RuntimeException exception = new RuntimeException("test");
Maybe<ExceptionPlan.Execution<String>, RuntimeException> maybe = plan.execute(exception);
assertSame(exception, assertThrows(RuntimeException.class, () -> maybe.orElseThrow(e -> e)));
}
@Test public void emptyPlan_checkedPropagation() {
ExceptionPlan<String> plan = new ExceptionPlan<>();
Exception exception = new Exception("test");
Maybe<ExceptionPlan.Execution<String>, Exception> maybe = plan.execute(exception);
assertSame(exception, assertThrows(Exception.class, () -> maybe.orElseThrow(e -> e)));
}
@Test public void planWithZeroStrategies() {
ExceptionPlan<String> plan = new ExceptionPlan<String>()
.upon(Exception.class, asList());
Exception exception = new Exception("test");
Maybe<ExceptionPlan.Execution<String>, Exception> maybe = plan.execute(exception);
assertSame(exception, assertThrows(Exception.class, () -> maybe.orElseThrow(e -> e)));
}
@Test public void planWithStrategies() throws Exception {
ExceptionPlan<String> plan = new ExceptionPlan<String>()
.upon(Exception.class, asList("retry", "report"));
Exception exception = new Exception("test");
ExceptionPlan.Execution<String> execution = plan.execute(exception).orElseThrow();
assertThat(execution.strategy()).isEqualTo("retry");
execution = execution.remainingExceptionPlan().execute(exception).orElseThrow();
assertThat(execution.strategy()).isEqualTo("report");
Maybe<ExceptionPlan.Execution<String>, Exception> maybe =
execution.remainingExceptionPlan().execute(exception);
assertSame(exception, assertThrows(Exception.class, () -> maybe.orElseThrow(e -> e)));
}
@Test public void planWithPartiallyOverlappingRules() throws Exception {
ExceptionPlan<String> plan = new ExceptionPlan<String>()
.upon(MyException.class, asList("report"))
.upon(Exception.class, asList("report", "report"));
MyException myException = new MyException();
ExceptionPlan.Execution<String> execution = plan.execute(myException).orElseThrow();
assertThat(execution.strategy()).isEqualTo("report");
Maybe<ExceptionPlan.Execution<String>, Exception> maybe =
execution.remainingExceptionPlan().execute(myException);
assertSame(myException, assertThrows(MyException.class, () -> maybe.orElseThrow(e -> e)));
assertThat(plan.execute(new Exception("test")).orElseThrow().strategy()).isEqualTo("report");
}
@Test public void withTypedPredicate() throws Exception {
ExceptionPlan<String> plan = new ExceptionPlan<String>()
.upon(Exception.class, e -> "recoverable".equals(e.getMessage()), asList("recover"))
.upon(Exception.class, asList("report"));
MyError error = new MyError();
assertSame(error, assertThrows(MyError.class, () -> plan.execute(error).orElseThrow(e -> e)));
ExceptionPlan.Execution<String> execution =
plan.execute(new Exception("recoverable")).orElseThrow();
assertThat(execution.strategy()).isEqualTo("recover");
execution = plan.execute(new Exception("bad")).orElseThrow();
assertThat(execution.strategy()).isEqualTo("report");
}
@Test public void withPredicate() throws Exception {
ExceptionPlan<String> plan = new ExceptionPlan<String>()
.upon(e -> "recoverable".equals(e.getMessage()), asList("recover"))
.upon(Exception.class, asList("report"));
MyError error = new MyError();
assertSame(error, assertThrows(MyError.class, () -> plan.execute(error).orElseThrow(e -> e)));
ExceptionPlan.Execution<String> execution =
plan.execute(new Exception("recoverable")).orElseThrow();
assertThat(execution.strategy()).isEqualTo("recover");
execution = plan.execute(new Exception("bad")).orElseThrow();
assertThat(execution.strategy()).isEqualTo("report");
}
@Test public void testNulls() {
new ClassSanityTester().testNulls(ExceptionPlan.class);
}
@SuppressWarnings("serial")
private static class MyException extends Exception {}
@SuppressWarnings("serial")
private static class MyError extends Error {}
}