Path: blob/master/test/jdk/javax/sound/sampled/DataLine/DataLine_ArrayIndexOutOfBounds.java
41152 views
/*1* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 708836726* @summary SourceDataLine.write and TargetDataLine.read don't throw ArrayIndexOutOfBoundsException27* @author Alex Menkov28*/2930import javax.sound.sampled.AudioSystem;31import javax.sound.sampled.DataLine;32import javax.sound.sampled.Line;33import javax.sound.sampled.LineUnavailableException;34import javax.sound.sampled.Mixer;35import javax.sound.sampled.SourceDataLine;36import javax.sound.sampled.TargetDataLine;3738public class DataLine_ArrayIndexOutOfBounds {3940static int total = 0;41static int failed = 0;4243// shared buffer for all tests44static final byte[] buffer = new byte[5000000];4546// the class describes different test scenarios (buffer properties)47static abstract class Scenario {48abstract int getBufferOffset(DataLine line);49abstract int getBufferLength(DataLine line);50}5152// scenarios to tests53static Scenario[] scenarios = new Scenario[]{54new Scenario() {55public String toString() {56return "offset is near Integer.MAX_VALUE";57}58public int getBufferOffset(DataLine line) {59return Integer.MAX_VALUE - 4096;60}61public int getBufferLength(DataLine line) {62return 65536;63}64},65new Scenario() {66public String toString() {67return "offset is less than buffer.length, length is large";68}69int getBufferOffset(DataLine line) {70return buffer.length / 10;71}72int getBufferLength(DataLine line) {73return Integer.MAX_VALUE - getBufferOffset(line) + 4096;74}75}76};7778public static void main(String[] args) throws Exception {79Mixer.Info[] infos = AudioSystem.getMixerInfo();80log("" + infos.length + " mixers detected");81for (int i=0; i<infos.length; i++) {82Mixer mixer = AudioSystem.getMixer(infos[i]);83log("Mixer " + (i+1) + ": " + infos[i]);84try {85mixer.open();86for (Scenario scenario: scenarios) {87testSDL(mixer, scenario);88testTDL(mixer, scenario);89}90mixer.close();91} catch (LineUnavailableException ex) {92log("LineUnavailableException: " + ex);93}94}95if (failed == 0) {96log("PASSED (" + total + " tests)");97} else {98log("FAILED (" + failed + " of " + total + " tests)");99throw new Exception("Test FAILED");100}101}102103final static int STOPPER_DELAY = 5000; // 1 sec104105static class AsyncLineStopper implements Runnable {106private final DataLine line;107private final long delayMS; // delay before stop the line108private final Thread thread;109private final Object readyEvent = new Object();110private final Object startEvent = new Object();111112public AsyncLineStopper(DataLine line, long delayMS) {113this.line = line;114this.delayMS = delayMS;115thread = new Thread(this);116thread.setDaemon(true);117// starts the thread and waits until it becomes ready118synchronized (readyEvent) {119thread.start();120try {121readyEvent.wait();122} catch (InterruptedException ex) { }123}124}125126// makes the delay and then stops the line127public void schedule() {128synchronized(startEvent) {129startEvent.notifyAll();130}131}132133// force stop/close the line134public void force() {135thread.interrupt();136try {137thread.join();138} catch (InterruptedException ex) {139log("join exception: " + ex);140}141}142143// Runnable implementation144public void run() {145try {146synchronized(readyEvent) {147readyEvent.notifyAll();148}149synchronized(startEvent) {150startEvent.wait();151}152// delay153Thread.sleep(delayMS);154} catch (InterruptedException ex) {155log(" AsyncLineStopper has been interrupted: " + ex);156}157// and flush158log(" stop...");159line.stop();160log(" close...");161line.close();162}163}164165static void testSDL(Mixer mixer, Scenario scenario) {166log(" Testing SDL (scenario: " + scenario + ")...");167Line.Info linfo = new Line.Info(SourceDataLine.class);168SourceDataLine line = null;169try {170line = (SourceDataLine)mixer.getLine(linfo);171log(" got line: " + line);172log(" open...");173line.open();174} catch (IllegalArgumentException ex) {175log(" unsupported (IllegalArgumentException)");176return;177} catch (LineUnavailableException ex) {178log(" unavailable: " + ex);179return;180}181182total++;183184log(" start...");185line.start();186187AsyncLineStopper lineStopper = new AsyncLineStopper(line, STOPPER_DELAY);188int offset = scenario.getBufferOffset(line);189int len = scenario.getBufferLength(line);190// ensure len represents integral number of frames191len -= len % line.getFormat().getFrameSize();192193log(" write...");194lineStopper.schedule();195try {196line.write(buffer, offset, len);197log(" ERROR: didn't get ArrayIndexOutOfBoundsException");198failed++;199} catch (ArrayIndexOutOfBoundsException ex) {200log(" OK: got ArrayIndexOutOfBoundsException: " + ex);201}202lineStopper.force();203}204205static void testTDL(Mixer mixer, Scenario scenario) {206log(" Testing TDL (scenario: " + scenario + ")...");207Line.Info linfo = new Line.Info(TargetDataLine.class);208TargetDataLine line = null;209try {210line = (TargetDataLine)mixer.getLine(linfo);211log(" got line: " + line);212log(" open...");213line.open();214} catch (IllegalArgumentException ex) {215log(" unsupported (IllegalArgumentException)");216return;217} catch (LineUnavailableException ex) {218log(" unavailable: " + ex);219return;220}221222total++;223224log(" start...");225line.start();226227AsyncLineStopper lineStopper = new AsyncLineStopper(line, STOPPER_DELAY);228int offset = scenario.getBufferOffset(line);229int len = scenario.getBufferLength(line);230// ensure len represents integral number of frames231len -= len % line.getFormat().getFrameSize();232233log(" read...");234try {235line.read(buffer, offset, len);236log(" ERROR: didn't get ArrayIndexOutOfBoundsException");237failed++;238} catch (ArrayIndexOutOfBoundsException ex) {239log(" OK: got ArrayIndexOutOfBoundsException: " + ex);240}241lineStopper.force();242}243244static void log(String s) {245System.out.println(s);246System.out.flush();247}248}249250251