@Before
 public void replaceEscapedCustomDfsSink() {
   // Replace the null with a memory buffer that we have a reference to
   SinkFactoryImpl sf = new SinkFactoryImpl();
   sf.setSink(
       "null",
       new SinkBuilder() {
         @Override
         public EventSink build(Context context, String... argv) {
           LOG.info("excapedCustomDfs replaced with MemorySinkSource");
           mem.reset();
           return mem;
         }
       });
   FlumeBuilder.setSinkFactory(sf);
 }
  /**
   * This test has an append that is blocked because a sink inside of a roll always throws an
   * exception. (ex: a down network connection). This test attempts to guarantee that the rotate
   * succeeds in a reasoanble amoutn of time.
   *
   * @throws IOException
   * @throws InterruptedException
   */
  @Test
  public void testRollAppendBlockedDeadlock() throws IOException, InterruptedException {
    final EventSink mock = mock(EventSink.Base.class);
    doNothing().doThrow(new IOException()).when(mock).close();
    final Event e1 = new EventImpl("foo1".getBytes());
    final Event e2 = new EventImpl("foo2".getBytes());
    doThrow(new IOException()).when(mock).append(e1);
    doThrow(new IOException()).when(mock).append(e2);

    SinkFactoryImpl sfi = new SinkFactoryImpl();
    sfi.setSink(
        "rollLock",
        new SinkBuilder() {
          @Override
          public EventSink build(Context context, String... argv) {
            return mock;
          }
        });
    FlumeBuilder.setSinkFactory(sfi);

    final RollSink roll =
        new RollSink(
            LogicalNodeContext.testingContext(),
            "insistentOpen stubbornAppend insistentAppend rollLock",
            1000000,
            1000000);
    final CountDownLatch latch = new CountDownLatch(1);
    // excessively long roll and check times which allow test to force checks.
    Thread t =
        new Thread("blocked append thread") {
          public void run() {
            try {
              roll.open();
              roll.append(e1); // append blocks.
            } catch (InterruptedException e) {
              latch.countDown();
              LOG.error("Exited with expected Exception");
              return;
            } catch (IOException e) {
              LOG.info("Got the unexpected IOException exit", e);
              e.printStackTrace();
            }
            LOG.info("Got the unexpected clean exit");
          }
        };
    t.start();
    // have another thread timeout.
    final CountDownLatch latch2 = new CountDownLatch(1);
    Thread t2 =
        new Thread("roll rotate thread") {
          public void run() {
            try {
              Clock.sleep(1000); // this is imperfect, but wait for append to block.
              roll.rotate();
              roll.close();
            } catch (IOException e) {
              e.printStackTrace();
            } catch (InterruptedException e) {
              e.printStackTrace();
            } finally {
              latch2.countDown();
            }
          }
        };
    t2.start();
    boolean success = latch.await(5, TimeUnit.SECONDS);
    assertTrue(success);

    success = latch2.await(5, TimeUnit.SECONDS);
    assertTrue(success);
  }