/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package ddf.catalog.cache; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MockInputStream extends InputStream { private static final Logger LOGGER = LoggerFactory.getLogger(MockInputStream.class); private int invocationCount = 0; private InputStream is; // Parameters to configure failures for testing private int invocationCountToThrowIOException = -1; private int invocationCountToTimeout = -1; private long readDelay = 0; private TimeUnit timeUnit; private boolean readSlow; public MockInputStream(String name) { this(name, false); } public MockInputStream(String name, boolean readSlow) { try { this.is = new FileInputStream(name); } catch (FileNotFoundException e) { LOGGER.info("FileNotFoundException", e); } this.readSlow = readSlow; } public void setInvocationCountToThrowIOException(int count) { invocationCountToThrowIOException = count; } public void setInvocationCountToTimeout(int count) { invocationCountToTimeout = count; } public void setReadDelay(long delay, TimeUnit timeUnit) { this.readDelay = delay; this.timeUnit = timeUnit; } @Override public int available() throws IOException { return is.available(); } @Override public int read() throws IOException { return is.read(); } @Override public int read(byte[] buffer) throws IOException { invocationCount++; if (invocationCount == invocationCountToThrowIOException) { LOGGER.info("Simulating read exception by closing inputstream"); // Simulates IOException while reading from the remote source. // By closing stream, when try to read from it an IOException will be thrown. is.close(); } else if (invocationCount == invocationCountToTimeout) { LOGGER.info("Simulating read taking too long by sleeping for {} ms", timeUnit.toMillis(readDelay)); try { // Simulates read of InputStream chunk from remote source taking // longer than the timeout for each chunk to be read if (readDelay > 0) { timeUnit.sleep(readDelay); } } catch (InterruptedException e) { LOGGER.info("Thread sleep interrupted"); return 0; } LOGGER.info("Simulated read timeout completed"); } else if (readSlow && readDelay > 0L) { try { // Slows down reading of product input stream so that client // has time to come up if (readDelay > 0) { timeUnit.sleep(readDelay); } } catch (InterruptedException e) { LOGGER.info("Thread sleep interrupted"); return 0; } } return super.read(buffer); } @Override public int read(byte[] buffer, int startPos, int len) throws IOException { return super.read(buffer, startPos, len); } }