Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.compatibility.common.util;
     18 
     19 import static com.google.common.truth.Truth.assertThat;
     20 
     21 import static org.mockito.Mockito.verify;
     22 import static org.testng.Assert.expectThrows;
     23 
     24 import com.android.compatibility.common.util.SafeCleanerRule.Dumper;
     25 
     26 import com.google.common.collect.ImmutableList;
     27 
     28 import org.junit.AssumptionViolatedException;
     29 import org.junit.Test;
     30 import org.junit.runner.Description;
     31 import org.junit.runner.RunWith;
     32 import org.junit.runners.model.Statement;
     33 import org.mockito.Mock;
     34 import org.mockito.junit.MockitoJUnitRunner;
     35 
     36 import java.util.List;
     37 import java.util.concurrent.Callable;
     38 
     39 @RunWith(MockitoJUnitRunner.class)
     40 public class SafeCleanerRuleTest {
     41 
     42     private static class FailureStatement extends Statement {
     43         private final Throwable mThrowable;
     44 
     45         FailureStatement(Throwable t) {
     46             mThrowable = t;
     47         }
     48 
     49         @Override
     50         public void evaluate() throws Throwable {
     51             throw mThrowable;
     52         }
     53     }
     54 
     55     private final Description mDescription = Description.createSuiteDescription("Whatever");
     56     private final RuntimeException mRuntimeException = new RuntimeException("D'OH!");
     57 
     58     @Mock private Dumper mDumper;
     59 
     60     // Use mocks for objects that don't throw any exception.
     61     @Mock private ThrowingRunnable mGoodGuyRunner1;
     62     @Mock private ThrowingRunnable mGoodGuyRunner2;
     63     @Mock private Callable<List<Throwable>> mGoodGuyExtraExceptions1;
     64     @Mock private Callable<List<Throwable>> mGoodGuyExtraExceptions2;
     65     @Mock private Statement mGoodGuyStatement;
     66 
     67     @Test
     68     public void testEmptyRule_testPass() throws Throwable {
     69         final SafeCleanerRule rule = new SafeCleanerRule();
     70         rule.apply(mGoodGuyStatement, mDescription).evaluate();
     71     }
     72 
     73     @Test
     74     public void testEmptyRule_testFails() throws Throwable {
     75         final SafeCleanerRule rule = new SafeCleanerRule();
     76         final Throwable actualException = expectThrows(RuntimeException.class,
     77                 () -> rule.apply(new FailureStatement(mRuntimeException), mDescription).evaluate());
     78         assertThat(actualException).isSameAs(mRuntimeException);
     79     }
     80 
     81     @Test
     82     public void testEmptyRule_testFails_withDumper() throws Throwable {
     83         final SafeCleanerRule rule = new SafeCleanerRule().setDumper(mDumper);
     84         final Throwable actualException = expectThrows(RuntimeException.class,
     85                 () -> rule.apply(new FailureStatement(mRuntimeException), mDescription).evaluate());
     86         assertThat(actualException).isSameAs(mRuntimeException);
     87         verify(mDumper).dump("Whatever", actualException);
     88     }
     89 
     90     @Test
     91     public void testOnlyTestFails() throws Throwable {
     92         final SafeCleanerRule rule = new SafeCleanerRule()
     93                 .run(mGoodGuyRunner1)
     94                 .add(mGoodGuyExtraExceptions1);
     95         final Throwable actualException = expectThrows(RuntimeException.class,
     96                 () -> rule.apply(new FailureStatement(mRuntimeException), mDescription).evaluate());
     97         assertThat(actualException).isSameAs(mRuntimeException);
     98         verify(mGoodGuyRunner1).run();
     99         verify(mGoodGuyExtraExceptions1).call();
    100     }
    101 
    102     @Test
    103     public void testOnlyTestFails_withDumper() throws Throwable {
    104         final SafeCleanerRule rule = new SafeCleanerRule()
    105                 .setDumper(mDumper)
    106                 .run(mGoodGuyRunner1)
    107                 .add(mGoodGuyExtraExceptions1);
    108         final Throwable actualException = expectThrows(RuntimeException.class,
    109                 () -> rule.apply(new FailureStatement(mRuntimeException), mDescription).evaluate());
    110         assertThat(actualException).isSameAs(mRuntimeException);
    111         verify(mGoodGuyRunner1).run();
    112         verify(mGoodGuyExtraExceptions1).call();
    113         verify(mDumper).dump("Whatever", actualException);
    114     }
    115 
    116     @Test
    117     public void testTestPass_oneRunnerFails() throws Throwable {
    118         final SafeCleanerRule rule = new SafeCleanerRule()
    119                 .run(mGoodGuyRunner1)
    120                 .run(() -> { throw mRuntimeException; })
    121                 .run(mGoodGuyRunner2)
    122                 .add(mGoodGuyExtraExceptions1);
    123         final Throwable actualException = expectThrows(RuntimeException.class,
    124                 () -> rule.apply(mGoodGuyStatement, mDescription).evaluate());
    125         assertThat(actualException).isSameAs(mRuntimeException);
    126         verify(mGoodGuyRunner1).run();
    127         verify(mGoodGuyRunner2).run();
    128         verify(mGoodGuyExtraExceptions1).call();
    129     }
    130 
    131     @Test
    132     public void testTestPass_oneRunnerFails_withDumper() throws Throwable {
    133         final SafeCleanerRule rule = new SafeCleanerRule()
    134                 .setDumper(mDumper)
    135                 .run(mGoodGuyRunner1)
    136                 .run(() -> {
    137                     throw mRuntimeException;
    138                 })
    139                 .run(mGoodGuyRunner2)
    140                 .add(mGoodGuyExtraExceptions1);
    141         final Throwable actualException = expectThrows(RuntimeException.class,
    142                 () -> rule.apply(mGoodGuyStatement, mDescription).evaluate());
    143         assertThat(actualException).isSameAs(mRuntimeException);
    144         verify(mGoodGuyRunner1).run();
    145         verify(mGoodGuyRunner2).run();
    146         verify(mGoodGuyExtraExceptions1).call();
    147         verify(mDumper).dump("Whatever", actualException);
    148     }
    149 
    150     @Test
    151     public void testTestPass_oneExtraExceptionThrownAsCallable() throws Throwable {
    152         final SafeCleanerRule rule = new SafeCleanerRule()
    153                 .run(mGoodGuyRunner1)
    154                 .add(mRuntimeException)
    155                 .add(mGoodGuyExtraExceptions1)
    156                 .run(mGoodGuyRunner2);
    157         final Throwable actualException = expectThrows(RuntimeException.class,
    158                 () -> rule.apply(mGoodGuyStatement, mDescription).evaluate());
    159         assertThat(actualException).isSameAs(mRuntimeException);
    160         verify(mGoodGuyRunner1).run();
    161         verify(mGoodGuyRunner2).run();
    162         verify(mGoodGuyExtraExceptions1).call();
    163     }
    164 
    165     @Test
    166     public void testTestPass_oneExtraExceptionThrown() throws Throwable {
    167         final SafeCleanerRule rule = new SafeCleanerRule()
    168                 .run(mGoodGuyRunner1)
    169                 .add(() -> {
    170                     return ImmutableList.of(mRuntimeException);
    171                 })
    172                 .add(mGoodGuyExtraExceptions1)
    173                 .run(mGoodGuyRunner2);
    174         final Throwable actualException = expectThrows(RuntimeException.class,
    175                 () -> rule.apply(mGoodGuyStatement, mDescription).evaluate());
    176         assertThat(actualException).isSameAs(mRuntimeException);
    177         verify(mGoodGuyRunner1).run();
    178         verify(mGoodGuyRunner2).run();
    179         verify(mGoodGuyExtraExceptions1).call();
    180     }
    181 
    182     @Test
    183     public void testTestPass_oneExtraExceptionThrown_withDumper() throws Throwable {
    184         final SafeCleanerRule rule = new SafeCleanerRule()
    185                 .setDumper(mDumper)
    186                 .run(mGoodGuyRunner1)
    187                 .add(() -> { return ImmutableList.of(mRuntimeException); })
    188                 .add(mGoodGuyExtraExceptions1)
    189                 .run(mGoodGuyRunner2);
    190         final Throwable actualException = expectThrows(RuntimeException.class,
    191                 () -> rule.apply(mGoodGuyStatement, mDescription).evaluate());
    192         assertThat(actualException).isSameAs(mRuntimeException);
    193         verify(mGoodGuyRunner1).run();
    194         verify(mGoodGuyRunner2).run();
    195         verify(mGoodGuyExtraExceptions1).call();
    196         verify(mDumper).dump("Whatever", actualException);
    197     }
    198 
    199     @Test
    200     public void testThrowTheKitchenSinkAKAEverybodyThrows() throws Throwable {
    201         final Exception extra1 = new Exception("1");
    202         final Exception extra2 = new Exception("2");
    203         final Exception extra3 = new Exception("3");
    204         final Error error1 = new Error("one");
    205         final Error error2 = new Error("two");
    206         final RuntimeException testException  = new RuntimeException("TEST, Y U NO PASS?");
    207         final SafeCleanerRule rule = new SafeCleanerRule()
    208                 .run(mGoodGuyRunner1)
    209                 .add(mGoodGuyExtraExceptions1)
    210                 .add(mRuntimeException)
    211                 .add(() -> {
    212                     return ImmutableList.of(extra1, extra2);
    213                 })
    214                 .run(() -> {
    215                     throw error1;
    216                 })
    217                 .run(mGoodGuyRunner2)
    218                 .add(() -> {
    219                     return ImmutableList.of(extra3);
    220                 })
    221                 .add(mGoodGuyExtraExceptions2)
    222                 .run(() -> {
    223                     throw error2;
    224                 });
    225 
    226         final SafeCleanerRule.MultipleExceptions actualException = expectThrows(
    227                 SafeCleanerRule.MultipleExceptions.class,
    228                 () -> rule.apply(new FailureStatement(testException), mDescription).evaluate());
    229         assertThat(actualException.getThrowables())
    230                 .containsExactly(testException, mRuntimeException, error1, error2, extra1, extra2,
    231                         extra3)
    232                 .inOrder();
    233         verify(mGoodGuyRunner1).run();
    234         verify(mGoodGuyRunner2).run();
    235         verify(mGoodGuyExtraExceptions1).call();
    236     }
    237 
    238     @Test
    239     public void testIgnoreAssumptionViolatedException() throws Throwable {
    240         final AssumptionViolatedException ave = new AssumptionViolatedException(
    241                 "tis an assumption violation");
    242         final RuntimeException testException  = new RuntimeException("TEST, Y U NO PASS?");
    243         final SafeCleanerRule rule = new SafeCleanerRule()
    244                 .run(mGoodGuyRunner1)
    245                 .add(mRuntimeException)
    246                 .run(() -> {
    247                     throw ave;
    248                 });
    249 
    250         final SafeCleanerRule.MultipleExceptions actualException = expectThrows(
    251                 SafeCleanerRule.MultipleExceptions.class,
    252                 () -> rule.apply(new FailureStatement(testException), mDescription).evaluate());
    253         assertThat(actualException.getThrowables())
    254                 .containsExactly(testException, mRuntimeException)
    255                 .inOrder();
    256         verify(mGoodGuyRunner1).run();
    257     }
    258 
    259     @Test
    260     public void testThrowTheKitchenSinkAKAEverybodyThrows_withDumper() throws Throwable {
    261         final Exception extra1 = new Exception("1");
    262         final Exception extra2 = new Exception("2");
    263         final Exception extra3 = new Exception("3");
    264         final Exception extra4 = new Exception("4");
    265         final Error error1 = new Error("one");
    266         final Error error2 = new Error("two");
    267         final RuntimeException testException  = new RuntimeException("TEST, Y U NO PASS?");
    268         final SafeCleanerRule rule = new SafeCleanerRule()
    269                 .setDumper(mDumper)
    270                 .run(mGoodGuyRunner1)
    271                 .add(mGoodGuyExtraExceptions1)
    272                 .add(() -> {
    273                     return ImmutableList.of(extra1, extra2);
    274                 })
    275                 .run(() -> {
    276                     throw error1;
    277                 })
    278                 .run(mGoodGuyRunner2)
    279                 .add(() -> { return ImmutableList.of(extra3); })
    280                 .add(mGoodGuyExtraExceptions2)
    281                 .run(() -> {
    282                     throw error2;
    283                 })
    284                 .run(() -> {
    285                     throw extra4;
    286                 });
    287 
    288         final SafeCleanerRule.MultipleExceptions actualException = expectThrows(
    289                 SafeCleanerRule.MultipleExceptions.class,
    290                 () -> rule.apply(new FailureStatement(testException), mDescription).evaluate());
    291         assertThat(actualException.getThrowables())
    292                 .containsExactly(testException, error1, error2, extra4, extra1, extra2, extra3)
    293                 .inOrder();
    294         verify(mGoodGuyRunner1).run();
    295         verify(mGoodGuyRunner2).run();
    296         verify(mGoodGuyExtraExceptions1).call();
    297         verify(mDumper).dump("Whatever", actualException);
    298     }
    299 }
    300