1 /* 2 * Copyright (c) 2003, 2016, 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 24 import java.io.IOException; 25 import java.io.InputStream; 26 27 import javax.sound.sampled.AudioFormat; 28 import javax.sound.sampled.AudioInputStream; 29 import javax.sound.sampled.AudioSystem; 30 31 /** 32 * @test 33 * @bug 4948663 34 * @summary AudioInputStream does not use the original stream passed to its constructor 35 */ 36 public class AISReadFraction { 37 38 static int failed = 0; 39 static byte[] testData = new byte[256]; 40 static boolean DEBUG = false; 41 42 static AudioFormat[] formats = { 43 new AudioFormat(44100.0f, 8, 1, false, false), // frameSize = 1 44 new AudioFormat(44100.0f, 8, 2, false, false), // frameSize = 2 45 new AudioFormat(44100.0f, 16, 1, true, false), // frameSize = 2 46 new AudioFormat(44100.0f, 24, 1, true, false), // frameSize = 3 47 new AudioFormat(44100.0f, 16, 2, true, false), // frameSize = 4 48 new AudioFormat(44100.0f, 8, 5, false, false), // frameSize = 5 49 new AudioFormat(44100.0f, 16, 3, true, false), // frameSize = 6 50 new AudioFormat(44100.0f, 8, 7, false, false), // frameSize = 7 51 new AudioFormat(44100.0f, 32, 2, true, false) // frameSize = 8 52 }; 53 54 55 public static void main(String args[]) throws Exception { 56 for (int i = 0; i<testData.length; i++) { 57 testData[i] = (byte) (i % 128); 58 } 59 60 for (int f = 0; f < formats.length; f++) { 61 // first test without marking 62 doTest(formats[f], false); 63 // then with marking 64 doTest(formats[f], true); 65 } 66 67 out(""+failed+" failures."); 68 if (failed>0) throw new Exception("Test FAILED!"); 69 out("Test passed."); 70 } 71 72 static void doTest(AudioFormat format, boolean doMark) { 73 out("Test with"+(doMark?"":"out")+" marking. Audio format: " 74 +"sampleSize="+format.getSampleSizeInBits()+"bits " 75 +"channels="+format.getChannels()+" " 76 +"frameSize="+format.getFrameSize()+"byte(s)"); 77 int maxReadBytes = (testData.length / format.getFrameSize()) * format.getFrameSize(); 78 InputStream is = new FractionalIS(testData, doMark); 79 AudioInputStream ais = new AudioInputStream(is, format, AudioSystem.NOT_SPECIFIED); 80 // first some general tests 81 if (ais.markSupported() && !doMark) { 82 out(" #AIS reports markSupported, but underlying stream cannot! FAILED"); 83 failed ++; 84 } 85 if (!ais.markSupported() && doMark) { 86 out(" #AIS does not report markSupported, but underlying stream can mark! FAILED"); 87 failed++; 88 } 89 byte[] data = new byte[1000]; 90 int frameSize = format.getFrameSize(); 91 int counter = 5; 92 int totalReadBytes = 0; 93 boolean hasRead0 = false; 94 boolean hasMarked = false; 95 boolean hasReset = false; 96 int markPos = 0; 97 while (true) { 98 try { 99 int toBeRead = frameSize * counter; 100 counter += 3; 101 if (counter > 14) { 102 counter -= 14; 103 } 104 int read = ais.read(data, 0, toBeRead); 105 if (DEBUG) out(" -> ais.read(data, 0, "+toBeRead+"): "+read+" (frameSize="+frameSize+")"); 106 if ((totalReadBytes == maxReadBytes) && (read != -1) 107 && ((read > 0) || hasRead0)) { 108 if (read == 0) { 109 out(" #stream was read to the end ("+maxReadBytes+"), but ais.read returned repeatedly 0 bytes. FAILED"); 110 } else { 111 out(" #stream was read to the end ("+maxReadBytes+"), but ais.read returned "+read+" bytes... FAILED"); 112 } 113 failed++; 114 break; 115 } 116 if (read > 0) { 117 verifyReadBytes(data, totalReadBytes, read); 118 if ((read % frameSize) != 0) { 119 out(" #Read non-integral number of frames: "+read+" bytes, frameSize="+frameSize+" bytes. FAILED"); 120 failed++; 121 } 122 totalReadBytes += read; 123 hasRead0 = false; 124 } 125 else if (read == 0) { 126 //out(" wanted to read "+toBeRead+" at position "+totalReadBytes+", but got 0 bytes!"); 127 if (hasRead0) { 128 out(" read 0 twice in a row! FAILED"); 129 failed++; 130 break; 131 } 132 hasRead0 = true; 133 } else { 134 // end of stream 135 out(" End of stream reached. Total read bytes: "+totalReadBytes); 136 if (totalReadBytes != maxReadBytes) { 137 out(" #Failed: should have read "+maxReadBytes+" bytes! FAILED."); 138 failed++; 139 } 140 break; 141 } 142 143 // test marking 144 if (totalReadBytes > 50 && !hasMarked && !hasReset && doMark) { 145 out(" Marking at position "+totalReadBytes); 146 hasMarked = true; 147 ais.mark(0); 148 markPos = totalReadBytes; 149 } 150 if (totalReadBytes > 100 && hasMarked && !hasReset && doMark) { 151 out(" Resetting at position "+totalReadBytes+" back to "+markPos); 152 hasReset = true; 153 ais.reset(); 154 totalReadBytes = markPos; 155 } 156 157 } catch (IOException e) { 158 out(" #caught unexpected exception:"); 159 e.printStackTrace(); 160 failed++; 161 } 162 } 163 } 164 165 static void verifyReadBytes(byte[] data, int offset, int len) { 166 int firstWrongByte = -1; 167 for (int i = 0; i < len; i++) { 168 int expected = ((offset + i) % 128); 169 if (data[i] != expected) { 170 out(" read data is not correct! offset="+offset+" expected="+expected+" actual="+data[i]); 171 failed++; 172 break; 173 } 174 } 175 } 176 177 178 public static void out(String s) { 179 System.out.println(s); 180 } 181 182 183 static class FractionalIS extends InputStream { 184 byte[] data; 185 int pos = 0; 186 boolean canMark; 187 // a counter how many bytes are not returned 188 int missingBytes = 0; 189 int markPos = -1; 190 191 FractionalIS(byte[] data, boolean canMark) { 192 this.data = data; 193 this.canMark = canMark; 194 } 195 196 public int read() throws IOException { 197 if (pos >= data.length) { 198 return -1; 199 } 200 return data[pos++] & 0xFF; 201 } 202 203 public int read(byte[] b, int off, int len) throws IOException { 204 if (++missingBytes > 5) { 205 missingBytes = 0; 206 } 207 int reducedLen = len - missingBytes; 208 if (reducedLen <= 0) reducedLen = 1; 209 if (DEBUG) out(" FIS.read(data, 0, "+len+"): reducing len to "+reducedLen+" bytes."); 210 int ret = super.read(b, off, reducedLen); 211 if (DEBUG) out(" returning "+ret+" bytes. Now at pos="+pos); 212 return ret; 213 } 214 215 public void mark(int readlimit) { 216 markPos = pos; 217 if (DEBUG) out(" FIS.mark(): marking at "+pos); 218 } 219 220 public void reset() throws IOException { 221 if (!canMark) { 222 throw new IOException("reset not supported!"); 223 } 224 if (markPos == -1) { 225 throw new IOException("Mark position not set!"); 226 } 227 pos = markPos; 228 if (DEBUG) out(" FIS.reset(): now back at "+pos); 229 } 230 231 public boolean markSupported() { 232 return canMark; 233 } 234 235 } 236 237 }