1 /* 2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package test.java.io.InputStream; 24 25 import org.testng.annotations.Test; 26 27 /** 28 * @test 29 * @bug 4016710 6516099 30 * @summary check for correct implementation of InputStream.skip{NBytes} 31 */ 32 33 import java.io.EOFException; 34 import java.io.InputStream; 35 import java.io.IOException; 36 37 public class Skip { 38 private static final int EOF = -1; 39 dotest(InputStream in, int curpos, long total, long toskip, long expected)40 private static void dotest(InputStream in, int curpos, long total, 41 long toskip, long expected) throws Exception { 42 try { 43 System.err.println("\n\nCurrently at pos = " + curpos + 44 "\nTotal bytes in the Stream = " + total + 45 "\nNumber of bytes to skip = " + toskip + 46 "\nNumber of bytes that should be skipped = " + 47 expected); 48 49 long skipped = in.skip(toskip); 50 51 System.err.println("actual number skipped: "+ skipped); 52 53 if ((skipped < 0) || (skipped > expected)) { 54 throw new RuntimeException("Unexpected byte count skipped"); 55 } 56 } catch (IOException e) { 57 System.err.println("IOException is thrown: " + e); 58 } catch (Throwable e) { 59 throw new RuntimeException("Unexpected " + e + " is thrown!"); 60 } 61 } 62 dotestExact(MyInputStream in, long curpos, long total, long toskip, boolean expectIOE, boolean expectEOFE)63 private static void dotestExact(MyInputStream in, long curpos, long total, 64 long toskip, boolean expectIOE, boolean expectEOFE) { 65 66 System.err.println("\n\nCurrently at pos = " + curpos + 67 "\nTotal bytes in the Stream = " + total + 68 "\nNumber of bytes to skip = " + toskip); 69 70 try { 71 long pos = in.position(); 72 assert pos == curpos : pos + " != " + curpos; 73 in.skipNBytes(toskip); 74 if (in.position() != pos + (toskip < 0 ? 0 : toskip)) { 75 throw new RuntimeException((in.position() - pos) + 76 " bytes skipped; expected " + toskip); 77 } 78 } catch (EOFException eofe) { 79 if (!expectEOFE) { 80 throw new RuntimeException("Unexpected EOFException", eofe); 81 } 82 System.err.println("Caught expected EOFException"); 83 } catch (IOException ioe) { 84 if (!expectIOE) { 85 throw new RuntimeException("Unexpected IOException", ioe); 86 } 87 System.err.println("Caught expected IOException"); 88 } 89 } 90 91 @Test testSkip()92 public void testSkip() throws Exception { 93 MyInputStream in = new MyInputStream(11); 94 95 // test for negative skip 96 dotest(in, 0, 11, -23, 0); 97 98 // check for skip beyond EOF starting from before EOF 99 dotest(in, 0, 11, 20, 11); 100 101 // check for skip after EOF 102 dotest(in, EOF, 11, 20, 0); 103 104 in = new MyInputStream(9000); 105 106 // check for skip equal to the read chunk size in InputStream.java 107 dotest(in, 0, 9000, 2048, 2048); 108 109 // check for skip larger than the read chunk size in InputStream.java 110 dotest(in, 2048, 9000, 5000, 5000); 111 112 // check for skip beyond EOF starting from before EOF 113 dotest(in, 7048, 9000, 5000, 1952); 114 115 in = new MyInputStream(5000); 116 117 // check for multiple chunk reads 118 dotest(in, 0, 5000, 6000, 5000); 119 120 /* 121 * check for skip larger than Integer.MAX_VALUE 122 * (Takes about 2 hrs on a sparc ultra-1) 123 * long total = (long)Integer.MAX_VALUE + (long)10; 124 * long toskip = total - (long)6; 125 * in = new MyInputStream(total); 126 * dotest(in, 0, total, toskip, toskip); 127 */ 128 129 // tests for skipping an exact number of bytes 130 131 final long streamLength = Long.MAX_VALUE; 132 in = new MyInputStream(streamLength); 133 134 // negative skip: OK 135 dotestExact(in, 0, streamLength, -1, false, false); 136 137 // negative skip at EOF: OK 138 in.position(streamLength); 139 dotestExact(in, streamLength, streamLength, -1, false, false); 140 in.position(0); 141 142 // zero skip: OK 143 dotestExact(in, 0, streamLength, 0, false, false); 144 145 // zero skip at EOF: OK 146 in.position(streamLength); 147 dotestExact(in, streamLength, streamLength, 0, false, false); 148 149 // skip(1) at EOF: EOFE 150 dotestExact(in, streamLength, streamLength, 1, false, true); 151 in.position(0); 152 153 final long n = 31; // skip count 154 long pos = 0; 155 156 // skip(n) returns negative value: IOE 157 in.setState(-1, 100); 158 dotestExact(in, pos, streamLength, n, true, false); 159 160 // skip(n) returns n + 1: IOE 161 in.setState(n + 1, 100); 162 dotestExact(in, pos, streamLength, n, true, false); 163 pos += n + 1; 164 165 // skip(n) returns n/2 but only n/4 subsequent reads succeed: EOFE 166 in.setState(n/2, n/2 + n/4); 167 dotestExact(in, pos, streamLength, n, false, true); 168 pos += n/2 + n/4; 169 170 // skip(n) returns n/2 but n - n/2 subsequent reads succeed: OK 171 in.setState(n/2, n); 172 dotestExact(in, pos, streamLength, n, false, false); 173 pos += n; 174 } 175 } 176 177 class MyInputStream extends InputStream { 178 private static final int EOF = -1; 179 180 private final long endoffile; 181 182 private long readctr = 0; 183 184 private boolean isStateSet = false; 185 private long skipReturn; 186 private long readLimit; 187 MyInputStream(long endoffile)188 public MyInputStream(long endoffile) { 189 this.endoffile = endoffile; 190 } 191 192 /** 193 * Limits the behavior of skip() and read(). 194 * 195 * @param skipReturn the value to be returned by skip() 196 * @param maxReads the maximum number of reads past the current position 197 * before EOF is reached 198 */ setState(long skipReturn, long maxReads)199 public void setState(long skipReturn, long maxReads) { 200 this.skipReturn = skipReturn; 201 this.readLimit = readctr + maxReads; 202 isStateSet = true; 203 } 204 read()205 public int read() { 206 if (readctr == endoffile || 207 (isStateSet && readctr >= readLimit)) { 208 return EOF; 209 } 210 else { 211 readctr++; 212 return 0; 213 } 214 } 215 available()216 public int available() { return 0; } 217 position()218 public long position() { return readctr; } 219 position(long pos)220 public void position(long pos) { 221 readctr = pos < 0 ? 0 : Math.min(pos, endoffile); 222 } 223 224 public long skip(long n) throws IOException { 225 if (isStateSet) { 226 return skipReturn < 0 ? skipReturn : super.skip(skipReturn); 227 } 228 229 // InputStream skip implementation. 230 return super.skip(n); // readctr is implicitly incremented 231 } 232 } 233