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
24import javax.sound.sampled.AudioFormat;
25import javax.sound.sampled.AudioSystem;
26import javax.sound.sampled.Line;
27import javax.sound.sampled.LineUnavailableException;
28import javax.sound.sampled.Mixer;
29import javax.sound.sampled.SourceDataLine;
30
31/**
32 * @test
33 * @bug 4681384
34 * @summary SourceDataLine.write() causes Unexpected Signal 11 in native code
35 *          outside the VM
36 */
37public class SourceDataLineDefaultBufferSizeCrash {
38
39    static final int STATUS_PASSED = 0;
40    static final int STATUS_FAILED = 2;
41    static final int STATUS_TEMP = 95;
42
43    public static void main(String argv[]) throws Exception {
44        int testExitStatus = run(argv, System.out) + STATUS_TEMP;
45    }
46
47    public static int run(String argv[], java.io.PrintStream out) throws Exception {
48        int testResult = STATUS_PASSED;
49
50        int framesNumberToExceed = 2;
51        if ( argv.length > 0 ) {
52            try {
53                framesNumberToExceed = Integer.parseInt(argv[0]);
54            }
55            catch (NumberFormatException e) {
56            }
57        }
58
59        out.println
60            ("\n==> Test for SourceDataLine.write() method:");
61
62        Mixer.Info[] installedMixersInfo = AudioSystem.getMixerInfo();
63
64        if ( installedMixersInfo == null ) {
65            out.println("## AudioSystem.getMixerInfo() returned unexpected result:");
66            out.println("#  expected: an array of Mixer.Info objects (may be array of length 0);");
67            out.println("#  produced: null;");
68            return STATUS_FAILED;
69        }
70
71        if ( installedMixersInfo.length == 0 ) {
72            // there are no mixers installed on the system -
73            // so this testcase can not be tested
74            out.println("\n>>>  There are no mixers installed on the system!");
75            return STATUS_PASSED;
76        }
77
78        out.println("\n>>>  Number of mixers installed on the system = "
79            + installedMixersInfo.length);
80        Mixer installedMixer = null;
81        for (int i=0; i < installedMixersInfo.length; i++) {
82            try {
83                installedMixer = AudioSystem.getMixer(installedMixersInfo[i]);
84            } catch (SecurityException securityException) {
85                // installed Mixer is unavailable because of security restrictions
86                out.println("\n>>>  installedMixer[" + i
87                    + "] is unavailable because of security restrictions");
88                continue;
89            } catch (Throwable thrown) {
90                out.println("\n##  installedMixer[" + i + "] is unavailable because of");
91                out.println("#  AudioSystem.getMixer() threw unexpected exception:");
92                thrown.printStackTrace(out);
93                testResult = STATUS_FAILED;
94                continue;
95            }
96
97            out.println("\n>>>  installedMixer["+i+"] = " + installedMixer);
98            try {
99                installedMixer.open();
100            } catch (LineUnavailableException lineUnavailableException) {
101                // installedMixer is not available due to resource restrictions
102                out.println(">>   installedMixer[" + i
103                    + "] is not opened because of resource restrictions");
104                continue;
105            } catch (SecurityException securityException) {
106                // installedMixer is not available due to security restrictions
107                out.println(">>   installedMixer[" + i
108                    + "] is not opened because of security restrictions");
109                continue;
110            } catch (Throwable thrown) {
111                out.println("## installedMixer.open() throws unexpected exception:");
112                thrown.printStackTrace(out);
113                testResult = STATUS_FAILED;
114                continue;
115            }
116            Line.Info supportedSourceLineInfo[] = null;
117            try {
118                supportedSourceLineInfo = installedMixer.getSourceLineInfo();
119            } catch (Throwable thrown) {
120                out.println("## installedMixer.getSourceLineInfo() throws "
121                    + "unexpected exception:");
122                thrown.printStackTrace(out);
123                testResult = STATUS_FAILED;
124                installedMixer.close();
125                continue;
126            }
127            if ( supportedSourceLineInfo == null ) {
128                out.println("## installedMixer.getSourceLineInfo() returned null array");
129                out.println("#  Mixer = " + installedMixer);
130                testResult = STATUS_FAILED;
131                installedMixer.close();
132                continue;
133            }
134            out.println("\n>>  Number of SourceLineInfo supported by installedMixer ="
135                + supportedSourceLineInfo.length);
136
137            for (int j=0; j < supportedSourceLineInfo.length; j++) {
138                Line.Info testSourceLineInfo = supportedSourceLineInfo[j];
139
140                out.println("\n>  testSourceLineInfo["+j+"] = " + testSourceLineInfo);
141                Line testSourceLine = null;
142                try {
143                    testSourceLine = installedMixer.getLine(testSourceLineInfo);
144                } catch (LineUnavailableException lineUnavailableException) {
145                    // line is not available due to resource restrictions
146                    out.println(">  Line for this SourceLine Info is not available "
147                        + "due to resource restrictions");
148                    continue;
149                } catch (SecurityException securityException) {
150                    // line is not available due to security restrictions
151                    out.println(">  Line for this SourceLine Info is not available "
152                        + "due to security restrictions");
153                    continue;
154                } catch (Throwable thrown) {
155                    out.println("## installedMixer.getLine(testSourceLineInfo) throws"
156                        + "unexpected Exception:");
157                    thrown.printStackTrace(out);
158                    testResult = STATUS_FAILED;
159                    continue;
160                }
161
162                out.println(">  testedSourceLine = " + testSourceLine);
163                if ( ! (testSourceLine instanceof SourceDataLine) ) {
164                    out.println(">  testSourceLine is not SourceDataLine");
165                    continue;
166                }
167
168                SourceDataLine testedSourceLine = (SourceDataLine)testSourceLine;
169                AudioFormat lineAudioFormat = testedSourceLine.getFormat();
170
171                out.println("\n>  opening tested SourceLine:");
172                try {
173                    //testedSourceLine.open(lineAudioFormat, 2048);
174                    testedSourceLine.open(lineAudioFormat);
175                    out.println(">  OK - line is opened with "+testedSourceLine.getBufferSize()+" bytes buffer");
176                } catch (LineUnavailableException lineUnavailableException) {
177                    out.println(">  Line is not available due to resource restrictions:");
178                    lineUnavailableException.printStackTrace(out);
179                    continue;
180                } catch (SecurityException securityException) {
181                    out.println("> Line is not available due to security restrictions:");
182                    securityException.printStackTrace(out);
183                    continue;
184                } catch (Throwable thrown) {
185                    out.println("## SourceDataLine.open(AudioFormat format) failed:");
186                    out.println("#  Unexpected Exception is thrown");
187                    out.println("#  Mixer = " + installedMixer);
188                    out.println("#  SourceDataLine = " + testedSourceLine);
189                    thrown.printStackTrace(out);
190                    testResult = STATUS_FAILED;
191                    continue;
192                }
193
194                testedSourceLine.start();
195
196                int frameSize = 1;
197                if ( lineAudioFormat.getFrameSize() != AudioSystem.NOT_SPECIFIED ) {
198                    frameSize = lineAudioFormat.getFrameSize();
199                } else {
200                    if ( lineAudioFormat.getSampleSizeInBits() != AudioSystem.NOT_SPECIFIED ) {
201                        frameSize = lineAudioFormat.getSampleSizeInBits()/8;
202                        if ( lineAudioFormat.getSampleSizeInBits()%8 != 0 ) {
203                            frameSize++;
204                        }
205                    }
206                }
207                int bufferSizeToWrite = testedSourceLine.available()
208                    + (frameSize * framesNumberToExceed);
209                byte[] dataToWrite = new byte[bufferSizeToWrite];
210                for (int k=0; k < bufferSizeToWrite; k++) {
211                    dataToWrite[k] = (byte)1;
212                }
213                int offsetToWrite = 0;
214
215                out.println("\n>  check SourceDataLine.write() to write more data "
216                    + "than can currently be written:");
217
218                out.println(">  testedSourceLine.available() = " + testedSourceLine.available());
219                out.println(">  frame size = " + frameSize);
220                out.println(">  number of bytes to write = " + bufferSizeToWrite);
221                int writtenBytes = -1;
222                try {
223                    writtenBytes =
224                        testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite);
225                    out.println(">  OK - number of written bytes = " + writtenBytes);
226                } catch (Throwable thrown) {
227                    out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:");
228                    out.println("#  Unexpected Exception is thrown");
229                    thrown.printStackTrace(out);
230                    testResult = STATUS_FAILED;
231                }
232
233                testedSourceLine.close();
234
235            }  // for (int j=0; j < supportedSourceLineInfo.length; j++)
236            installedMixer.close();
237
238        }  // for (int i=0; i < installedMixersInfo.length; i++)
239
240        if ( testResult == STATUS_FAILED ) {
241            throw new Exception("Test FAILED!");
242        } else {
243            out.println("\n==> test PASSED!");
244        }
245        return testResult;
246    }
247
248}
249