Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      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.google.common.io;
     18 
     19 import static org.easymock.EasyMock.createStrictMock;
     20 import static org.easymock.EasyMock.expectLastCall;
     21 import static org.easymock.EasyMock.replay;
     22 import static org.easymock.EasyMock.reset;
     23 import static org.easymock.EasyMock.verify;
     24 
     25 import junit.framework.TestCase;
     26 
     27 import java.io.Closeable;
     28 import java.io.Flushable;
     29 import java.io.IOException;
     30 
     31 /**
     32  * Unit tests for {@link Closeables} and {@link Flushables}.
     33  *
     34  * <p>Checks proper closing and flushing behavior, and ensures that
     35  * IOExceptions on Closeable.close() or Flushable.flush() are not
     36  * propagated out from the {@link Closeables#close} method if {@code
     37  * swallowException} is true.
     38  *
     39  * @author Michael Lancaster
     40  */
     41 public class CloseablesTest extends TestCase {
     42   private Closeable mockCloseable;
     43   private Flushable mockFlushable;
     44 
     45   public void testClose_closeableClean() throws IOException {
     46     // make sure that no exception is thrown regardless of value of
     47     // 'swallowException' when the mock does not throw an exception.
     48     setupCloseable(false);
     49     doClose(mockCloseable, false, false);
     50 
     51     setupCloseable(false);
     52     doClose(mockCloseable, true, false);
     53   }
     54 
     55   public void testClose_closeableWithEatenException() throws IOException {
     56     // make sure that no exception is thrown if 'swallowException' is true
     57     // when the mock does throw an exception.
     58     setupCloseable(true);
     59     doClose(mockCloseable, true);
     60   }
     61 
     62   public void testClose_closeableWithThrownException() throws IOException {
     63     // make sure that the exception is thrown if 'swallowException' is false
     64     // when the mock does throw an exception.
     65     setupCloseable(true);
     66     doClose(mockCloseable, false);
     67   }
     68 
     69   public void testCloseQuietly_closeableWithEatenException()
     70       throws IOException {
     71     // make sure that no exception is thrown by CloseQuietly when the mock does
     72     // throw an exception, either on close, on flush, or both.
     73     setupCloseable(true);
     74     Closeables.closeQuietly(mockCloseable);
     75   }
     76 
     77   public void testFlush_clean() throws IOException {
     78     // make sure that no exception is thrown regardless of value of
     79     // 'swallowException' when the mock does not throw an exception.
     80     setupFlushable(false);
     81     doFlush(mockFlushable, false, false);
     82 
     83     setupFlushable(false);
     84     doFlush(mockFlushable, true, false);
     85   }
     86 
     87   public void testFlush_flushableWithEatenException() throws IOException {
     88     // make sure that no exception is thrown if 'swallowException' is true
     89     // when the mock does throw an exception on flush.
     90     setupFlushable(true);
     91     doFlush(mockFlushable, true, false);
     92   }
     93 
     94   public void testFlush_flushableWithThrownException() throws IOException {
     95     // make sure that the exception is thrown if 'swallowException' is false
     96     // when the mock does throw an exception on flush.
     97     setupFlushable(true);
     98     doFlush(mockFlushable, false, true);
     99   }
    100 
    101   public void testFlushQuietly_flushableWithEatenException()
    102       throws IOException {
    103     // make sure that no exception is thrown by CloseQuietly when the mock does
    104     // throw an exception on flush.
    105     setupFlushable(true);
    106     Flushables.flushQuietly(mockFlushable);
    107   }
    108 
    109   public void testCloseNull() throws IOException {
    110     Closeables.close(null, true);
    111     Closeables.close(null, false);
    112     Closeables.closeQuietly(null);
    113   }
    114 
    115   @Override protected void setUp() throws Exception {
    116     mockCloseable = createStrictMock(Closeable.class);
    117     mockFlushable = createStrictMock(Flushable.class);
    118   }
    119 
    120   private void expectThrown() {
    121     expectLastCall().andThrow(new IOException("This should only appear in the "
    122         + "logs. It should not be rethrown."));
    123   }
    124 
    125   // Set up a closeable to expect to be closed, and optionally to throw an
    126   // exception.
    127   private void setupCloseable(boolean shouldThrow) throws IOException {
    128     reset(mockCloseable);
    129     mockCloseable.close();
    130     if (shouldThrow) {
    131       expectThrown();
    132     }
    133     replay(mockCloseable);
    134   }
    135 
    136   // Set up a flushable to expect to be flushed and closed, and optionally to
    137   // throw an exception.
    138   private void setupFlushable(boolean shouldThrowOnFlush) throws IOException {
    139     reset(mockFlushable);
    140     mockFlushable.flush();
    141     if (shouldThrowOnFlush) {
    142       expectThrown();
    143     }
    144     replay(mockFlushable);
    145   }
    146 
    147   private void doClose(Closeable closeable, boolean swallowException) {
    148     doClose(closeable, swallowException, !swallowException);
    149   }
    150 
    151   // Close the closeable using the Closeables, passing in the swallowException
    152   // parameter. expectThrown determines whether we expect an exception to
    153   // be thrown by Closeables.close;
    154   private void doClose(Closeable closeable, boolean swallowException,
    155       boolean expectThrown) {
    156     try {
    157       Closeables.close(closeable, swallowException);
    158       if (expectThrown) {
    159         fail("Didn't throw exception.");
    160       }
    161     } catch (IOException e) {
    162       if (!expectThrown) {
    163         fail("Threw exception");
    164       }
    165     }
    166     verify(closeable);
    167   }
    168 
    169   // Flush the flushable using the Flushables, passing in the swallowException
    170   // parameter. expectThrown determines whether we expect an exception to
    171   // be thrown by Flushables.flush;
    172   private void doFlush(Flushable flushable, boolean swallowException,
    173       boolean expectThrown) {
    174     try {
    175       Flushables.flush(flushable, swallowException);
    176       if (expectThrown) {
    177         fail("Didn't throw exception.");
    178       }
    179     } catch (IOException e) {
    180       if (!expectThrown) {
    181         fail("Threw exception");
    182       }
    183     }
    184     verify(flushable);
    185   }
    186 }
    187