/* * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /** * @test * @bug 4016710 6516099 * @summary check for correct implementation of InputStream.skip{NBytes} */ import java.io.EOFException; import java.io.InputStream; import java.io.IOException; public class Skip { private static final int EOF = -1; private static void dotest(InputStream in, int curpos, long total, long toskip, long expected) throws Exception { try { System.err.println("\n\nCurrently at pos = " + curpos + "\nTotal bytes in the Stream = " + total + "\nNumber of bytes to skip = " + toskip + "\nNumber of bytes that should be skipped = " + expected); long skipped = in.skip(toskip); System.err.println("actual number skipped: "+ skipped); if ((skipped < 0) || (skipped > expected)) { throw new RuntimeException("Unexpected byte count skipped"); } } catch (IOException e) { System.err.println("IOException is thrown: " + e); } catch (Throwable e) { throw new RuntimeException("Unexpected " + e + " is thrown!"); } } private static void dotestExact(MyInputStream in, long curpos, long total, long toskip, boolean expectIOE, boolean expectEOFE) { System.err.println("\n\nCurrently at pos = " + curpos + "\nTotal bytes in the Stream = " + total + "\nNumber of bytes to skip = " + toskip); try { long pos = in.position(); assert pos == curpos : pos + " != " + curpos; in.skipNBytes(toskip); if (in.position() != pos + (toskip < 0 ? 0 : toskip)) { throw new RuntimeException((in.position() - pos) + " bytes skipped; expected " + toskip); } } catch (EOFException eofe) { if (!expectEOFE) { throw new RuntimeException("Unexpected EOFException", eofe); } System.err.println("Caught expected EOFException"); } catch (IOException ioe) { if (!expectIOE) { throw new RuntimeException("Unexpected IOException", ioe); } System.err.println("Caught expected IOException"); } } public static void main( String argv[] ) throws Exception { MyInputStream in = new MyInputStream(11); // test for negative skip dotest(in, 0, 11, -23, 0); // check for skip beyond EOF starting from before EOF dotest(in, 0, 11, 20, 11); // check for skip after EOF dotest(in, EOF, 11, 20, 0); in = new MyInputStream(9000); // check for skip equal to the read chunk size in InputStream.java dotest(in, 0, 9000, 2048, 2048); // check for skip larger than the read chunk size in InputStream.java dotest(in, 2048, 9000, 5000, 5000); // check for skip beyond EOF starting from before EOF dotest(in, 7048, 9000, 5000, 1952); in = new MyInputStream(5000); // check for multiple chunk reads dotest(in, 0, 5000, 6000, 5000); /* * check for skip larger than Integer.MAX_VALUE * (Takes about 2 hrs on a sparc ultra-1) * long total = (long)Integer.MAX_VALUE + (long)10; * long toskip = total - (long)6; * in = new MyInputStream(total); * dotest(in, 0, total, toskip, toskip); */ // tests for skipping an exact number of bytes final long streamLength = Long.MAX_VALUE; in = new MyInputStream(streamLength); // negative skip: OK dotestExact(in, 0, streamLength, -1, false, false); // negative skip at EOF: OK in.position(streamLength); dotestExact(in, streamLength, streamLength, -1, false, false); in.position(0); // zero skip: OK dotestExact(in, 0, streamLength, 0, false, false); // zero skip at EOF: OK in.position(streamLength); dotestExact(in, streamLength, streamLength, 0, false, false); // skip(1) at EOF: EOFE dotestExact(in, streamLength, streamLength, 1, false, true); in.position(0); final long n = 31; // skip count long pos = 0; // skip(n) returns negative value: IOE in.setState(-1, 100); dotestExact(in, pos, streamLength, -1, true, false); // skip(n) returns n + 1: IOE in.setState(n + 1, 100); dotestExact(in, pos, streamLength, n, true, false); pos += n + 1; // skip(n) returns n/2 but only n/4 subsequent reads succeed: EOFE in.setState(n/2, n/2 + n/4); dotestExact(in, pos, streamLength, n, false, true); pos += n/2 + n/4; // skip(n) returns n/2 but n - n/2 subsequent reads succeed: OK in.setState(n/2, n); dotestExact(in, pos, streamLength, n, false, false); pos += n; } } class MyInputStream extends InputStream { private static final int EOF = -1; private final long endoffile; private long readctr = 0; private boolean isStateSet = false; private long skipReturn; private long readLimit; public MyInputStream(long endoffile) { this.endoffile = endoffile; } /** * Limits the behavior of skip() and read(). * * @param skipReturn the value to be returned by skip() * @param maxReads the maximum number of reads past the current position * before EOF is reached */ public void setState(long skipReturn, long maxReads) { this.skipReturn = skipReturn; this.readLimit = readctr + maxReads; isStateSet = true; } public int read() { if (readctr == endoffile || (isStateSet && readctr >= readLimit)) { return EOF; } else { readctr++; return 0; } } public int available() { return 0; } public long position() { return readctr; } public void position(long pos) { readctr = pos < 0 ? 0 : Math.min(pos, endoffile); } public long skip(long n) throws IOException { if (isStateSet) { return super.skip(skipReturn); } // InputStream skip implementation. return super.skip(n); // readctr is implicitly incremented } }