# HG changeset patch # User andrew # Date 1596248430 -3600 # Sat Aug 01 03:20:30 2020 +0100 # Node ID 039b7fa799bb06f76c5af7a49d8d88fe99d39c1f # Parent 164cd43a173938a6b307d7232b72d0dcd93c689e # Parent 2f117c5839733a3c17bf3fe99080df94b809b899 Merge jdk8u272-b01 diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -1231,6 +1231,7 @@ 4789a6a01301851b530fddbf7b0ce28f717f3de7 jdk8u262-b05 b4d9777fdbc2309e1a6a0bd657dcfefb0e44148c aarch64-shenandoah-jdk8u262-b05 fa8eb8a0a0bb5103315d5b0968a0ff1100cec979 aarch64-shenandoah-jdk8u262-b05-shenandoah-merge-2020-06-04 +4789a6a01301851b530fddbf7b0ce28f717f3de7 jdk8u272-b00 097f47e7fe97b47dcb02603d9d592e1cba7f564e jdk8u262-b06 1cf70821a22ba40410c09226a652b84aa8b4fdbe aarch64-shenandoah-jdk8u262-b06 745caf348aeec7b19f9f92ad283e3f8bd498dd02 jdk8u262-b07 @@ -1247,3 +1248,4 @@ 66699ff7f013e0a0bf93fc925e0a9cdcdd92801d jdk8u265-b00 9204e03217f70fdbb3dd492eb687fbfb61ee0d5c jdk8u265-b01 03a7cddeb256a6f574329d54e6c806e8fe038329 aarch64-shenandoah-jdk8u265-b01 +9204e03217f70fdbb3dd492eb687fbfb61ee0d5c jdk8u265-ga diff --git a/make/Bundles.gmk b/make/Bundles.gmk --- a/make/Bundles.gmk +++ b/make/Bundles.gmk @@ -89,16 +89,16 @@ if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -L '$<' '$@'; fi $(JDK_BUNDLE_DIR)/MacOS/libjli.dylib: - $(ECHO) Creating link $(patsubst $(OUTPUT_ROOT)/%,%,$@) + $(ECHO) Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@) $(MKDIR) -p $(@D) $(RM) $@ - $(LN) -s ../Home/jre/lib/jli/libjli.dylib $@ + $(CP) $(JDK_IMAGE_DIR)/jre/lib/jli/libjli.dylib $@ $(JRE_BUNDLE_DIR)/MacOS/libjli.dylib: - $(ECHO) Creating link $(patsubst $(OUTPUT_ROOT)/%,%,$@) + $(ECHO) Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@) $(MKDIR) -p $(@D) $(RM) $@ - $(LN) -s ../Home/lib/jli/libjli.dylib $@ + $(CP) $(JRE_IMAGE_DIR)/lib/jli/libjli.dylib $@ $(JDK_BUNDLE_DIR)/Info.plist: $(SPEC) $(ECHO) Creating $(patsubst $(OUTPUT_ROOT)/%,%,$@) diff --git a/make/mapfiles/libnet/mapfile-vers b/make/mapfiles/libnet/mapfile-vers --- a/make/mapfiles/libnet/mapfile-vers +++ b/make/mapfiles/libnet/mapfile-vers @@ -99,6 +99,13 @@ Java_sun_net_ExtendedOptionsImpl_setFlowOption; Java_sun_net_ExtendedOptionsImpl_getFlowOption; Java_sun_net_ExtendedOptionsImpl_flowSupported; + Java_sun_net_ExtendedOptionsImpl_keepAliveOptionsSupported; + Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveProbes; + Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveTime; + Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveIntvl; + Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveProbes; + Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveTime; + Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveIntvl; NET_AllocSockaddr; NET_SockaddrToInetAddress; NET_SockaddrEqualsInetAddress; diff --git a/src/macosx/bin/java_md_macosx.c b/src/macosx/bin/java_md_macosx.c --- a/src/macosx/bin/java_md_macosx.c +++ b/src/macosx/bin/java_md_macosx.c @@ -651,11 +651,31 @@ } size_t indexOfLastPathComponent = pathLen - sizeOfLastPathComponent; - if (0 == strncmp(realPathToSelf + indexOfLastPathComponent, lastPathComponent, sizeOfLastPathComponent - 1)) { + if (0 == strncmp(realPathToSelf + indexOfLastPathComponent, lastPathComponent, sizeOfLastPathComponent)) { realPathToSelf[indexOfLastPathComponent + 1] = '\0'; return JNI_TRUE; } + // If libjli.dylib is loaded from a macos bundle MacOS dir, find the JRE dir + // in ../Home. + const char altLastPathComponent[] = "/MacOS/libjli.dylib"; + size_t sizeOfAltLastPathComponent = sizeof(altLastPathComponent) - 1; + if (pathLen < sizeOfLastPathComponent) { + return JNI_FALSE; + } + + size_t indexOfAltLastPathComponent = pathLen - sizeOfAltLastPathComponent; + if (0 == strncmp(realPathToSelf + indexOfAltLastPathComponent, altLastPathComponent, sizeOfAltLastPathComponent)) { + JLI_Snprintf(realPathToSelf + indexOfAltLastPathComponent, sizeOfAltLastPathComponent, "%s", "/Home/jre"); + if (access(realPathToSelf, F_OK) == 0) { + return JNI_TRUE; + } + JLI_Snprintf(realPathToSelf + indexOfAltLastPathComponent, sizeOfAltLastPathComponent, "%s", "/Home"); + if (access(realPathToSelf, F_OK) == 0) { + return JNI_TRUE; + } + } + if (!speculative) JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL); return JNI_FALSE; diff --git a/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m b/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m --- a/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m +++ b/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m @@ -93,7 +93,6 @@ CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; #if USE_NSVIEW_FOR_SCRATCH [ctxinfo->context makeCurrentContext]; - [ctxinfo->context setView: ctxinfo->scratchSurface]; #else [ctxinfo->context clearDrawable]; [ctxinfo->context makeCurrentContext]; diff --git a/src/share/classes/com/sun/jndi/ldap/LdapCtx.java b/src/share/classes/com/sun/jndi/ldap/LdapCtx.java --- a/src/share/classes/com/sun/jndi/ldap/LdapCtx.java +++ b/src/share/classes/com/sun/jndi/ldap/LdapCtx.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, 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 @@ -2690,7 +2690,8 @@ synchronized (clnt) { if (!clnt.isLdapv3 || clnt.referenceCount > 1 - || clnt.usingSaslStreams()) { + || clnt.usingSaslStreams() + || !clnt.conn.useable) { closeConnection(SOFT_CLOSE); } } diff --git a/src/share/classes/com/sun/media/sound/AbstractDataLine.java b/src/share/classes/com/sun/media/sound/AbstractDataLine.java --- a/src/share/classes/com/sun/media/sound/AbstractDataLine.java +++ b/src/share/classes/com/sun/media/sound/AbstractDataLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -59,10 +59,9 @@ // current buffer size in bytes protected int bufferSize; - protected boolean running = false; - private boolean started = false; - private boolean active = false; - + private volatile boolean running; + private volatile boolean started; + private volatile boolean active; /** * Constructs a new AbstractLine. diff --git a/src/share/classes/com/sun/media/sound/AbstractLine.java b/src/share/classes/com/sun/media/sound/AbstractLine.java --- a/src/share/classes/com/sun/media/sound/AbstractLine.java +++ b/src/share/classes/com/sun/media/sound/AbstractLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -47,7 +47,7 @@ protected final Line.Info info; protected Control[] controls; AbstractMixer mixer; - private boolean open = false; + private volatile boolean open; private final Vector listeners = new Vector(); /** diff --git a/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java b/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java --- a/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java +++ b/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -65,7 +65,7 @@ // DEVICE STATE - private boolean open = false; + private volatile boolean open; private int openRefCount; /** List of Receivers and Transmitters that opened the device implicitely. @@ -75,7 +75,7 @@ /** * This is the device handle returned from native code */ - protected long id = 0; + protected volatile long id; @@ -477,7 +477,7 @@ (which opens the device implicitely). */ abstract class AbstractReceiver implements MidiDeviceReceiver { - private boolean open = true; + private volatile boolean open = true; /** Deliver a MidiMessage. diff --git a/src/share/classes/com/sun/media/sound/MidiInDevice.java b/src/share/classes/com/sun/media/sound/MidiInDevice.java --- a/src/share/classes/com/sun/media/sound/MidiInDevice.java +++ b/src/share/classes/com/sun/media/sound/MidiInDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -38,7 +38,7 @@ */ final class MidiInDevice extends AbstractMidiDevice implements Runnable { - private Thread midiInThread = null; + private volatile Thread midiInThread; // CONSTRUCTOR diff --git a/src/share/classes/com/sun/media/sound/RealTimeSequencer.java b/src/share/classes/com/sun/media/sound/RealTimeSequencer.java --- a/src/share/classes/com/sun/media/sound/RealTimeSequencer.java +++ b/src/share/classes/com/sun/media/sound/RealTimeSequencer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -106,7 +106,7 @@ /** * True if the sequence is running. */ - private boolean running = false; + private volatile boolean running; /** the thread for pushing out the MIDI messages */ @@ -116,7 +116,7 @@ /** * True if we are recording */ - private boolean recording = false; + private volatile boolean recording; /** diff --git a/src/share/classes/com/sun/security/ntlm/NTLM.java b/src/share/classes/com/sun/security/ntlm/NTLM.java --- a/src/share/classes/com/sun/security/ntlm/NTLM.java +++ b/src/share/classes/com/sun/security/ntlm/NTLM.java @@ -167,7 +167,7 @@ byte[] readSecurityBuffer(int offset) throws NTLMException { int pos = readInt(offset+4); - if (pos == 0) return null; + if (pos == 0) return new byte[0]; try { return Arrays.copyOfRange( internal, pos, pos + readShort(offset)); diff --git a/src/share/classes/com/sun/tools/example/debug/tty/TTY.java b/src/share/classes/com/sun/tools/example/debug/tty/TTY.java --- a/src/share/classes/com/sun/tools/example/debug/tty/TTY.java +++ b/src/share/classes/com/sun/tools/example/debug/tty/TTY.java @@ -40,6 +40,7 @@ import com.sun.jdi.connect.*; import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; import java.io.*; public class TTY implements EventNotifier { @@ -48,7 +49,7 @@ /** * List of Strings to execute at each stop. */ - private List monitorCommands = new ArrayList(); + private List monitorCommands = new CopyOnWriteArrayList<>(); private int monitorCount = 0; /** diff --git a/src/share/classes/javax/sound/midi/Sequence.java b/src/share/classes/javax/sound/midi/Sequence.java --- a/src/share/classes/javax/sound/midi/Sequence.java +++ b/src/share/classes/javax/sound/midi/Sequence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -266,11 +266,7 @@ * @see #getTracks */ public boolean deleteTrack(Track track) { - - synchronized(tracks) { - - return tracks.removeElement(track); - } + return tracks.removeElement(track); } @@ -283,8 +279,8 @@ * @see #deleteTrack */ public Track[] getTracks() { - - return (Track[]) tracks.toArray(new Track[tracks.size()]); + // Creation of the non-empty array will be synchronized inside toArray() + return tracks.toArray(new Track[0]); } diff --git a/src/share/classes/jdk/net/ExtendedSocketOptions.java b/src/share/classes/jdk/net/ExtendedSocketOptions.java --- a/src/share/classes/jdk/net/ExtendedSocketOptions.java +++ b/src/share/classes/jdk/net/ExtendedSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -57,4 +57,66 @@ */ public static final SocketOption SO_FLOW_SLA = new ExtSocketOption("SO_FLOW_SLA", SocketFlow.class); + + /** + * Keep-Alive idle time. + * + *

+ * The value of this socket option is an {@code Integer} that is the number + * of seconds of idle time before keep-alive initiates a probe. The socket + * option is specific to stream-oriented sockets using the TCP/IP protocol. + * The exact semantics of this socket option are system dependent. + * + *

+ * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE + * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been + * idle for some amount of time. The default value for this idle period is + * system dependent, but is typically 2 hours. The {@code TCP_KEEPIDLE} + * option can be used to affect this value for a given socket. + */ + public static final SocketOption TCP_KEEPIDLE + = new ExtSocketOption("TCP_KEEPIDLE", Integer.class); + + /** + * Keep-Alive retransmission interval time. + * + *

+ * The value of this socket option is an {@code Integer} that is the number + * of seconds to wait before retransmitting a keep-alive probe. The socket + * option is specific to stream-oriented sockets using the TCP/IP protocol. + * The exact semantics of this socket option are system dependent. + * + *

+ * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE + * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been + * idle for some amount of time. If the remote system does not respond to a + * keep-alive probe, TCP retransmits the probe after some amount of time. + * The default value for this retransmission interval is system dependent, + * but is typically 75 seconds. The {@code TCP_KEEPINTERVAL} option can be + * used to affect this value for a given socket. + */ + public static final SocketOption TCP_KEEPINTERVAL + = new ExtSocketOption("TCP_KEEPINTERVAL", Integer.class); + + /** + * Keep-Alive retransmission maximum limit. + * + *

+ * The value of this socket option is an {@code Integer} that is the maximum + * number of keep-alive probes to be sent. The socket option is specific to + * stream-oriented sockets using the TCP/IP protocol. The exact semantics of + * this socket option are system dependent. + * + *

+ * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE + * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been + * idle for some amount of time. If the remote system does not respond to a + * keep-alive probe, TCP retransmits the probe a certain number of times + * before a connection is considered to be broken. The default value for + * this keep-alive probe retransmit limit is system dependent, but is + * typically 8. The {@code TCP_KEEPCOUNT} option can be used to affect this + * value for a given socket. + */ + public static final SocketOption TCP_KEEPCOUNT + = new ExtSocketOption("TCP_KEEPCOUNT", Integer.class); } diff --git a/src/share/classes/jdk/net/Sockets.java b/src/share/classes/jdk/net/Sockets.java --- a/src/share/classes/jdk/net/Sockets.java +++ b/src/share/classes/jdk/net/Sockets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -36,6 +36,7 @@ import java.util.HashMap; import java.util.Collections; import sun.net.ExtendedOptionsImpl; +import sun.net.ExtendedOptionsHelper; /** * Defines static methods to set and get socket options defined by the @@ -363,6 +364,7 @@ if (flowsupported) { set.add(ExtendedSocketOptions.SO_FLOW_SLA); } + set.addAll(ExtendedOptionsHelper.keepAliveOptions()); set = Collections.unmodifiableSet(set); options.put(Socket.class, set); @@ -372,6 +374,7 @@ set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); set.add(StandardSocketOptions.IP_TOS); + set.addAll(ExtendedOptionsHelper.keepAliveOptions()); set = Collections.unmodifiableSet(set); options.put(ServerSocket.class, set); @@ -404,4 +407,5 @@ set = Collections.unmodifiableSet(set); options.put(MulticastSocket.class, set); } + } diff --git a/src/share/classes/sun/net/ExtendedOptionsHelper.java b/src/share/classes/sun/net/ExtendedOptionsHelper.java new file mode 100644 --- /dev/null +++ b/src/share/classes/sun/net/ExtendedOptionsHelper.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package sun.net; + +import java.net.SocketOption; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPCOUNT; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPINTERVAL; + +public class ExtendedOptionsHelper { + + private static final boolean keepAliveOptSupported = + ExtendedOptionsImpl.keepAliveOptionsSupported(); + private static final Set> extendedOptions = options(); + + private static Set> options() { + Set> options = new HashSet<>(); + if (keepAliveOptSupported) { + options.add(TCP_KEEPCOUNT); + options.add(TCP_KEEPIDLE); + options.add(TCP_KEEPINTERVAL); + } + return Collections.unmodifiableSet(options); + } + + public static Set> keepAliveOptions() { + return extendedOptions; + } +} diff --git a/src/share/classes/sun/net/ExtendedOptionsImpl.java b/src/share/classes/sun/net/ExtendedOptionsImpl.java --- a/src/share/classes/sun/net/ExtendedOptionsImpl.java +++ b/src/share/classes/sun/net/ExtendedOptionsImpl.java @@ -89,4 +89,12 @@ public static native void setFlowOption(FileDescriptor fd, SocketFlow f); public static native void getFlowOption(FileDescriptor fd, SocketFlow f); public static native boolean flowSupported(); + + public static native void setTcpKeepAliveProbes(FileDescriptor fd, int value) throws SocketException; + public static native void setTcpKeepAliveTime(FileDescriptor fd, int value) throws SocketException; + public static native void setTcpKeepAliveIntvl(FileDescriptor fd, int value) throws SocketException; + public static native int getTcpKeepAliveProbes(FileDescriptor fd) throws SocketException; + public static native int getTcpKeepAliveTime(FileDescriptor fd) throws SocketException; + public static native int getTcpKeepAliveIntvl(FileDescriptor fd) throws SocketException; + public static native boolean keepAliveOptionsSupported(); } diff --git a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java --- a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -39,6 +39,7 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import sun.net.NetHooks; +import sun.net.ExtendedOptionsHelper; /** * Base implementation of AsynchronousServerSocketChannel. @@ -231,6 +232,7 @@ HashSet> set = new HashSet>(2); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + set.addAll(ExtendedOptionsHelper.keepAliveOptions()); return Collections.unmodifiableSet(set); } } diff --git a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java --- a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -40,6 +40,7 @@ import java.util.concurrent.locks.*; import sun.net.NetHooks; import sun.net.ExtendedOptionsImpl; +import sun.net.ExtendedOptionsHelper; /** * Base implementation of AsynchronousSocketChannel @@ -512,6 +513,7 @@ if (ExtendedOptionsImpl.flowSupported()) { set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); } + set.addAll(ExtendedOptionsHelper.keepAliveOptions()); return Collections.unmodifiableSet(set); } } diff --git a/src/share/classes/sun/nio/ch/Net.java b/src/share/classes/sun/nio/ch/Net.java --- a/src/share/classes/sun/nio/ch/Net.java +++ b/src/share/classes/sun/nio/ch/Net.java @@ -34,6 +34,9 @@ import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import sun.net.ExtendedOptionsImpl; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPCOUNT; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPINTERVAL; public class Net { @@ -279,13 +282,29 @@ Class type = name.type(); if (type == SocketFlow.class) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA")); - } + ExtendedOptionsImpl.checkSetOptionPermission(name); + ExtendedOptionsImpl.checkValueType(value, SocketFlow.class); ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value); return; } + if (name == TCP_KEEPINTERVAL) { + ExtendedOptionsImpl.checkSetOptionPermission(name); + ExtendedOptionsImpl.checkValueType(value, Integer.class); + ExtendedOptionsImpl.setTcpKeepAliveIntvl(fd, (Integer)value); + return; + } + if (name == TCP_KEEPIDLE) { + ExtendedOptionsImpl.checkSetOptionPermission(name); + ExtendedOptionsImpl.checkValueType(value, Integer.class); + ExtendedOptionsImpl.setTcpKeepAliveTime(fd, (Integer)value); + return; + } + if (name == TCP_KEEPCOUNT) { + ExtendedOptionsImpl.checkSetOptionPermission(name); + ExtendedOptionsImpl.checkValueType(value, Integer.class); + ExtendedOptionsImpl.setTcpKeepAliveProbes(fd, (Integer)value); + return; + } if (type != Integer.class && type != Boolean.class) throw new AssertionError("Should not reach here"); @@ -341,14 +360,23 @@ Class type = name.type(); if (type == SocketFlow.class) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA")); - } + ExtendedOptionsImpl.checkGetOptionPermission(name); SocketFlow flow = SocketFlow.create(); ExtendedOptionsImpl.getFlowOption(fd, flow); return flow; } + if (name == TCP_KEEPINTERVAL) { + ExtendedOptionsImpl.checkGetOptionPermission(name); + return ExtendedOptionsImpl.getTcpKeepAliveIntvl(fd); + } + if (name == TCP_KEEPIDLE) { + ExtendedOptionsImpl.checkGetOptionPermission(name); + return ExtendedOptionsImpl.getTcpKeepAliveTime(fd); + } + if (name == TCP_KEEPCOUNT) { + ExtendedOptionsImpl.checkGetOptionPermission(name); + return ExtendedOptionsImpl.getTcpKeepAliveProbes(fd); + } // only simple values supported by this method if (type != Integer.class && type != Boolean.class) diff --git a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java --- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -32,6 +32,7 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; +import sun.net.ExtendedOptionsHelper; /** @@ -183,6 +184,7 @@ set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); set.add(StandardSocketOptions.IP_TOS); + set.addAll(ExtendedOptionsHelper.keepAliveOptions()); return Collections.unmodifiableSet(set); } } diff --git a/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/share/classes/sun/nio/ch/SocketChannelImpl.java --- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -34,6 +34,7 @@ import java.util.*; import sun.net.NetHooks; import sun.net.ExtendedOptionsImpl; +import sun.net.ExtendedOptionsHelper; /** @@ -239,6 +240,7 @@ if (ExtendedOptionsImpl.flowSupported()) { set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); } + set.addAll(ExtendedOptionsHelper.keepAliveOptions()); return Collections.unmodifiableSet(set); } } diff --git a/src/share/classes/sun/security/krb5/Config.java b/src/share/classes/sun/security/krb5/Config.java --- a/src/share/classes/sun/security/krb5/Config.java +++ b/src/share/classes/sun/security/krb5/Config.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, 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 @@ -151,6 +151,7 @@ KdcComm.initStatic(); EType.initStatic(); Checksum.initStatic(); + KrbAsReqBuilder.ReferralsState.initStatic(); } @@ -275,7 +276,7 @@ * value does not look like a boolean value. * @throws IllegalArgumentException see {@link #get(String...)} */ - private Boolean getBooleanObject(String... keys) { + public Boolean getBooleanObject(String... keys) { String s = get(keys); if (s == null) { return null; diff --git a/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java b/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java --- a/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java +++ b/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, 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 @@ -278,7 +278,9 @@ } options = (options == null) ? new KDCOptions() : options; if (referralsState.isEnabled()) { - options.set(KDCOptions.CANONICALIZE, true); + if (referralsState.sendCanonicalize()) { + options.set(KDCOptions.CANONICALIZE, true); + } extraPAs = new PAData[]{ new PAData(Krb5.PA_REQ_ENC_PA_REP, new byte[]{}) }; } else { @@ -333,7 +335,7 @@ boolean preAuthFailedOnce = false; KdcComm comm = null; EncryptionKey pakey = null; - ReferralsState referralsState = new ReferralsState(); + ReferralsState referralsState = new ReferralsState(this); while (true) { if (referralsState.refreshComm()) { comm = new KdcComm(refCname.getRealmAsString()); @@ -379,43 +381,88 @@ } } - private final class ReferralsState { + static final class ReferralsState { + private static boolean canonicalizeConfig; private boolean enabled; + private boolean sendCanonicalize; + private boolean isEnterpriseCname; private int count; private boolean refreshComm; + private KrbAsReqBuilder reqBuilder; - ReferralsState() throws KrbException { - if (Config.DISABLE_REFERRALS) { - if (refCname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) { - throw new KrbException("NT-ENTERPRISE principals only allowed" + - " when referrals are enabled."); + static { + initStatic(); + } + + // Config may be refreshed while running so the setting + // value may need to be updated. See Config::refresh. + static void initStatic() { + canonicalizeConfig = false; + try { + canonicalizeConfig = Config.getInstance() + .getBooleanObject("libdefaults", "canonicalize") == + Boolean.TRUE; + } catch (KrbException e) { + if (Krb5.DEBUG) { + System.out.println("Exception in getting canonicalize," + + " using default value " + + Boolean.valueOf(canonicalizeConfig) + ": " + + e.getMessage()); } - enabled = false; - } else { - enabled = true; + } + } + + ReferralsState(KrbAsReqBuilder reqBuilder) throws KrbException { + this.reqBuilder = reqBuilder; + sendCanonicalize = canonicalizeConfig; + isEnterpriseCname = reqBuilder.refCname.getNameType() == + PrincipalName.KRB_NT_ENTERPRISE; + updateStatus(); + if (!enabled && isEnterpriseCname) { + throw new KrbException("NT-ENTERPRISE principals only" + + " allowed when referrals are enabled."); } refreshComm = true; } + private void updateStatus() { + enabled = !Config.DISABLE_REFERRALS && + (isEnterpriseCname || sendCanonicalize); + } + boolean handleError(KrbException ke) throws RealmException { if (enabled) { if (ke.returnCode() == Krb5.KRB_ERR_WRONG_REALM) { Realm referredRealm = ke.getError().getClientRealm(); - if (req.getMessage().reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) && - referredRealm != null && referredRealm.toString().length() > 0 && + if (referredRealm != null && + !referredRealm.toString().isEmpty() && count < Config.MAX_REFERRALS) { - refCname = new PrincipalName(refCname.getNameType(), - refCname.getNameStrings(), referredRealm); + // A valid referral was received while referrals + // were enabled. Change the cname realm to the referred + // realm and set refreshComm to send a new request. + reqBuilder.refCname = new PrincipalName( + reqBuilder.refCname.getNameType(), + reqBuilder.refCname.getNameStrings(), + referredRealm); refreshComm = true; count++; return true; } } - if (count < Config.MAX_REFERRALS && - refCname.getNameType() != PrincipalName.KRB_NT_ENTERPRISE) { - // Server may raise an error if CANONICALIZE is true. - // Try CANONICALIZE false. - enabled = false; + if (count < Config.MAX_REFERRALS && sendCanonicalize) { + if (Krb5.DEBUG) { + System.out.println("KrbAsReqBuilder: AS-REQ failed." + + " Retrying with CANONICALIZE false."); + } + + // Server returned an unexpected error with + // CANONICALIZE true. Retry with false. + sendCanonicalize = false; + + // Setting CANONICALIZE to false may imply that referrals + // are now disabled (if cname is not of NT-ENTERPRISE type). + updateStatus(); + return true; } } @@ -431,6 +478,10 @@ boolean isEnabled() { return enabled; } + + boolean sendCanonicalize() { + return sendCanonicalize; + } } /** diff --git a/src/share/classes/sun/security/krb5/KrbKdcRep.java b/src/share/classes/sun/security/krb5/KrbKdcRep.java --- a/src/share/classes/sun/security/krb5/KrbKdcRep.java +++ b/src/share/classes/sun/security/krb5/KrbKdcRep.java @@ -44,11 +44,13 @@ ) throws KrbApErrException { // cname change in AS-REP is allowed only if the client - // sent CANONICALIZE and the server supports RFC 6806 - Section 11 - // FAST scheme (ENC-PA-REP flag). + // sent CANONICALIZE or an NT-ENTERPRISE cname in the request, and the + // server supports RFC 6806 - Section 11 FAST scheme (ENC-PA-REP flag). if (isAsReq && !req.reqBody.cname.equals(rep.cname) && - (!req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) || - !rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP))) { + ((!req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) && + req.reqBody.cname.getNameType() != + PrincipalName.KRB_NT_ENTERPRISE) || + !rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP))) { rep.encKDCRepPart.key.destroy(); throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED); } @@ -126,14 +128,16 @@ } // RFC 6806 - Section 11 mechanism check - if (rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP) && - req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE)) { + // The availability of the ENC-PA-REP flag in the KDC response is + // mandatory on some cases (see Krb5.TKT_OPTS_ENC_PA_REP check above). + if (rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP)) { boolean reqPaReqEncPaRep = false; boolean repPaReqEncPaRepValid = false; - // PA_REQ_ENC_PA_REP only required for AS requests for (PAData pa : req.pAData) { if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) { + // The KDC supports RFC 6806 and ENC-PA-REP was sent in + // the request (AS-REQ). A valid checksum is now required. reqPaReqEncPaRep = true; break; } diff --git a/src/share/classes/sun/security/validator/PKIXValidator.java b/src/share/classes/sun/security/validator/PKIXValidator.java --- a/src/share/classes/sun/security/validator/PKIXValidator.java +++ b/src/share/classes/sun/security/validator/PKIXValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, 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 @@ -32,9 +32,9 @@ import javax.security.auth.x500.X500Principal; import sun.security.action.GetBooleanAction; -import sun.security.action.GetPropertyAction; import sun.security.provider.certpath.AlgorithmChecker; import sun.security.provider.certpath.PKIXExtendedParameters; +import sun.security.util.SecurityProperties; /** * Validator implementation built on the PKIX CertPath API. This @@ -66,14 +66,14 @@ private final static boolean TRY_VALIDATOR = true; /** - * System property that if set (or set to "true"), allows trust anchor - * certificates to be used if they do not have the proper CA extensions. - * Set to false if prop is not set, or set to any other value. + * System or security property that if set (or set to "true"), allows trust + * anchor certificates to be used if they do not have the proper CA + * extensions. Set to false if prop is not set, or set to any other value. */ private static final boolean ALLOW_NON_CA_ANCHOR = allowNonCaAnchor(); private static boolean allowNonCaAnchor() { - String prop = GetPropertyAction - .privilegedGetProperty("jdk.security.allowNonCaAnchor"); + String prop = SecurityProperties + .privilegedGetOverridable("jdk.security.allowNonCaAnchor"); return prop != null && (prop.isEmpty() || prop.equalsIgnoreCase("true")); } diff --git a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java --- a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java +++ b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java @@ -200,10 +200,19 @@ return (LG(b, n)) | (LG(b, n + 4) << 32); } - static final long GETSIG(byte[] b) { - return LG(b, 0); + static long getSig(byte[] b, int n) { return LG(b, n); } + + private static boolean pkSigAt(byte[] b, int n, int b1, int b2) { + return b[n] == 'P' & b[n + 1] == 'K' & b[n + 2] == b1 & b[n + 3] == b2; } + static boolean cenSigAt(byte[] b, int n) { return pkSigAt(b, n, 1, 2); } + static boolean locSigAt(byte[] b, int n) { return pkSigAt(b, n, 3, 4); } + static boolean endSigAt(byte[] b, int n) { return pkSigAt(b, n, 5, 6); } + static boolean extSigAt(byte[] b, int n) { return pkSigAt(b, n, 7, 8); } + static boolean end64SigAt(byte[] b, int n) { return pkSigAt(b, n, 6, 6); } + static boolean locator64SigAt(byte[] b, int n) { return pkSigAt(b, n, 6, 7); } + // local file (LOC) header fields static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract diff --git a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java --- a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java +++ b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java @@ -1073,7 +1073,7 @@ int pos = 0; int limit = cen.length - ENDHDR; while (pos < limit) { - if (CENSIG(cen, pos) != CENSIG) + if (!cenSigAt(cen, pos)) zerror("invalid CEN header (bad signature)"); int method = CENHOW(cen, pos); int nlen = CENNAM(cen, pos); @@ -1921,7 +1921,7 @@ throws IOException { byte[] cen = zipfs.cen; - if (CENSIG(cen, pos) != CENSIG) + if (!cenSigAt(cen, pos)) zerror("invalid CEN header (bad signature)"); versionMade = CENVEM(cen, pos); version = CENVER(cen, pos); @@ -2084,9 +2084,9 @@ assert (buf.length >= LOCHDR); if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR) throw new ZipException("loc: reading failed"); - if (LOCSIG(buf) != LOCSIG) + if (!locSigAt(buf, 0)) throw new ZipException("loc: wrong sig ->" - + Long.toString(LOCSIG(buf), 16)); + + Long.toString(getSig(buf, 0), 16)); //startPos = pos; version = LOCVER(buf); flag = LOCFLG(buf); @@ -2318,9 +2318,9 @@ if (zipfs.readFullyAt(buf, 0, buf.length , locoff) != buf.length) throw new ZipException("loc: reading failed"); - if (LOCSIG(buf) != LOCSIG) + if (!locSigAt(buf, 0)) throw new ZipException("loc: wrong sig ->" - + Long.toString(LOCSIG(buf), 16)); + + Long.toString(getSig(buf, 0), 16)); int locElen = LOCEXT(buf); if (locElen < 9) // EXTT is at lease 9 bytes diff --git a/src/share/lib/security/java.security-aix b/src/share/lib/security/java.security-aix --- a/src/share/lib/security/java.security-aix +++ b/src/share/lib/security/java.security-aix @@ -1093,4 +1093,17 @@ # If a system property of the same name is also specified, it supersedes the # security property value defined here. # -#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file +#jdk.security.krb5.default.initiate.credential=always-impersonate + +# +# Trust Anchor Certificates - CA Basic Constraint check +# +# X.509 v3 certificates used as Trust Anchors (to validate signed code or TLS +# connections) must have the cA Basic Constraint field set to 'true'. Also, if +# they include a Key Usage extension, the keyCertSign bit must be set. These +# checks, enabled by default, can be disabled for backward-compatibility +# purposes with the jdk.security.allowNonCaAnchor System and Security +# properties. In the case that both properties are simultaneously set, the +# System value prevails. The default value of the property is "false". +# +#jdk.security.allowNonCaAnchor=true \ No newline at end of file diff --git a/src/share/lib/security/java.security-linux b/src/share/lib/security/java.security-linux --- a/src/share/lib/security/java.security-linux +++ b/src/share/lib/security/java.security-linux @@ -1099,4 +1099,17 @@ # If a system property of the same name is also specified, it supersedes the # security property value defined here. # -#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file +#jdk.security.krb5.default.initiate.credential=always-impersonate + +# +# Trust Anchor Certificates - CA Basic Constraint check +# +# X.509 v3 certificates used as Trust Anchors (to validate signed code or TLS +# connections) must have the cA Basic Constraint field set to 'true'. Also, if +# they include a Key Usage extension, the keyCertSign bit must be set. These +# checks, enabled by default, can be disabled for backward-compatibility +# purposes with the jdk.security.allowNonCaAnchor System and Security +# properties. In the case that both properties are simultaneously set, the +# System value prevails. The default value of the property is "false". +# +#jdk.security.allowNonCaAnchor=true \ No newline at end of file diff --git a/src/share/lib/security/java.security-macosx b/src/share/lib/security/java.security-macosx --- a/src/share/lib/security/java.security-macosx +++ b/src/share/lib/security/java.security-macosx @@ -1097,4 +1097,17 @@ # If a system property of the same name is also specified, it supersedes the # security property value defined here. # -#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file +#jdk.security.krb5.default.initiate.credential=always-impersonate + +# +# Trust Anchor Certificates - CA Basic Constraint check +# +# X.509 v3 certificates used as Trust Anchors (to validate signed code or TLS +# connections) must have the cA Basic Constraint field set to 'true'. Also, if +# they include a Key Usage extension, the keyCertSign bit must be set. These +# checks, enabled by default, can be disabled for backward-compatibility +# purposes with the jdk.security.allowNonCaAnchor System and Security +# properties. In the case that both properties are simultaneously set, the +# System value prevails. The default value of the property is "false". +# +#jdk.security.allowNonCaAnchor=true \ No newline at end of file diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris --- a/src/share/lib/security/java.security-solaris +++ b/src/share/lib/security/java.security-solaris @@ -1095,4 +1095,17 @@ # If a system property of the same name is also specified, it supersedes the # security property value defined here. # -#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file +#jdk.security.krb5.default.initiate.credential=always-impersonate + +# +# Trust Anchor Certificates - CA Basic Constraint check +# +# X.509 v3 certificates used as Trust Anchors (to validate signed code or TLS +# connections) must have the cA Basic Constraint field set to 'true'. Also, if +# they include a Key Usage extension, the keyCertSign bit must be set. These +# checks, enabled by default, can be disabled for backward-compatibility +# purposes with the jdk.security.allowNonCaAnchor System and Security +# properties. In the case that both properties are simultaneously set, the +# System value prevails. The default value of the property is "false". +# +#jdk.security.allowNonCaAnchor=true \ No newline at end of file diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows --- a/src/share/lib/security/java.security-windows +++ b/src/share/lib/security/java.security-windows @@ -1097,4 +1097,17 @@ # If a system property of the same name is also specified, it supersedes the # security property value defined here. # -#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file +#jdk.security.krb5.default.initiate.credential=always-impersonate + +# +# Trust Anchor Certificates - CA Basic Constraint check +# +# X.509 v3 certificates used as Trust Anchors (to validate signed code or TLS +# connections) must have the cA Basic Constraint field set to 'true'. Also, if +# they include a Key Usage extension, the keyCertSign bit must be set. These +# checks, enabled by default, can be disabled for backward-compatibility +# purposes with the jdk.security.allowNonCaAnchor System and Security +# properties. In the case that both properties are simultaneously set, the +# System value prevails. The default value of the property is "false". +# +#jdk.security.allowNonCaAnchor=true \ No newline at end of file diff --git a/src/solaris/back/linker_md.c b/src/solaris/back/linker_md.c --- a/src/solaris/back/linker_md.c +++ b/src/solaris/back/linker_md.c @@ -42,6 +42,7 @@ #include #include +#include "util.h" #include "path_md.h" #ifndef NATIVE #include "iomgr.h" @@ -57,8 +58,10 @@ static void dll_build_name(char* buffer, size_t buflen, const char* paths, const char* fname) { char *path, *paths_copy, *next_token; + *buffer = '\0'; - paths_copy = strdup(paths); + paths_copy = jvmtiAllocate((int)strlen(paths) + 1); + strcpy(paths_copy, paths); if (paths_copy == NULL) { return; } @@ -67,15 +70,18 @@ path = strtok_r(paths_copy, PATH_SEPARATOR, &next_token); while (path != NULL) { - snprintf(buffer, buflen, "%s/lib%s." LIB_SUFFIX, path, fname); - if (access(buffer, F_OK) == 0) { + size_t result_len = (size_t)snprintf(buffer, buflen, "%s/lib%s." LIB_SUFFIX, path, fname); + if (result_len >= buflen) { + EXIT_ERROR(JVMTI_ERROR_INVALID_LOCATION, "One or more of the library paths supplied to jdwp, " + "likely by sun.boot.library.path, is too long."); + } else if (access(buffer, F_OK) == 0) { break; } *buffer = '\0'; path = strtok_r(NULL, PATH_SEPARATOR, &next_token); } - free(paths_copy); + jvmtiDeallocate(paths_copy); } /* @@ -100,13 +106,11 @@ { const int pnamelen = pname ? strlen(pname) : 0; - *holder = '\0'; - /* Quietly truncate on buffer overflow. Should be an error. */ - if (pnamelen + (int)strlen(fname) + 10 > holderlen) { - return; - } - if (pnamelen == 0) { + if (pnamelen + (int)strlen(fname) + 10 > holderlen) { + EXIT_ERROR(JVMTI_ERROR_INVALID_LOCATION, "One or more of the library paths supplied to jdwp, " + "likely by sun.boot.library.path, is too long."); + } (void)snprintf(holder, holderlen, "lib%s." LIB_SUFFIX, fname); } else { dll_build_name(holder, holderlen, pname, fname); diff --git a/src/solaris/classes/java/net/PlainSocketImpl.java b/src/solaris/classes/java/net/PlainSocketImpl.java --- a/src/solaris/classes/java/net/PlainSocketImpl.java +++ b/src/solaris/classes/java/net/PlainSocketImpl.java @@ -31,7 +31,7 @@ import java.util.Collections; import jdk.net.*; -import static sun.net.ExtendedOptionsImpl.*; +import sun.net.ExtendedOptionsImpl; /* * On Unix systems we simply delegate to native methods. @@ -58,29 +58,59 @@ } protected void setOption(SocketOption name, T value) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - super.setOption(name, value); + if (name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + checkSetOption(name, value, SocketFlow.class); + ExtendedOptionsImpl.setFlowOption(getFileDescriptor(), (SocketFlow)value); + } else if (name == ExtendedSocketOptions.TCP_KEEPIDLE) { + checkSetOption(name, value, Integer.class); + ExtendedOptionsImpl.setTcpKeepAliveTime(getFileDescriptor(), (Integer)value); + } else if (name == ExtendedSocketOptions.TCP_KEEPINTERVAL) { + checkSetOption(name, value, Integer.class); + ExtendedOptionsImpl.setTcpKeepAliveIntvl(getFileDescriptor(), (Integer)value); + } else if (name == ExtendedSocketOptions.TCP_KEEPCOUNT) { + checkSetOption(name, value, Integer.class); + ExtendedOptionsImpl.setTcpKeepAliveProbes(getFileDescriptor(), (Integer)value); } else { - if (isClosedOrPending()) { - throw new SocketException("Socket closed"); - } - checkSetOptionPermission(name); - checkValueType(value, SocketFlow.class); - setFlowOption(getFileDescriptor(), (SocketFlow)value); + super.setOption(name, value); } } - protected T getOption(SocketOption name) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - return super.getOption(name); + private void checkSetOption(SocketOption name, T value, Class expected) throws IOException { + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); } + ExtendedOptionsImpl.checkSetOptionPermission(name); + ExtendedOptionsImpl.checkValueType(value, expected); + } + + private void checkGetOption(SocketOption name) throws IOException { if (isClosedOrPending()) { throw new SocketException("Socket closed"); } - checkGetOptionPermission(name); - SocketFlow flow = SocketFlow.create(); - getFlowOption(getFileDescriptor(), flow); - return (T)flow; + ExtendedOptionsImpl.checkGetOptionPermission(name); + } + + protected T getOption(SocketOption name) throws IOException { + if (name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + checkGetOption(name); + SocketFlow flow = SocketFlow.create(); + ExtendedOptionsImpl.getFlowOption(getFileDescriptor(), flow); + return (T)flow; + } else if (name == ExtendedSocketOptions.TCP_KEEPIDLE) { + checkGetOption(name); + int retVal = ExtendedOptionsImpl.getTcpKeepAliveTime(getFileDescriptor()); + return (T)Integer.valueOf(retVal); + } else if (name == ExtendedSocketOptions.TCP_KEEPINTERVAL) { + checkGetOption(name); + int retVal = ExtendedOptionsImpl.getTcpKeepAliveIntvl(getFileDescriptor()); + return (T)Integer.valueOf(retVal); + } else if (name == ExtendedSocketOptions.TCP_KEEPCOUNT) { + checkGetOption(name); + int retVal = ExtendedOptionsImpl.getTcpKeepAliveProbes(getFileDescriptor()); + return (T)Integer.valueOf(retVal); + } else { + return super.getOption(name); + } } protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { diff --git a/src/solaris/classes/sun/awt/X11/XIconWindow.java b/src/solaris/classes/sun/awt/X11/XIconWindow.java --- a/src/solaris/classes/sun/awt/X11/XIconWindow.java +++ b/src/solaris/classes/sun/awt/X11/XIconWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, 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 @@ -24,13 +24,26 @@ */ package sun.awt.X11; -import java.awt.*; -import java.awt.image.*; +import java.awt.AlphaComposite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.SystemColor; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferUShort; +import java.awt.image.ImageObserver; +import java.awt.image.WritableRaster; import sun.awt.IconInfo; +import sun.awt.image.ImageRepresentation; import sun.awt.image.ToolkitImage; -import sun.awt.image.ImageRepresentation; - import sun.util.logging.PlatformLogger; public class XIconWindow extends XBaseWindow { @@ -479,7 +492,7 @@ if (window == 0) { log.finest("Icon window wasn't set"); XCreateWindowParams params = getDelayedParams(); - params.add(BORDER_PIXEL, Long.valueOf(XToolkit.getAwtDefaultFg())); + params.add(BORDER_PIXEL, Long.valueOf(0)); params.add(BACKGROUND_PIXMAP, iconPixmap); params.add(COLORMAP, adata.get_awt_cmap()); params.add(DEPTH, awtImage.get_Depth()); diff --git a/src/solaris/classes/sun/awt/X11/XToolkit.java b/src/solaris/classes/sun/awt/X11/XToolkit.java --- a/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -111,7 +111,6 @@ static boolean securityWarningEnabled; private static volatile int screenWidth = -1, screenHeight = -1; // Dimensions of default screen - static long awt_defaultFg; // Pixel private static XMouseInfoPeer xPeer; /** @@ -241,9 +240,6 @@ } tryXKB(); - AwtScreenData defaultScreen = new AwtScreenData(XToolkit.getDefaultScreenData()); - awt_defaultFg = defaultScreen.get_blackpixel(); - arrowCursor = XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(), XCursorFontConstants.XC_arrow); areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true")); @@ -1335,7 +1331,6 @@ } static native long getDefaultXColormap(); - static native long getDefaultScreenData(); static ColorModel screenmodel; @@ -2026,10 +2021,6 @@ } } - static long getAwtDefaultFg() { - return awt_defaultFg; - } - static boolean isLeftMouseButton(MouseEvent me) { switch (me.getID()) { case MouseEvent.MOUSE_PRESSED: diff --git a/src/solaris/native/java/net/ExtendedOptionsImpl.c b/src/solaris/native/java/net/ExtendedOptionsImpl.c --- a/src/solaris/native/java/net/ExtendedOptionsImpl.c +++ b/src/solaris/native/java/net/ExtendedOptionsImpl.c @@ -25,6 +25,10 @@ #include #include +#if defined(__linux__) || defined(MACOSX) +#include +#include +#endif #include "net_util.h" #include "jdk_net_SocketFlow.h" @@ -328,9 +332,193 @@ return JNI_FALSE; } +// Keep alive options are available for MACOSX and Linux only for +// the time being. +#if defined(__linux__) || defined(MACOSX) + +// Map socket option level/name to OS specific constant +#ifdef __linux__ +#define SOCK_OPT_LEVEL SOL_TCP +#define SOCK_OPT_NAME_KEEPIDLE TCP_KEEPIDLE +#define SOCK_OPT_NAME_KEEPIDLE_STR "TCP_KEEPIDLE" +#endif +#ifdef MACOSX +#define SOCK_OPT_LEVEL IPPROTO_TCP +#define SOCK_OPT_NAME_KEEPIDLE TCP_KEEPALIVE +#define SOCK_OPT_NAME_KEEPIDLE_STR "TCP_KEEPALIVE" +#endif + +static jint socketOptionSupported(jint sockopt) { + jint one = 1; + jint rv, s; + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) { + return 0; + } + rv = setsockopt(s, SOCK_OPT_LEVEL, sockopt, (void *) &one, sizeof (one)); + if (rv != 0 && errno == ENOPROTOOPT) { + rv = 0; + } else { + rv = 1; + } + close(s); + return rv; +} + +static void handleError(JNIEnv *env, jint rv, const char *errmsg) { + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else { + JNU_ThrowByNameWithLastError(env, "java/net/SocketException", errmsg); + } + } +} + +static void setTcpSocketOption +(JNIEnv *env, jobject fileDesc, jint optval, int opt, int optlevel, const char* errmsg) { + int fd = getFD(env, fileDesc); + + if (fd < 0) { + NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); + return; + } else { + jint rv = setsockopt(fd, optlevel, opt, &optval, sizeof (optval)); + handleError(env, rv, errmsg); + } +} + +static jint getTcpSocketOption +(JNIEnv *env, jobject fileDesc, int opt, int optlevel, const char* errmsg) { + int fd = getFD(env, fileDesc); + + if (fd < 0) { + NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); + return -1; + } else { + jint optval, rv; + socklen_t sz = sizeof (optval); + rv = getsockopt(fd, optlevel, opt, &optval, &sz); + handleError(env, rv, errmsg); + return optval; + } +} + +#else /* __linux__ || MACOSX */ + +/* Keep alive options not supported for non-linux/non-macosx so throw UnsupportedOpExc */ + +static void setTcpSocketOption +(JNIEnv *env, jobject fileDesc, jint optval, int opt, int optlevel, const char* errmsg) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +static jint getTcpSocketOption +(JNIEnv *env, jobject fileDesc, int opt, int optlevel, const char* errmsg) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +#endif /* __linux__ || MACOSX*/ + #endif /* __solaris__ */ JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported (JNIEnv *env, jclass UNUSED) { return flowSupported0(); } + +#if defined(__linux__) || defined(MACOSX) + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: keepAliveOptionsSupported + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_keepAliveOptionsSupported +(JNIEnv *env, jobject unused) { + return socketOptionSupported(SOCK_OPT_NAME_KEEPIDLE) && socketOptionSupported(TCP_KEEPCNT) + && socketOptionSupported(TCP_KEEPINTVL); +} + +#else + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: keepAliveOptionsSupported + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_keepAliveOptionsSupported +(JNIEnv *env, jobject unused) { + return JNI_FALSE; +} + +#endif /* __linux__ || MACOSX */ + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: setTcpKeepAliveProbes + * Signature: (Ljava/io/FileDescriptor;I)V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveProbes +(JNIEnv *env, jobject unused, jobject fileDesc, jint optval) { + setTcpSocketOption(env, fileDesc, optval, TCP_KEEPCNT, SOCK_OPT_LEVEL, + "set option TCP_KEEPCNT failed"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: setTcpKeepAliveTime + * Signature: (Ljava/io/FileDescriptor;I)V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveTime +(JNIEnv *env, jobject unused, jobject fileDesc, jint optval) { + setTcpSocketOption(env, fileDesc, optval, SOCK_OPT_NAME_KEEPIDLE, SOCK_OPT_LEVEL, + "set option " SOCK_OPT_NAME_KEEPIDLE_STR " failed"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: setTcpKeepAliveIntvl + * Signature: (Ljava/io/FileDescriptor;I)V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveIntvl +(JNIEnv *env, jobject unused, jobject fileDesc, jint optval) { + setTcpSocketOption(env, fileDesc, optval, TCP_KEEPINTVL, SOCK_OPT_LEVEL, + "set option TCP_KEEPINTVL failed"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: getTcpKeepAliveProbes + * Signature: (Ljava/io/FileDescriptor;)I + */ +JNIEXPORT jint JNICALL Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveProbes +(JNIEnv *env, jobject unused, jobject fileDesc) { + return getTcpSocketOption(env, fileDesc, TCP_KEEPCNT, SOCK_OPT_LEVEL, + "get option TCP_KEEPCNT failed"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: getTcpKeepAliveTime + * Signature: (Ljava/io/FileDescriptor;)I + */ +JNIEXPORT jint JNICALL Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveTime +(JNIEnv *env, jobject unused, jobject fileDesc) { + return getTcpSocketOption(env, fileDesc, SOCK_OPT_NAME_KEEPIDLE, SOCK_OPT_LEVEL, + "get option " SOCK_OPT_NAME_KEEPIDLE_STR " failed"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: getTcpKeepAliveIntvl + * Signature: (Ljava/io/FileDescriptor;)I + */ +JNIEXPORT jint JNICALL Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveIntvl +(JNIEnv *env, jobject unused, jobject fileDesc) { + return getTcpSocketOption(env, fileDesc, TCP_KEEPINTVL, SOCK_OPT_LEVEL, + "get option TCP_KEEPINTVL failed"); +} diff --git a/src/solaris/native/java/util/TimeZone_md.c b/src/solaris/native/java/util/TimeZone_md.c --- a/src/solaris/native/java/util/TimeZone_md.c +++ b/src/solaris/native/java/util/TimeZone_md.c @@ -122,6 +122,7 @@ struct dirent64 *entry = NULL; char *pathname = NULL; char *tz = NULL; + long name_max = 0; if (strcmp(dir, ZONEINFO_DIR) == 0) { /* fast path for 1st iteration */ @@ -145,7 +146,13 @@ return NULL; } - entry = (struct dirent64 *) malloc((size_t) pathconf(dir, _PC_NAME_MAX)); + name_max = pathconf(dir, _PC_NAME_MAX); + // If pathconf did not work, fall back to a mimimum buffer size. + if (name_max < 1024) { + name_max = 1024; + } + + entry = (struct dirent64 *)malloc(offsetof(struct dirent64, d_name) + name_max + 1); if (entry == NULL) { (void) closedir(dirp); return NULL; diff --git a/src/solaris/native/sun/xawt/XToolkit.c b/src/solaris/native/sun/xawt/XToolkit.c --- a/src/solaris/native/sun/xawt/XToolkit.c +++ b/src/solaris/native/sun/xawt/XToolkit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, 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 @@ -143,13 +143,6 @@ return (jlong) defaultConfig->awt_cmap; } -JNIEXPORT jlong JNICALL Java_sun_awt_X11_XToolkit_getDefaultScreenData - (JNIEnv *env, jclass clazz) -{ - return ptr_to_jlong(getDefaultConfig(DefaultScreen(awt_display))); -} - - JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { diff --git a/src/windows/back/linker_md.c b/src/windows/back/linker_md.c --- a/src/windows/back/linker_md.c +++ b/src/windows/back/linker_md.c @@ -36,13 +36,16 @@ #include "sys.h" +#include "util.h" #include "path_md.h" static void dll_build_name(char* buffer, size_t buflen, const char* paths, const char* fname) { char *path, *paths_copy, *next_token; + *buffer = '\0'; - paths_copy = strdup(paths); + paths_copy = jvmtiAllocate((int)strlen(paths) + 1); + strcpy(paths_copy, paths); if (paths_copy == NULL) { return; } @@ -51,15 +54,18 @@ path = strtok_s(paths_copy, PATH_SEPARATOR, &next_token); while (path != NULL) { - _snprintf(buffer, buflen, "%s\\%s.dll", path, fname); - if (_access(buffer, 0) == 0) { + size_t result_len = (size_t)_snprintf(buffer, buflen, "%s\\%s.dll", path, fname); + if (result_len >= buflen) { + EXIT_ERROR(JVMTI_ERROR_INVALID_LOCATION, "One or more of the library paths supplied to jdwp, " + "likely by sun.boot.library.path, is too long."); + } else if (_access(buffer, 0) == 0) { break; } *buffer = '\0'; path = strtok_s(NULL, PATH_SEPARATOR, &next_token); } - free(paths_copy); + jvmtiDeallocate(paths_copy); } /* @@ -106,13 +112,11 @@ { const int pnamelen = pname ? (int)strlen(pname) : 0; - *holder = '\0'; - /* Quietly truncates on buffer overflow. Should be an error. */ - if (pnamelen + (int)strlen(fname) + 10 > holderlen) { - return; - } - if (pnamelen == 0) { + if (pnamelen + (int)strlen(fname) + 10 > holderlen) { + EXIT_ERROR(JVMTI_ERROR_INVALID_LOCATION, "One or more of the library paths supplied to jdwp, " + "likely by sun.boot.library.path, is too long."); + } sprintf(holder, "%s.dll", fname); } else { dll_build_name(holder, holderlen, pname, fname); diff --git a/src/windows/native/java/net/ExtendedOptionsImpl.c b/src/windows/native/java/net/ExtendedOptionsImpl.c --- a/src/windows/native/java/net/ExtendedOptionsImpl.c +++ b/src/windows/native/java/net/ExtendedOptionsImpl.c @@ -60,3 +60,81 @@ (JNIEnv *env, jclass UNUSED) { return JNI_FALSE; } + +/* Keepalive options not supported */ + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: keepAliveOptionsSupported + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_keepAliveOptionsSupported +(JNIEnv *env, jobject unused) { + return JNI_FALSE; +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: setTcpKeepAliveProbes + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveProbes +(JNIEnv *env, jobject unused, jobject fileDesc, jint optval) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: setTcpKeepAliveTime + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveTime +(JNIEnv *env, jobject unused, jobject fileDesc, jint optval) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: setTcpKeepAliveIntvl + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setTcpKeepAliveIntvl +(JNIEnv *env, jobject unused, jobject fileDesc, jint optval) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: getTcpKeepAliveProbes + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveProbes +(JNIEnv *env, jobject unused, jobject fileDesc) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: getTcpKeepAliveTime + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveTime +(JNIEnv *env, jobject unused, jobject fileDesc) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: getTcpKeepAliveIntvl + * Signature: (I)I; + */ +JNIEXPORT jint JNICALL Java_sun_net_ExtendedOptionsImpl_getTcpKeepAliveIntvl +(JNIEnv *env, jobject unused, jobject fileDesc) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} diff --git a/src/windows/native/java/net/Inet4AddressImpl.c b/src/windows/native/java/net/Inet4AddressImpl.c --- a/src/windows/native/java/net/Inet4AddressImpl.c +++ b/src/windows/native/java/net/Inet4AddressImpl.c @@ -484,7 +484,7 @@ ReplyBuffer = (VOID*) malloc(ReplySize); if (ReplyBuffer == NULL) { IcmpCloseHandle(hIcmpFile); - NET_ThrowNew(env, WSAGetLastError(), "Unable to allocate memory"); + NET_ThrowNew(env, -1, "Unable to allocate memory"); return JNI_FALSE; } diff --git a/src/windows/native/java/net/Inet6AddressImpl.c b/src/windows/native/java/net/Inet6AddressImpl.c --- a/src/windows/native/java/net/Inet6AddressImpl.c +++ b/src/windows/native/java/net/Inet6AddressImpl.c @@ -460,7 +460,7 @@ ReplyBuffer = (VOID*) malloc(ReplySize); if (ReplyBuffer == NULL) { IcmpCloseHandle(hIcmpFile); - NET_ThrowNew(env, WSAGetLastError(), "Unable to allocate memory"); + NET_ThrowNew(env, -1, "Unable to allocate memory"); return JNI_FALSE; } diff --git a/src/windows/native/java/net/SocketInputStream.c b/src/windows/native/java/net/SocketInputStream.c --- a/src/windows/native/java/net/SocketInputStream.c +++ b/src/windows/native/java/net/SocketInputStream.c @@ -134,12 +134,13 @@ (*env)->SetByteArrayRegion(env, data, off, nread, (jbyte *)bufP); } else { if (nread < 0) { + int err = WSAGetLastError(); // Check if the socket has been closed since we last checked. // This could be a reason for recv failing. if ((*env)->GetIntField(env, fdObj, IO_fd_fdID) == -1) { NET_ThrowSocketException(env, "Socket closed"); } else { - switch (WSAGetLastError()) { + switch (err) { case WSAEINTR: JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); diff --git a/src/windows/native/sun/net/spi/DefaultProxySelector.c b/src/windows/native/sun/net/spi/DefaultProxySelector.c --- a/src/windows/native/sun/net/spi/DefaultProxySelector.c +++ b/src/windows/native/sun/net/spi/DefaultProxySelector.c @@ -117,12 +117,13 @@ char regserver[MAX_STR_LEN]; char override[MAX_STR_LEN]; char *s, *s2; + char *ctx = NULL; int pport = 0; int defport = 0; char *phost; /** - * Let's opem the Registry entry. We'll check a few values in it: + * Let's open the Registry entry. We'll check a few values in it: * * - ProxyEnable: 0 means no proxy, 1 means use the proxy * - ProxyServer: a string that can take 2 forms: @@ -167,7 +168,7 @@ * The semicolons (;) separated entries have to be matched with the * the beginning of the hostname. */ - s = strtok(override, "; "); + s = strtok_s(override, "; ", &ctx); urlhost = (*env)->GetStringUTFChars(env, host, &isCopy); if (urlhost == NULL) { if (!(*env)->ExceptionCheck(env)) @@ -184,7 +185,7 @@ (*env)->ReleaseStringUTFChars(env, host, urlhost); goto noproxy; } - s = strtok(NULL, "; "); + s = strtok_s(NULL, "; ", &ctx); } if (isCopy == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, host, urlhost); diff --git a/src/windows/native/sun/windows/awt_Window.cpp b/src/windows/native/sun/windows/awt_Window.cpp --- a/src/windows/native/sun/windows/awt_Window.cpp +++ b/src/windows/native/sun/windows/awt_Window.cpp @@ -1544,6 +1544,15 @@ CHECK_NULL(sequencedEventConst); } + static jclass windowCls = NULL; + if (windowCls == NULL) { + jclass windowClsLocal = env->FindClass("java/awt/Window"); + CHECK_NULL(windowClsLocal); + windowCls = (jclass)env->NewGlobalRef(windowClsLocal); + env->DeleteLocalRef(windowClsLocal); + CHECK_NULL(windowCls); + } + if (env->EnsureLocalCapacity(3) < 0) { return; } @@ -1554,6 +1563,28 @@ AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite); if (awtOpposite != NULL) { jOpposite = awtOpposite->GetTarget(env); + if ((jOpposite != NULL) && + !env->IsInstanceOf(jOpposite, windowCls)) { + env->DeleteLocalRef(jOpposite); + jOpposite = NULL; + + HWND parent = AwtComponent::GetTopLevelParentForWindow(opposite); + if ((parent != NULL) && (parent != opposite)) { + if (parent == GetHWnd()) { + jOpposite = env->NewLocalRef(target); + } else { + AwtComponent* awtParent = AwtComponent::GetComponent(parent); + if (awtParent != NULL) { + jOpposite = awtParent->GetTarget(env); + if ((jOpposite != NULL) && + !env->IsInstanceOf(jOpposite, windowCls)) { + env->DeleteLocalRef(jOpposite); + jOpposite = NULL; + } + } + } + } + } } } jobject event = env->NewObject(wClassEvent, wEventInitMID, target, id, diff --git a/test/ProblemList.txt b/test/ProblemList.txt --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -318,6 +318,13 @@ ############################################################################ # jdk_sound +javax/sound/sampled/DirectAudio/bug6372428.java 8055097 generic-all +javax/sound/sampled/Clip/bug5070081.java 8055097 generic-all +javax/sound/sampled/DataLine/LongFramePosition.java 8055097 generic-all + +javax/sound/sampled/Clip/Drain/ClipDrain.java 7062792 generic-all + +javax/sound/sampled/Mixers/DisabledAssertionCrash.java 7067310 generic-all ############################################################################ diff --git a/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java b/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java --- a/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java +++ b/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java @@ -25,6 +25,7 @@ * @test * @bug 8007267 * @summary [macosx] com.apple.eawt.Application.setDefaultMenuBar is not working + * @requires (os.family == "mac") * @author leonid.romanov@oracle.com * @run main DefaultMenuBarTest */ @@ -32,7 +33,6 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; -import sun.awt.*; import java.lang.reflect.Method; @@ -41,7 +41,7 @@ static volatile int listenerCallCounter = 0; public static void main(String[] args) throws Exception { - if (sun.awt.OSInfo.getOSType() != sun.awt.OSInfo.OSType.MACOSX) { + if (!System.getProperty("os.name").contains("OS X")) { System.out.println("This test is for MacOS only. Automatically passed on other platforms."); return; } @@ -53,7 +53,6 @@ } }); - SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); Robot robot = new Robot(); robot.setAutoDelay(100); @@ -62,7 +61,7 @@ robot.keyRelease(ks.getKeyCode()); robot.keyRelease(KeyEvent.VK_META); - toolkit.realSync(); + robot.waitForIdle(); if (listenerCallCounter != 1) { throw new Exception("Test failed: ActionListener either wasn't called or was called more than once"); diff --git a/test/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java b/test/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java --- a/test/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java +++ b/test/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java @@ -24,6 +24,7 @@ /* * @test * @bug 4928019 + * @key headful * @summary Makes sure all the basic classes can be created with GTK. * @author Scott Violet */ diff --git a/test/com/sun/java/swing/plaf/gtk/Test6635110.java b/test/com/sun/java/swing/plaf/gtk/Test6635110.java --- a/test/com/sun/java/swing/plaf/gtk/Test6635110.java +++ b/test/com/sun/java/swing/plaf/gtk/Test6635110.java @@ -23,6 +23,7 @@ /* @test @bug 6635110 + @key headful @summary GTK icons should not throw NPE when called by non-GTK UI @author Peter Zhelezniakov @run main Test6635110 diff --git a/test/com/sun/java/swing/plaf/gtk/Test6963870.java b/test/com/sun/java/swing/plaf/gtk/Test6963870.java --- a/test/com/sun/java/swing/plaf/gtk/Test6963870.java +++ b/test/com/sun/java/swing/plaf/gtk/Test6963870.java @@ -23,6 +23,7 @@ /* @test @bug 6963870 + @key headful @summary Tests that GTKPainter.ListTableFocusBorder.getBorderInsets() doesn't return null @author Peter Zhelezniakov diff --git a/test/com/sun/jndi/ldap/LdapCtx/Reconnect.java b/test/com/sun/jndi/ldap/LdapCtx/Reconnect.java new file mode 100644 --- /dev/null +++ b/test/com/sun/jndi/ldap/LdapCtx/Reconnect.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2019, 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. + */ + +import javax.naming.Context; +import javax.naming.ldap.InitialLdapContext; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.util.Hashtable; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +/* + * @test + * @bug 8217606 + * @summary The LdapContext.reconnect method allows LDAP clients to initiate an + * LDAP bind operation on the existing connection. Invoking this method + * should not open a new connection under those circumstances. + * + * @library ../lib/ + * @run main Reconnect + */ +public class Reconnect { + + private static final byte[] BIND_RESPONSE = { + 0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, + 0x01, 0x00, 0x04, 0x00, 0x04, 0x00 + }; + + /* + * This test checks that there's only one connection from the client to + * the server. + * + * The mechanics is as follows. The first connection is awaited for some + * generous timeout to factor in a possibility of running on a slow system. + * Once the connection has been made, the second timeout begins. This + * second timeout is smaller. The test then verifies that no further + * connections have been made for that amount of time. + */ + public static void main(String[] args) throws Exception { + + final Semaphore s = new Semaphore(0); + + BaseLdapServer server = new BaseLdapServer() { + + @Override + protected void beforeConnectionHandled(Socket socket) { + // Increment the number of connections from LDAP client + s.release(1); + } + + @Override + protected void handleRequest(Socket socket, + LdapMessage msg, + OutputStream out) + throws IOException + { + switch (msg.getOperation()) { + case BIND_REQUEST: + out.write(BIND_RESPONSE); + default: + break; + } + } + }; + + try (BaseLdapServer s1 = server.start()) { + Hashtable env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, + "ldap://" + InetAddress.getLoopbackAddress().getHostName() + + ":" + server.getPort()); + env.put("java.naming.ldap.version", "3"); + + // open connection + InitialLdapContext context = new InitialLdapContext(env, null); + + // send bind request + context.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple"); + context.addToEnvironment(Context.SECURITY_PRINCIPAL, "test"); + context.addToEnvironment(Context.SECURITY_CREDENTIALS, "secret"); + + context.reconnect(null); + } + + if (!s.tryAcquire(60L, TimeUnit.SECONDS)) { + throw new RuntimeException("No connection has been made"); + } + + if (s.tryAcquire(5L, TimeUnit.SECONDS)) { + throw new RuntimeException("Expected 1 connection, but found: " + + (s.availablePermits() + 2)); + } + } +} diff --git a/test/com/sun/jndi/ldap/lib/BaseLdapServer.java b/test/com/sun/jndi/ldap/lib/BaseLdapServer.java new file mode 100644 --- /dev/null +++ b/test/com/sun/jndi/ldap/lib/BaseLdapServer.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2019, 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. + */ + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; +import java.util.logging.*; +import static java.util.logging.Level.*; + +/* + * A bare-bones (testing aid) server for LDAP scenarios. + * + * Override the following methods to provide customized behavior + * + * * beforeConnectionHandled + * * handleRequest + * + * Instances of this class are safe for use by multiple threads. + */ +public class BaseLdapServer implements Closeable { + + private static final Logger logger = Logger.getLogger("BaseLdapServer"); + + private final Thread acceptingThread = new Thread(this::acceptConnections); + private final ServerSocket serverSocket; + private final List socketList = new ArrayList<>(); + private final ExecutorService connectionsPool; + + private final Object lock = new Object(); + /* + * 3-valued state to detect restarts and other programming errors. + */ + private State state = State.NEW; + + private enum State { + NEW, + STARTED, + STOPPED + } + + public BaseLdapServer() throws IOException { + this(new ServerSocket(0, 0, InetAddress.getLoopbackAddress())); + } + + public BaseLdapServer(ServerSocket serverSocket) { + this.serverSocket = Objects.requireNonNull(serverSocket); + this.connectionsPool = Executors.newCachedThreadPool(); + } + + private void acceptConnections() { + logger().log(INFO, "Server is accepting connections at port {0}", + getPort()); + try { + while (isRunning()) { + Socket socket = serverSocket.accept(); + logger().log(INFO, "Accepted new connection at {0}", socket); + synchronized (lock) { + // Recheck if the server is still running + // as someone has to close the `socket` + if (isRunning()) { + socketList.add(socket); + } else { + closeSilently(socket); + } + } + connectionsPool.submit(() -> handleConnection(socket)); + } + } catch (IOException | RejectedExecutionException e) { + if (isRunning()) { + throw new RuntimeException( + "Unexpected exception while accepting connections", e); + } + } finally { + logger().log(INFO, "Server stopped accepting connections at port {0}", + getPort()); + } + } + + /* + * A "Template Method" describing how a connection (represented by a socket) + * is handled. + * + * The socket is closed immediately before the method returns (normally or + * abruptly). + */ + private void handleConnection(Socket socket) { + // No need to close socket's streams separately, they will be closed + // automatically when `socket.close()` is called + beforeConnectionHandled(socket); + try { + OutputStream out = socket.getOutputStream(); + InputStream in = socket.getInputStream(); + byte[] inBuffer = new byte[1024]; + int count; + byte[] request; + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int msgLen = -1; + + // As inBuffer.length > 0, at least 1 byte is read + while ((count = in.read(inBuffer)) > 0) { + buffer.write(inBuffer, 0, count); + if (msgLen <= 0) { + msgLen = LdapMessage.getMessageLength(buffer.toByteArray()); + } + + if (msgLen > 0 && buffer.size() >= msgLen) { + if (buffer.size() > msgLen) { + byte[] tmpBuffer = buffer.toByteArray(); + request = Arrays.copyOf(tmpBuffer, msgLen); + buffer.reset(); + buffer.write(tmpBuffer, msgLen, tmpBuffer.length - msgLen); + } else { + request = buffer.toByteArray(); + buffer.reset(); + } + msgLen = -1; + } else { + logger.log(INFO, "Request message incomplete, " + + "bytes received {0}, expected {1}", new Integer[] { buffer.size(), msgLen}); + continue; + } + handleRequest(socket, new LdapMessage(request), out); + } + } catch (Throwable t) { + if (!isRunning()) { + logger.log(INFO, "Connection Handler exit {0}", t.getMessage()); + } else { + t.printStackTrace(); + } + } finally { + if (socket != null) { + try { + socket.close(); + } catch (Exception e) { + } + } + } + } + + /* + * Called first thing in `handleConnection()`. + * + * Override to customize the behavior. + */ + protected void beforeConnectionHandled(Socket socket) { /* empty */ } + + /* + * Called after an LDAP request has been read in `handleConnection()`. + * + * Override to customize the behavior. + */ + protected void handleRequest(Socket socket, + LdapMessage request, + OutputStream out) + throws IOException + { + logger().log(INFO, "Discarding message {0} from {1}. " + + "Override {2}.handleRequest to change this behavior.", + new Object[] {request, socket, getClass().getName()}); + } + + /* + * To be used by subclasses. + */ + protected final Logger logger() { + return logger; + } + + /* + * Starts this server. May be called only once. + */ + public BaseLdapServer start() { + synchronized (lock) { + if (state != State.NEW) { + throw new IllegalStateException(state.toString()); + } + state = State.STARTED; + logger().log(INFO, "Starting server at port {0}", getPort()); + acceptingThread.start(); + return this; + } + } + + /* + * Stops this server. + * + * May be called at any time, even before a call to `start()`. In the latter + * case the subsequent call to `start()` will throw an exception. Repeated + * calls to this method have no effect. + * + * Stops accepting new connections, interrupts the threads serving already + * accepted connections and closes all the sockets. + */ + @Override + public void close() { + synchronized (lock) { + if (state == State.STOPPED) { + return; + } + state = State.STOPPED; + logger().log(INFO, "Stopping server at port {0}", getPort()); + acceptingThread.interrupt(); + closeSilently(serverSocket); + // It's important to signal an interruption so that overridden + // methods have a chance to return if they use + // interruption-sensitive blocking operations. However, blocked I/O + // operations on the socket will NOT react on that, hence the socket + // also has to be closed to propagate shutting down. + connectionsPool.shutdownNow(); + socketList.forEach(BaseLdapServer.this::closeSilently); + } + } + + /** + * Returns the local port this server is listening at. + * + * @return the port this server is listening at + */ + public int getPort() { + return serverSocket.getLocalPort(); + } + + /* + * Returns a flag to indicate whether this server is running or not. + * + * @return {@code true} if this server is running, {@code false} otherwise. + */ + public boolean isRunning() { + synchronized (lock) { + return state == State.STARTED; + } + } + + /* + * To be used by subclasses. + */ + protected final void closeSilently(Closeable resource) { + try { + resource.close(); + } catch (IOException ignored) { } + } +} diff --git a/test/com/sun/jndi/ldap/lib/LdapMessage.java b/test/com/sun/jndi/ldap/lib/LdapMessage.java new file mode 100644 --- /dev/null +++ b/test/com/sun/jndi/ldap/lib/LdapMessage.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2019, 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. + */ + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.Stream; + +/** + * An LDAP message. + */ +public class LdapMessage { + + private final byte[] message; + private int messageID; + private Operation operation; + + public enum Operation { + BIND_REQUEST(0x60, "BindRequest"), // [APPLICATION 0] + BIND_RESPONSE(0x61, "BindResponse"), // [APPLICATION 1] + UNBIND_REQUEST(0x42, "UnbindRequest"), // [APPLICATION 2] + SEARCH_REQUEST(0x63, "SearchRequest"), // [APPLICATION 3] + SEARCH_RESULT_ENTRY(0x64, "SearchResultEntry"), // [APPLICATION 4] + SEARCH_RESULT_DONE(0x65, "SearchResultDone"), // [APPLICATION 5] + MODIFY_REQUEST(0x66, "ModifyRequest"), // [APPLICATION 6] + MODIFY_RESPONSE(0x67, "ModifyResponse"), // [APPLICATION 7] + ADD_REQUEST(0x68, "AddRequest"), // [APPLICATION 8] + ADD_RESPONSE(0x69, "AddResponse"), // [APPLICATION 9] + DELETE_REQUEST(0x4A, "DeleteRequest"), // [APPLICATION 10] + DELETE_RESPONSE(0x6B, "DeleteResponse"), // [APPLICATION 11] + MODIFY_DN_REQUEST(0x6C, "ModifyDNRequest"), // [APPLICATION 12] + MODIFY_DN_RESPONSE(0x6D, "ModifyDNResponse"), // [APPLICATION 13] + COMPARE_REQUEST(0x6E, "CompareRequest"), // [APPLICATION 14] + COMPARE_RESPONSE(0x6F, "CompareResponse"), // [APPLICATION 15] + ABANDON_REQUEST(0x50, "AbandonRequest"), // [APPLICATION 16] + SEARCH_RESULT_REFERENCE(0x73, "SearchResultReference"), // [APPLICATION 19] + EXTENDED_REQUEST(0x77, "ExtendedRequest"), // [APPLICATION 23] + EXTENDED_RESPONSE(0x78, "ExtendedResponse"), // [APPLICATION 24] + INTERMEDIATE_RESPONSE(0x79, "IntermediateResponse"); // [APPLICATION 25] + + private final int id; + private final String name; + + Operation(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + @Override + public String toString() { + return name; + } + + private static Operation fromId(int id) { + Optional optional = Stream.of(Operation.values()) + .filter(o -> o.id == id).findFirst(); + if (optional.isPresent()) { + return optional.get(); + } else { + throw new RuntimeException( + "Unknown id " + id + " for enum Operation."); + } + } + } + + public LdapMessage(byte[] message) { + this.message = message; + parse(); + } + + public LdapMessage(String hexString) { + this(parseHexBinary(hexString)); + } + + // Extracts the message ID and operation ID from an LDAP protocol encoding + private void parse() { + if (message == null || message.length < 2) { + throw new RuntimeException( + "Invalid ldap message: " + Arrays.toString(message)); + } + + if (message[0] != 0x30) { + throw new RuntimeException("Bad LDAP encoding in message, " + + "expected ASN.1 SEQUENCE tag (0x30), encountered " + + message[0]); + } + + int index = 2; + if ((message[1] & 0x80) == 0x80) { + index += (message[1] & 0x0F); + } + + if (message[index] != 0x02) { + throw new RuntimeException("Bad LDAP encoding in message, " + + "expected ASN.1 INTEGER tag (0x02), encountered " + + message[index]); + } + int length = message[index + 1]; + index += 2; + messageID = new BigInteger(1, + Arrays.copyOfRange(message, index, index + length)).intValue(); + index += length; + int operationID = message[index]; + operation = Operation.fromId(operationID); + } + + /** + * Return original ldap message in byte array. + * + * @return original ldap message + */ + public byte[] getMessage() { + return Arrays.copyOf(message, message.length); + } + + /** + * Return ldap message id. + * + * @return ldap message id. + */ + public int getMessageID() { + return messageID; + } + + /** + * Return ldap message's operation. + * + * @return ldap message's operation. + */ + public Operation getOperation() { + return operation; + } + + private static byte[] parseHexBinary(String s) { + + final int len = s.length(); + + // "111" is not a valid hex encoding. + if (len % 2 != 0) { + throw new IllegalArgumentException( + "hexBinary needs to be even-length: " + s); + } + + byte[] out = new byte[len / 2]; + + for (int i = 0; i < len; i += 2) { + int h = Character.digit(s.charAt(i), 16); + int l = Character.digit(s.charAt(i + 1), 16); + if (h == -1 || l == -1) { + throw new IllegalArgumentException( + "contains illegal character for hexBinary: " + s); + } + + out[i / 2] = (byte) (h * 16 + l); + } + + return out; + } + + public static int getMessageLength(byte[] encoding) { + if (encoding.length < 2) { + // not enough data to extract msg len, just return -1 + return -1; + } + + if (encoding[0] != 0x30) { + throw new RuntimeException("Error: bad LDAP encoding message: " + + "expected ASN.1 SEQUENCE tag (0x30), encountered " + + encoding[0]); + } + + int len; + int index = 1; + int payloadLen = 0; + + if ((encoding[1] & 0x80) == 0x80) { + len = (encoding[1] & 0x0F); + index++; + } else { + len = 1; + } + + if (len > 4) { + throw new RuntimeException( + "Error: LDAP encoding message payload too large"); + } + + if (encoding.length < index + len) { + // additional data required to extract payload len, return -1 + return -1; + } + + for (byte b : Arrays.copyOfRange(encoding, index, index + len)) { + payloadLen = payloadLen << 8 | (b & 0xFF); + } + + if (payloadLen <= 0) { + throw new RuntimeException( + "Error: invalid LDAP encoding message length or payload too large"); + } + + return index + len + payloadLen; + } +} diff --git a/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java b/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java new file mode 100644 --- /dev/null +++ b/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013, 2015, 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 4980592 + @summary switching user in XP causes an NPE in + sun.awt.windows.WWindowPeer.displayChanged + @requires (os.family == "windows") + @author son@sparc.spb.su: area=embedded + @run main DisplayChangedTest + */ +/** + * DisplayChangedTest.java + * + * summary: switching user in XP causes an NPE in + * sun.awt.windows.WWindowPeer.displayChanged + */ +import java.awt.Frame; +import java.awt.Dialog; +import java.awt.TextArea; +import java.awt.peer.ComponentPeer; +import java.awt.peer.FramePeer; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Field; + +import sun.awt.AWTAccessor; + +public class DisplayChangedTest { + + /** + * Test fails if it throws any exception. + * + * @throws Exception + */ + private void init() throws Exception { + + if (!System.getProperty("os.name").startsWith("Windows")) { + System.out.println("This is Windows only test."); + return; + } + + Frame frame = new Frame("AWT Frame"); + frame.pack(); + + FramePeer frame_peer = (FramePeer) AWTAccessor.getComponentAccessor() + .getPeer(frame); + Class comp_peer_class = Class.forName("sun.awt.windows.WComponentPeer"); + Field hwnd_field = comp_peer_class.getDeclaredField("hwnd"); + hwnd_field.setAccessible(true); + long hwnd = hwnd_field.getLong(frame_peer); + + Class clazz = Class.forName("sun.awt.windows.WEmbeddedFrame"); + Constructor constructor = clazz + .getConstructor(new Class[]{long.class}); + Frame embedded_frame = (Frame) constructor + .newInstance(new Object[]{new Long(hwnd)}); + frame.setVisible(true); + + ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer( + embedded_frame); + Class peerClass = peer.getClass(); + Method displayChangedM = peerClass.getMethod("displayChanged", + new Class[0]); + displayChangedM.invoke(peer, null); + embedded_frame.dispose(); + frame.dispose(); + + } + + public static void main(String args[]) throws Exception { + new DisplayChangedTest().init(); + } + +} diff --git a/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java b/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java new file mode 100644 --- /dev/null +++ b/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013, 2015, 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 6345002 + @summary grab problems with EmbeddedFrame + @requires (os.family == "windows") + @author Oleg.Semenov@sun.com area=EmbeddedFrame + @run main EmbeddedFrameGrabTest + */ +/** + * EmbeddedFrameGrabTest.java + * + * summary: grab problems with EmbeddedFrame + */ +import java.awt.Frame; +import java.awt.peer.FramePeer; +import javax.swing.JComboBox; +import java.awt.Panel; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.Rectangle; +import java.awt.TextArea; +import java.awt.Dialog; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; + +import sun.awt.AWTAccessor; + +public class EmbeddedFrameGrabTest { + + /** + * Test fails if it throws any exception. + * + * @throws Exception + */ + private void init() throws Exception { + + if (!System.getProperty("os.name").startsWith("Windows")) { + System.out.println("This is Windows only test."); + return; + } + + final Frame frame = new Frame("AWT Frame"); + frame.pack(); + frame.setSize(200, 200); + FramePeer frame_peer = (FramePeer) AWTAccessor.getComponentAccessor() + .getPeer(frame); + Class comp_peer_class + = Class.forName("sun.awt.windows.WComponentPeer"); + Field hwnd_field = comp_peer_class.getDeclaredField("hwnd"); + hwnd_field.setAccessible(true); + long hwnd = hwnd_field.getLong(frame_peer); + + Class clazz = Class.forName("sun.awt.windows.WEmbeddedFrame"); + Constructor constructor + = clazz.getConstructor(new Class[]{long.class}); + final Frame embedded_frame + = (Frame) constructor.newInstance(new Object[]{ + new Long(hwnd)});; + final JComboBox combo = new JComboBox<>(new String[]{ + "Item 1", "Item 2" + }); + combo.setSelectedIndex(1); + final Panel p = new Panel(); + p.setLayout(new BorderLayout()); + embedded_frame.add(p, BorderLayout.CENTER); + embedded_frame.validate(); + p.add(combo); + p.validate(); + frame.setVisible(true); + Robot robot = new Robot(); + robot.delay(2000); + Rectangle clos = new Rectangle( + combo.getLocationOnScreen(), combo.getSize()); + robot.mouseMove(clos.x + clos.width / 2, clos.y + clos.height / 2); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.delay(1000); + if (!combo.isPopupVisible()) { + throw new RuntimeException("Combobox popup is not visible!"); + } + robot.mouseMove(clos.x + clos.width / 2, clos.y + clos.height + 3); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.delay(1000); + if (combo.getSelectedIndex() != 0) { + throw new RuntimeException("Combobox selection has not changed!"); + } + embedded_frame.remove(p); + embedded_frame.dispose(); + frame.dispose(); + + } + + public static void main(String args[]) throws Exception { + new EmbeddedFrameGrabTest().init(); + } + +} diff --git a/test/java/awt/Graphics2D/MTGraphicsAccessTest/MTGraphicsAccessTest.java b/test/java/awt/Graphics2D/MTGraphicsAccessTest/MTGraphicsAccessTest.java --- a/test/java/awt/Graphics2D/MTGraphicsAccessTest/MTGraphicsAccessTest.java +++ b/test/java/awt/Graphics2D/MTGraphicsAccessTest/MTGraphicsAccessTest.java @@ -23,7 +23,7 @@ /* @test - @bug 5089429 6982632 + @bug 5089429 6982632 8145808 @summary Checks that we don't crash if rendering operations and state changes are performed on a graphics context from different threads. @@ -34,6 +34,7 @@ import java.awt.*; import java.awt.image.*; import java.awt.geom.*; +import java.util.concurrent.atomic.AtomicInteger; public class MTGraphicsAccessTest { @@ -46,7 +47,7 @@ static long testRunTime; volatile boolean done; - volatile int stillRunning; + AtomicInteger stillRunning = new AtomicInteger(0); volatile int numexceptions; Graphics2D sharedGraphics; @@ -108,7 +109,7 @@ mysleep(testRunTime); done = true; - while (stillRunning > 0) { mysleep(500); } + while (stillRunning.get() > 0) { mysleep(500); } if (numexceptions == 0) { System.err.println("Test passed"); @@ -187,7 +188,7 @@ Runnable testRunnable; public TesterThread(Runnable testRunnable) { - stillRunning++; + stillRunning.incrementAndGet(); this.testRunnable = testRunnable; } @@ -203,7 +204,7 @@ } } } finally { - stillRunning--; + stillRunning.decrementAndGet(); } } } diff --git a/test/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java b/test/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java --- a/test/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java +++ b/test/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 8156121 + * @bug 8156121 8200313 * @summary "Fail forward" fails for GTK3 if no GTK2 available * @modules java.desktop/sun.awt * @requires (os.family == "linux") @@ -31,8 +31,9 @@ import sun.awt.UNIXToolkit; -import java.awt.*; -import java.io.*; +import java.awt.Toolkit; +import java.io.BufferedReader; +import java.io.InputStreamReader; public class GtkVersionTest { public static class LoadGtk { @@ -42,7 +43,7 @@ } public static void main(String[] args) throws Exception { - test(null, "2"); + test(null, "3"); test("2", "2"); test("2.2", "2"); test("3", "3"); diff --git a/test/java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java b/test/java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java --- a/test/java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java +++ b/test/java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java @@ -38,6 +38,7 @@ * @bug 8013468 * @summary Cursor does not update properly when in fullscreen mode on Mac * The core reason of the issue was the lack of a mouse entered event in fullscreen + * @requires (os.family == "mac") * @library ../../regtesthelpers * @build Util * @author Petr Pchelko area=awt.event diff --git a/test/java/awt/SplashScreen/FullscreenAfterSplash/FullScreenAfterSplash.java b/test/java/awt/SplashScreen/FullscreenAfterSplash/FullScreenAfterSplash.java --- a/test/java/awt/SplashScreen/FullscreenAfterSplash/FullScreenAfterSplash.java +++ b/test/java/awt/SplashScreen/FullscreenAfterSplash/FullScreenAfterSplash.java @@ -37,6 +37,7 @@ * @test * @bug 8024185 * @summary Native Mac OS X full screen does not work after showing the splash + * @requires (os.family == "mac") * @library ../ * @build GenerateTestImage * @run main GenerateTestImage diff --git a/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.sh b/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.sh --- a/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.sh +++ b/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2008, 2017, 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 @@ -24,7 +24,7 @@ #!/bin/ksh -p # # @test IOExceptionIfEncodedURLTest.sh -# @bug 6193279 6619458 +# @bug 6193279 6619458 8137087 # @summary REGRESSION: AppletViewer throws IOException when path is encoded URL # @author Dmitry Cherepanov: area=appletviewer # @run compile IOExceptionIfEncodedURLTest.java @@ -54,7 +54,7 @@ #Call this to run the test with a file name test() { - ${TESTJAVA}${FILESEP}bin${FILESEP}appletviewer -Xnosecurity ${URL} > err 2>&1 & + "${TESTJAVA}"${FILESEP}bin${FILESEP}appletviewer -Xnosecurity ${URL} > err 2>&1 & APPLET_ID=$! sleep 15 kill -9 $APPLET_ID @@ -132,7 +132,9 @@ DEFAULT_JDK="/cygdrive/c/Program\ Files/Java/jdk1.8.0" FILESEP="/" PATHSEP=";" - TMP=`cd "${SystemRoot}/Temp"; echo ${PWD}` + TMP=`cd "${SYSTEMROOT}/Temp"; echo ${PWD}` + x="cygpath -m $PWD" + PWD=$(eval $x) ;; AIX ) diff --git a/test/java/awt/dnd/BadSerializaionTest/BadSerializationTest.java b/test/java/awt/dnd/BadSerializaionTest/BadSerializationTest.java deleted file mode 100644 --- a/test/java/awt/dnd/BadSerializaionTest/BadSerializationTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2014, 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 8030050 - * @summary Validate fields on DnD class deserialization - * @author petr.pchelko@oracle.com - */ - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; -import java.util.stream.Stream; - -public class BadSerializationTest { - - private static final String[] badSerialized = new String[] { - "badAction", - "noEvents", - "nullComponent", - "nullDragSource", - "nullOrigin" - }; - - private static final String goodSerialized = "good"; - - public static void main(String[] args) throws Exception { - String testSrc = System.getProperty("test.src") + File.separator; - testReadObject(testSrc + goodSerialized, false); - Stream.of(badSerialized).forEach(file -> testReadObject(testSrc + file, true)); - } - - private static void testReadObject(String filename, boolean expectException) { - Exception exceptionCaught = null; - try (FileInputStream fileInputStream = new FileInputStream(filename); - ObjectInputStream ois = new ObjectInputStream(fileInputStream)) { - ois.readObject(); - } catch (InvalidObjectException e) { - exceptionCaught = e; - } catch (IOException e) { - throw new RuntimeException("FAILED: IOException", e); - } catch (ClassNotFoundException e) { - throw new RuntimeException("FAILED: ClassNotFoundException", e); - } - if (exceptionCaught != null && !expectException) { - throw new RuntimeException("FAILED: UnexpectedException", exceptionCaught); - } - if (exceptionCaught == null && expectException) { - throw new RuntimeException("FAILED: Invalid object was created with no exception"); - } - } -} diff --git a/test/java/awt/dnd/BadSerializaionTest/badAction b/test/java/awt/dnd/BadSerializaionTest/badAction deleted file mode 100644 index d8b58ee48eb957adcfc1eeba826815e9a890be27..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch literal 0 Hc$@ 0 && args[0].equals("-write")) { + writeObjects(); //Creates the binary files for the test. + } else { + String testSrc = System.getProperty("test.src") + File.separator; + testReadObject(testSrc + goodSerialized, false); + Stream.of(badSerialized).forEach( + file -> testReadObject(testSrc + file, true)); + } + } + + private static void testReadObject(String filename, boolean expectException) { + Exception exceptionCaught = null; + try (FileInputStream fileInputStream = new FileInputStream(filename); + ObjectInputStream ois = new ObjectInputStream(fileInputStream)) { + ois.readObject(); + } catch (InvalidObjectException e) { + exceptionCaught = e; + } catch (IOException e) { + throw new RuntimeException("FAILED: IOException", e); + } catch (ClassNotFoundException e) { + throw new RuntimeException("FAILED: ClassNotFoundException", e); + } + if (exceptionCaught != null && !expectException) { + throw new RuntimeException("FAILED: UnexpectedException", exceptionCaught); + } + if (exceptionCaught == null && expectException) { + throw new RuntimeException("FAILED: Invalid object was created with no exception"); + } + } + + /** + * Creates the stubs for the test. It is necessary to disable all checks in + * the constructors of DragGestureEvent/DragGestureRecognizer before run. + */ + private static void writeObjects() throws Exception { + ArrayList evs = new ArrayList<>(); + Point ori = new Point(); + + write(new DragGestureEvent(new NothingNull(), ACTION_COPY, ori, evs), + "noEvents"); + + evs.add(new KeyEvent(new JPanel(), 0, 0, 0, 0, 'a', 0)); + + write(new DragGestureEvent(new NullComponent(), ACTION_COPY, ori, evs), + "nullComponent"); + + write(new DragGestureEvent(new NothingNull(), 100, ori, evs), + "badAction"); + + write(new DragGestureEvent(new NullDragSource(), ACTION_COPY, ori, evs), + "nullDragSource"); + + write(new DragGestureEvent(new NothingNull(), ACTION_COPY, null, evs), + "nullOrigin"); + + write(new DragGestureEvent(new NothingNull(), ACTION_COPY, ori, evs), + "good"); + } + + private static void write(Object obj, String file) throws Exception { + try (FileOutputStream fis = new FileOutputStream(file); + ObjectOutputStream ois = new ObjectOutputStream(fis)) { + ois.writeObject(obj); + } + } + + public static final class NullDragSource extends DragGestureRecognizer { + + public NullDragSource() { + super(null, new JPanel()); + } + + protected void registerListeners() { + } + + protected void unregisterListeners() { + } + } + + public static final class NullComponent extends DragGestureRecognizer { + + public NullComponent() { + super(new DragSource(), null); + } + + protected void registerListeners() { + } + + protected void unregisterListeners() { + } + } + + public static final class NothingNull extends DragGestureRecognizer { + + public NothingNull() { + super(new DragSource(), new JPanel()); + } + + protected void registerListeners() { + } + + protected void unregisterListeners() { + } + } +} diff --git a/test/java/awt/dnd/BadSerializationTest/badAction b/test/java/awt/dnd/BadSerializationTest/badAction new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..217bc7a508a5e0547bf483fc32e030da032dafb4 GIT binary patch literal 3451 zc$}41U2Gdg5FXoc;-pQQv`v4YE# zGs`C*zURfyHYFjw1fxtY3Ldoch*p!%!q8FLo~;v62*0>Z3$O;iirgY0o?{^f#0gP( z9FC#I0=8asTEX>vWzPHgh5cWBciZPx4TrBpZ&14cNoFrYx?&SW6eO2t0&VGl zK{SRoeDcx1MtZ&0A7o{VxwY)RMdDKDk-3rMJx}fo%+MtwZnP$r4)=W zzzA_z&28ZHL%o9|OR$Fcic3py$B_j{R~=H5OR$c~e7vJfRsYNpGjm0g3RZ0!SRX{( z7P#fhLqyc5LXL-IKR`SMn+-LCoUt&M?<^pD$BApYG&F~Xbrggf(^=@l+)DimDV zClSu(X3P(YjaIc8oqZbN4LHg4_^`H@tyWR!T|^aY9V9b#snDcWaDAV!Awv`Q8EQ`U6$}4hez`ki=Q!4zt>LX`2jVfVb0)6P#S`%XX8?mrHj{dPG@u z9h{wAnIfyzRg3EPTr8oXc1W9}gEi5CIus9QiA!omY^XtkGP={3X6G1ESUYwxHjz26 zth{^V$31VqmV)b+;7WZv79ww5S*4=nYD+k}U4Tr5`>riZo&ho1e;E*msH+2N?}K4O zp#wx7U4pIsNMb^i^P$`l44XAQz}itaAn5E^bGe`gsfQ6$1=z;qLaz#xF5!n@woUQW z3?@@z9o6baA~4L|9ceH(9!$8TLFWSxqsWxgHglscZ5fiwlIyfFO?ZM<;~nWHdWbrQ znoKfdV7kR@RqvFFB1{kqZ?;*~tfK)&|AvUGoh9Zl)y8~qk)Y;71&yu=jc#9Mo8=BS zm)!b~yMsjZkVox{@6Mp*3yGgF(WB5zg$0*;Ve+~}!R;(fFT?uP5knIrUh8_8LxfP_ zK$UC8uj{H>;33zm7{Aarot>^m!yGJS4zhH8kCvjD>mjig-l2zKSI)j1*3Pk>>xW{AcQ!vW{?e3>eZT??R*B=) zNx_iKr$tCwvXi+Do|fJcQljh;?1nJcR7I^~#C3sPSVkpgq+QB}{mVb+&YknZ2kpIT zmAx9TuDOYsFQ5JVn&Nf7zRcBM(1ii-s)jadi_j;j z+79}(v3ig`?qdn0c3xrJD!#%2O!frmJ|gQ%-|Oip+S-{LjWdb-UW5Ev1HXd7IXs@% z0;xrAHr`H6O@*G0cN?~lTF1^$Jo?717k)G5XX<#0g}oIL%tC4^(Kg2*UGYYS`BFwR z8O<^uQ*1OI#O{H4DjE$n34#!E4z2tLAB@EVWd(r0)YbF5%`51JVf*SdToMf5ro;Ps z<-Pe+Z&;_3y02Wry9)+{A7;hOQgB0d;sQEFZ7m zxj(slA-OxLaY>t23A-QjTXJWJqz;x!3}n4VFz;tDPny1{0F%;$KMH%v#d}Ce10|a% z8OBSWn~py8f7%O;?>u{lalQk}wY}U7`_NTw$0v7w{p9hLALeu?h^la-X|^EaFvpc)^v1`131lzofEr{4jSRRTt65b~nd(5mnW*zSmiJI=3nZ`X` zO;zskl6<+%1ARVsY}38)#T_{q zDZwanv?qcxj60$giU8L&>@FJtMHEn6>`~{+FyW%4s)(e+HS8bo;337O{t_~d3h6bx zK*QvKX;mO$E|xG&%0=4qXGon&?NRRN@-yQP?rS~%W)>h00U(2B>@uA3jOutnW9IlO z3%LJ_rHLmepIu?>5v`~%| zzOPDXZNkWKuPl~xmH}0$n>2j&zh7^aT78mG)Y}@Nbjo!Y;;5>{Y z(KGWkqp!DBL}_>tMQrmurFp<*8NV8COEGg3ts=#&Jj90E#zPTC;Yl7u8uq339AE9N zAlr1CYr$$hUu?3V!K+ai3W>+uVo_4#EKtR@Z{xwuJ5Zi0IsLyeD(J)yqZz3pfY3MDw?^vG580b=8q++AXtp+^)(Y8`fvOBcJ2&rb<~kv~9$ z(~=XI7DcT;!pajViDrDMen&8|t;3<2JrtWa_Ug~og zSNp6h(7=Z5x!ST@DhpVH*v48cuA(`qTwd}J!p5+xeUqs3+~(_NKm6&dFXZ6xI^1Bg zVu*(E5{L=?EH5|R^>{nv2f7!OQ9-QzG$5IV`!xpml|_T&lPRm+xd z9mZ+ROt3&T$qDO-bu9nPY8Fd8A;z26a5f=pRk6+FSB`Pj|5%T*YYcP(!5~(s(yjJ{N^AD9N4g$Q=Y?h&bwA zojapWBoz)}YDgfFY*iPbEneSJ)q6{G8?b9@#8AZq*QTBq(L*S3q%I8NcMe3Y2#fVP z#?RVjs?%On%oh&x5v99^q?Cy^1Y*Oy+e~fblIe(vU4N&K78k2pVlBX(g^+V;PBpv- z@Ej^oDt*oxUOVK0LNCH3ISw;;|KJ4!BW8flWFeD`k|#sI!4u+Tb<^-&6#A?_Lm_*p zbc!pw7td9%y!`*oOMlGL)wN?N{g5s5+TLGJK06y_A-@8nb>@dnRwA%PybM`K^(r^{ z(=l5tB&s39D;H}`T{ddOt|7azvVlTqW=uLvH!6I6`SRt^KB(`FTl6*l8mOCDc=xyO z-177TR^9D=bq&{huiSI#!Y6Ag2cspE$k#~y6>~9Qt{T^tU_{X;uXNW(n|9Yv@y8;( z0=YY{F>bX;;{>LM0`xPcn%d;`ToP?#%puzz%pW7qZzK0>7+u2SMI%;*UU+6 zix@1B6UM?YhCUP{*}G)Y;^wAz{%-r8OMi)atrfxb`awW_(XrRZi}#+$Zd}R!By0SV zr&bBOANp2;1*W)r#*yB0%B{oLq&s6~OWX0+d*6Tj$;}UzOect72o zRQt_cc2j6r2Z=}>>fhddO5T0`Uq`Z#?Ui)vH1qWRMqrwkl68$L@vr`K@cDnTKjlo6 z2x-(lNq=3C#5UIwCsnzrR26-oJnRPMwS!ZwZ(BK6M;MI@ra=!)UZy z`yit2Ve8B1Du4cX*_MQJqHV2Jt0*SQsvs-ay=u0pS(;kyu7ZU-Y?n1^eWKf}r9{9~Q0PlNCh&nMqEPuJw@1nVEn7`RDt; z|MJmqkd^{=KS~-TOPVU{`fhe!km@~Ds!-5{2KCj6)PXhk+@Ck5U?2~J#8Hg<1sHaC zJ>WjBE7)4l3Ua6*H`ke+F2IP3no2wr4pp$TD}#sR=Hn$49OQyknXh2HE40jUVmcBq zX^aaM^RmXAV);?(sKV*t`*zfycrOVM1ptr;0=&prd=az#lh03y+fIDFKMBb^BqIE_ zjIeo7d`nmLj1Z(%U{Xa-eY^XWugDuINaSHavd5{_-yG1txM_QQ2G!*v+e z58eI3r`wW{UV%|2mj#bnGl*7$&cV=e+M25ok+*N$rFqzZZw2lUi|3fdfOr;_$KV87 zEMVs)r{(=1ROY-NpFjA;H@BXxn9B{eTPf{ypBA7gI342qVN} zRlknY5B3g@t-uBnDlQ$tJx}H#UGYd&uD~WHXW|_ts`_V+nVBmZRIp0R!1@5{8?{SXNhY&X=5a>l~kOlJYvJ5GED!-Wf@#0YQe6Yk7wrkA;JsZelbpM;&w z&6+8Jw+#n8 z2!lh^4;Ad_+q1OXSwXSM234GtJ&L6EtF#mb0T+18J{!PgN_?3+`d>1*c?|WryxE28 zs=k9_=f}83Z2}pB&T(H6h87sCZ$mC&<)0r+I2FQ)asXLDxMMNZeY6Zp& zq;oCDqlY<1&+jr5M+89zNa8JXk2x(2+6F@(V08L%f|IL#*=}<6a_NrAfGDS?owK(q zQ()DaYEu0>A4_PcJ<{TM!K&y$ZN=>@@k!N)4b@3h!t3;<*?EQ())%`Jo3=SGubnye z{atUrnu2Rr;7T1Gi|yO`vO-1C*OqX+b{;Zi9{R2<1_s3T{>y+kM1Ad0cL|0Kg$@yU zdT^L4(*QlD^014^#aw81d3J5pzUJecrFoi0QHdXXuwW#&eG+B77WMc->-ng|4~#5>XrydmlwYB0%+ zf$1i5RjpGh3NS$&jBK;0Sw|!E{`GCHc9xjOR15RLC4!m{Wi+}fG`fA2ZH{}~1iAA+ zv4cbmkVmacV`tC_g~V5w=uv2!$I!$!uXR1lAwsBdpu#od zH+5Ala?AA!`p@1?XQ!*tFb_+ahb-OPqorWxdPuB=_voSZTzfd6eHZWa@W#245||5c zXC|Oj=u@@qemut{DA|9`QS1l|0-277jpiswVEMrU0|N6gm{0f7UBuqr zS`>Jsk~J>7KYy4?Q=E^NF24E4+WD7k?Hua~KNL&6v;FDu7pFq(0~TShLcE|x@`h|7 zEkM$doy=|Ubo3TWiBdqY8^T;u5!JF0*9CTQ6_uEgzEalqFaKP)a3Qb{+I!VHdo^BN za}%?lKXZ29bN5(tM`Lrf)E95ve*WA~M`a2I^E!|(6Z(s~Fkq}|XxnWO-bt#Khj-dq zIZPi5u>?|gMxo!zp~3-7_BiNXB5O*=^>o|Y`Z71z&T8g>L4KowU%}u!9?z?h)FL;T z+fGeQ*_)1c8#YU=6Ms%T^7<_oe>LW3YIur+y%iG7L24?|GRGiYF(Pfgl}W?6_S zwmlxi?tulWJsN5d1i^9+t^5Zc^u_%p1%Ut5*YkIppQ!7G-RskEQ84^99p0B~?=HOc zx^ph6`^pWxyI?>V3W5k?Du$v{Wct-jPi}g4bldq4!cNy~=(?rrP>(ll`FQP)gUQv4 z$vcx8m$Ye>u=_FpMSqq^>S3uwN7kwY^L_^Nr0I+DFe#1u+ioxV7>AV9QL=%O)?fPE xbo)hr(}6X<^Bfp9?YITynqF?&K6G8%@$nsBK5=sGyLsISqAJ{Inr(>i`4`|fF*N`H diff --git a/test/java/awt/dnd/BadSerializationTest/nullComponent b/test/java/awt/dnd/BadSerializationTest/nullComponent new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5de0e3f15a4c18cd5655f201196cfa71f6d87f4c GIT binary patch literal 3451 zc$}41TZ~)98UAgrcfFhJW;e;^0!g?wR8-iY<)UaKi1!9g9K4D{AiJ&9@i}9A$nlxO z%pCg|i3mg_L}-dsi3bV@A#v&Lr7!I>D$q*gi3gC7AnHpVR&9{_lvJwdKQqV2b~Zuc zX!rQc%s>D9^Znm{`P084D+TO-mb6KpbX4B;-TaaujmN1}p`goc>Z`MvBOC6;tM_JL zqy(eHQH=X#7^2VG>?OE!m@`dpy_q1O4T^b+?03a0vc#)~(B4+zvJ~=NQ zJo}G>X-JnK72$u^2%87Rcl1>kg&^HBlPY@Yi~Vo@oxGEQR0&2Td!Cvt>CT9LkR(C%WBh?4!{E-k?p{3>&Y zSUjgJ2E?U1)8kXxUbb09X>bu$Z1s@L)Tcs|TES0- zgbg7I#?R#eG2AvD@E{D1Q$JL&XK2sS)!qt<&9o-exOa??bP3@f9`!Z$LXsQm?@1;aSL+z0+#|t(@4{9rJXNgZ5Mr^D_qAFfzD9tW0 zq_Do&_1MJbys`1&>8}pI|Jw}Qy#}}H=vaww>&rS76<=Gz@!BQG)p+Q;vJw~&gV`rU5}`$A-@ZJwXHXm@2_OCRYYk zpmYU41an=Ar{*x366cIoHxYwjVt1m&{A4iWlNMc$0`wwNUf0Y``m|$6E-Sv*#WWEJ zT2FRl+jv9NIo4*983VH&=Bj3|RFq+cI2hSxQL~Ol=>2d!F7U~4>dHp zAvC%}m2HuG+yuGv1F?fd43J0N>tkos35CQ@m>E!Lrfk9GflXdFD7d|)`E}U7*<)y8 z%xhf_3y2UZ9I127_-%bvE8KFuj{dWE)7j|`G|a0Fj~@qe3Q^$(S-qH zRYM!MMR+Hvx*pzXXZ-|yF2oW@-J(Lj)k1{>m>qD?6GS$Zj_di@+xjv;wVhk>h(Ug< zfnUMs5+2VRk<=nTGq;_ao3l5a?l)|fT4%4${POMlul>uIpKIbN4)#_^FbAorMAsaH zbj66Y`BKI+InA;VQ*1mQ#qNOxDjtos34&lbhgN=%5BlP%ssg}Y>g)MK<`wnbuzzzJ zt_X&2)8T!#@zL^oZ#x&$y06^A`wIqyu^@;bp<*a{MP^vt{Oq<@CwE=`L)hzj4PAHi z9qRFpEgx?^d@Q|wEqy4hamkui3A-QjTk#i&q#l+^bY!zZFz@FuPny1{1hdk(KX!Y? z$2g>z30fdX~!)ncMWpW_Mw~Fjz2&A*$d}3zFg9sAgaQR zrrCzba$w>{%_T|Ncr7yhD$q*gi3gC7AnHpVR&9{_lvJwdKQqV2b~Zuc zX!rQc%s>D9^Znm{`P084D+TO-mb6KpbX4B;-TaaujmN1}p`goc>Z`MvBOC6;tM_JL zqy(eHQH=X#7^2VG>?OE!m@`dpy_q1O4T^b+?03a0vc#)~(B4+zvJ~=NQ zJo}G>X-JnK72$u^2%87Rcl1>kg&^HBlPY@Yi~Vo@oxGEQR0&2Td!Cvt>CT9LkR(C%WBh?4!{E-k?p{3>&Y zSUjgJ2E?U1)8kXxUbb09X>bu$Z1s@L)Tcs|TES0- zgbg7I#?R#eG2AvD@E{D1Q$JL&XK2sS)!qt<&9o-exOa??bP3@f9`!Z$LXsQm?@1;aSL+z0+#|t(@4{9rJXNgZ5Mr^D_qAFfzD9tW0 zq_Do&_1MJbys`1&>8}pI|Jw}Qy#}}H=vaww>&rS76<=Gz@!BQG)p+Q;vJw~&gV`rU5}`$A-@ZJwXHXm@2_OCRYYk zpmYU41an=Ar{*x366cIoHxYwjVt1m&{A4iWlNMc$0`wwNUf0Y``m|$6E-Sv*#WWEJ zT2FRl+jv9NIo4*983VH&=Bj3|RFq+cI2hSxQL~Ol=>2d!F7U~4>dHp zAvC%}m2HuG+yuGv1F?fd43J0N>tkos35CQ@m>E!Lrfk9GflXdFD7d|)`E}U7*<)y8 z%xhf_3y2UZ9I127_-%bvE8KFuj{dWE)7j|`G|a0Fj~@qe3Q^$(S-qH zRYM!MMR+Hvx*pzXXZ-|yF2oW@-J(Lj)k1{>m>qD?6GS$Zj_di@+xjv;wVhk>h(Ug< zfnUMs5+2VRk<=nTGq;_ao3l5a?l)|fT4%4${POMlul>uIpKIbN4)#_^FbAorMAsaH zbj66Y`BKI+InA;VQ*1mQ#qNOxDjtos34&lbhgN=%5BlP%ssg}Y>g)MK<`wnbuzzzJ zt_X&2)8T!#@zL^oZ#x&$y06^A`wIqyu^@;bp<*a{MP^vt{Oq<@CwE=`L)hzj4PAHi z9qRFpEgx?^d@Q|wEqy4hamkui3A-QjTk#i&q#l+^bY!zZFz@FuPny1{1hdk(KX!Y? z$2g>z30fdX~!)ncMWpW_Mw~Fjz2&A*$d}3zFg9sAgaQR zrrCzba$w>{%_T|Ncr7yh%RA@xumLP)&f!ijUm>p)K&Ktck|Sj)TsgtIVh>b17TAITe>`WNq(-gg^c}NuqyKujCPq8ITEHq z0pmuwKrwg1s8cLINo`d)HTdx6`qLk#0YV=DQoiq_CD(PCr-dM`0+T9y_PcFozaejB zAZ0gOBNkX?ddCKm+{ThnNNgU-Uh zaoU=#5n)AN+@Th%!LI_hN#voC$SUGSc0L6sA%*sAx$HK}^8;n>`{|VfUwym#TqO-@ z3kK`lVHHM&+z)-t8uh~7I7LT0&Nj#W`rl`YAN@G5T_Rwt!#n-RVY7eXlRJOi{L4#U zq#?5eIh%Vjs8h#+G;@|ATXu*d3ew9nq1IIU2Ed2JGadf}I&Hm{A5O?7^Qsg37l}vR z$LEHgA3Zy>Gh-Ckm|*CrI{Ama>qhte(-|0DfFa_ts#izyqrHn`OR$Cnic4E?*OeAz zD=w+ZC0NJgbmv5gswCx@pm0^t&gDJ7PuYA!$ef6Lexg^JxF{7n+({(ywNZ} z-QGYvjuOwt1mMC5G0Yni%x${HZkY>*3I#VLI3j9(#{3}La7C-pKBqlAhD4^%_U#6_Lpcl;K{05Slb<(?u8HQqb$ zjQnTA+FLV_v*1R%O)jAi5F00`Glv*Ok4TKv5{wv^&bDlq9^xD$zts>93xWuc#9ibr zvs;+74Tdqm?DRS%OD-qs*ZA_)3K)||` z6OLwEkSp`Rb7avsPK?iA#fbyd(*bq%!=QoCK_ZVY!Iq>au^`I%h;Io7&7NLhH>epW z=;~PYxS)rqj}cQAY-MtxR|Ikw@k21jp?GT!iz%^>YjH!dGfeId)tT2>jCrI^=R+T( z$dubMv|*1n4ajBDb6Z#@d_gOn6WIn@h%yHnOfsWjw#gh-v#{{uf2#mv#Kz1vn;LaA z#OU7|W3|1-T&7xB4=!WWcqpUNRiV9`=vA}aLzdB;5VvK9u5A*0D6xdhc8u9D8q850B^$Nx>vQ1Z~?WmZG zt;|J~uJ4gjFti>JYv!$b8AUE$_UYJlPP%AuzN7@!0z8@XDHZxw&ASutF$GE{?>UM+ z-gqF_j1lQYrJ-ee_sxQ*STwT~e7aAvZeOLZ_E%Tk)XbMJoZIp8zDV8Sj=Gxb zt9S0caQ^3`G6VgVPUNek{(^1{n5){g@mPd5N!4=ErVW)t^r-+_Aa$k{#;qJET)=ow zfF2^UrgUCU#nINr?22Zw>AlADYmNIA^v~h-yc$Z)a+|Ssa&j`VbhJCLMbJ9=*Vq$p z-gW6WqkgW2x7avaA;4^erV=f44Z;;OGOCv{rsOor0xYrdx*w+p=Bs!$&>-l92y>|A zzxZG*j+7Jt{!&lV?=`Qm8-{JG%WzRJe47dH>y;1Y-+9wMpVo8b8s6P7P8jh05IRr{ zM7zl(#Z8T`dvSQw91Gnk)&$h$&8U66anFJD@}=~BY3-M+8I^GQF~3D`hDhpS ztHeOoss!tP4(p_ui!2zICj4>Oiyr17C3WO%AZHXWeQ!4Y(EnLKQojA{9gGHSemhA_fF?n=WYX@3}&k!#O$ee6!Hr2g2gUz7TE dcN|aseSab-nzF|?*FA8JZqR2QOc)l1{{hA8L7D&n diff --git a/test/java/net/SocketOption/TcpKeepAliveTest.java b/test/java/net/SocketOption/TcpKeepAliveTest.java new file mode 100644 --- /dev/null +++ b/test/java/net/SocketOption/TcpKeepAliveTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 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 8194298 + * @summary Add support for per Socket configuration of TCP keepalive + * @run main TcpKeepAliveTest + */ +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.MulticastSocket; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketOption; +import java.util.Set; +import jdk.net.ExtendedSocketOptions; +import jdk.net.Sockets; + +public class TcpKeepAliveTest { + + private static final String LOCAL_HOST = "127.0.0.1"; + private static final int DEFAULT_KEEP_ALIVE_PROBES = 7; + private static final int DEFAULT_KEEP_ALIVE_TIME = 1973; + private static final int DEFAULT_KEEP_ALIVE_INTVL = 53; + + public static void main(String args[]) throws IOException { + + try (ServerSocket ss = new ServerSocket(0); + Socket s = new Socket(LOCAL_HOST, ss.getLocalPort()); + DatagramSocket ds = new DatagramSocket(0); + MulticastSocket mc = new MulticastSocket(0)) { + Set> supportedOpts = Sockets.supportedOptions(ss.getClass()); + Set> supportedOptsClient = Sockets.supportedOptions(s.getClass()); + Set> supportedOptsDG = Sockets.supportedOptions(ds.getClass()); + Set> supportedOptsMC = Sockets.supportedOptions(mc.getClass()); + if (supportedOpts.contains(ExtendedSocketOptions.TCP_KEEPIDLE)) { + Sockets.setOption(ss, ExtendedSocketOptions.TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME); + if (Sockets.getOption(ss, ExtendedSocketOptions.TCP_KEEPIDLE) != DEFAULT_KEEP_ALIVE_TIME) { + throw new RuntimeException("Test failed, TCP_KEEPIDLE should have been " + DEFAULT_KEEP_ALIVE_TIME); + } + } + if (supportedOpts.contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) { + Sockets.setOption(ss, ExtendedSocketOptions.TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES); + if (Sockets.getOption(ss, ExtendedSocketOptions.TCP_KEEPCOUNT) != DEFAULT_KEEP_ALIVE_PROBES) { + throw new RuntimeException("Test failed, TCP_KEEPCOUNT should have been " + DEFAULT_KEEP_ALIVE_PROBES); + } + } + if (supportedOpts.contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) { + Sockets.setOption(ss, ExtendedSocketOptions.TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL); + if (Sockets.getOption(ss, ExtendedSocketOptions.TCP_KEEPINTERVAL) != DEFAULT_KEEP_ALIVE_INTVL) { + throw new RuntimeException("Test failed, TCP_KEEPINTERVAL should have been " + DEFAULT_KEEP_ALIVE_INTVL); + } + } + if (supportedOptsClient.contains(ExtendedSocketOptions.TCP_KEEPIDLE)) { + Sockets.setOption(s, ExtendedSocketOptions.TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME); + if (Sockets.getOption(s, ExtendedSocketOptions.TCP_KEEPIDLE) != DEFAULT_KEEP_ALIVE_TIME) { + throw new RuntimeException("Test failed, TCP_KEEPIDLE should have been " + DEFAULT_KEEP_ALIVE_TIME); + } + } + if (supportedOptsClient.contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) { + Sockets.setOption(s, ExtendedSocketOptions.TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES); + if (Sockets.getOption(s, ExtendedSocketOptions.TCP_KEEPCOUNT) != DEFAULT_KEEP_ALIVE_PROBES) { + throw new RuntimeException("Test failed, TCP_KEEPCOUNT should have been " + DEFAULT_KEEP_ALIVE_PROBES); + } + } + if (supportedOptsClient.contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) { + Sockets.setOption(s, ExtendedSocketOptions.TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL); + if (Sockets.getOption(s, ExtendedSocketOptions.TCP_KEEPINTERVAL) != DEFAULT_KEEP_ALIVE_INTVL) { + throw new RuntimeException("Test failed, TCP_KEEPINTERVAL should have been " + DEFAULT_KEEP_ALIVE_INTVL); + } + } + if (supportedOptsDG.contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) { + throw new RuntimeException("Test failed, TCP_KEEPCOUNT is applicable" + + " for TCP Sockets only."); + } + if (supportedOptsDG.contains(ExtendedSocketOptions.TCP_KEEPIDLE)) { + throw new RuntimeException("Test failed, TCP_KEEPIDLE is applicable" + + " for TCP Sockets only."); + } + if (supportedOptsDG.contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) { + throw new RuntimeException("Test failed, TCP_KEEPINTERVAL is applicable" + + " for TCP Sockets only."); + } + if (supportedOptsMC.contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) { + throw new RuntimeException("Test failed, TCP_KEEPCOUNT is applicable" + + " for TCP Sockets only"); + } + if (supportedOptsMC.contains(ExtendedSocketOptions.TCP_KEEPIDLE)) { + throw new RuntimeException("Test failed, TCP_KEEPIDLE is applicable" + + " for TCP Sockets only"); + } + if (supportedOptsMC.contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) { + throw new RuntimeException("Test failed, TCP_KEEPINTERVAL is applicable" + + " for TCP Sockets only"); + } + } + } +} diff --git a/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java b/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java --- a/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java +++ b/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -31,10 +31,15 @@ import java.net.*; import static java.net.StandardSocketOptions.*; import java.io.IOException; +import java.util.Arrays; +import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPCOUNT; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE; +import static jdk.net.ExtendedSocketOptions.TCP_KEEPINTERVAL; public class Basic { @@ -156,6 +161,16 @@ checkOption(ch, SO_REUSEADDR, true); ch.setOption(SO_REUSEADDR, false); checkOption(ch, SO_REUSEADDR, false); + List> extOptions = Arrays.asList(TCP_KEEPCOUNT, + TCP_KEEPIDLE, TCP_KEEPINTERVAL); + if (options.containsAll(extOptions)) { + ch.setOption(TCP_KEEPIDLE, 1234); + checkOption(ch, TCP_KEEPIDLE, 1234); + ch.setOption(TCP_KEEPINTERVAL, 123); + checkOption(ch, TCP_KEEPINTERVAL, 123); + ch.setOption(TCP_KEEPCOUNT, 7); + checkOption(ch, TCP_KEEPCOUNT, 7); + } } finally { ch.close(); } diff --git a/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/test/java/nio/channels/AsynchronousSocketChannel/Basic.java --- a/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -29,13 +29,17 @@ import java.nio.ByteBuffer; import java.nio.channels.*; -import static java.net.StandardSocketOptions.*; import java.net.*; +import java.util.Arrays; import java.util.Random; +import java.util.Set; +import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.io.Closeable; import java.io.IOException; +import static java.net.StandardSocketOptions.*; +import static jdk.net.ExtendedSocketOptions.*; public class Basic { static final Random rand = new Random(); @@ -164,6 +168,25 @@ // read others (can't check as actual value is implementation dependent) ch.getOption(SO_RCVBUF); ch.getOption(SO_SNDBUF); + Set> options = ch.supportedOptions(); + List> extOptions = Arrays.asList(TCP_KEEPCOUNT, + TCP_KEEPIDLE, TCP_KEEPINTERVAL); + if (options.containsAll(extOptions)) { + ch.setOption(TCP_KEEPIDLE, 1234); + checkOption(ch, TCP_KEEPIDLE, 1234); + ch.setOption(TCP_KEEPINTERVAL, 123); + checkOption(ch, TCP_KEEPINTERVAL, 123); + ch.setOption(TCP_KEEPCOUNT, 7); + checkOption(ch, TCP_KEEPCOUNT, 7); + } + } + } + + static void checkOption(AsynchronousSocketChannel sc, SocketOption name, Object expectedValue) + throws IOException { + Object value = sc.getOption(name); + if (!value.equals(expectedValue)) { + throw new RuntimeException("value not as expected"); } } diff --git a/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java --- a/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -33,9 +33,14 @@ import java.io.IOException; import java.util.*; import static java.net.StandardSocketOptions.*; +import static jdk.net.ExtendedSocketOptions.*; public class SocketOptionTests { + private static final int DEFAULT_KEEP_ALIVE_PROBES = 7; + private static final int DEFAULT_KEEP_ALIVE_TIME = 1973; + private static final int DEFAULT_KEEP_ALIVE_INTVL = 53; + static void checkOption(ServerSocketChannel ssc, SocketOption name, Object expectedValue) throws IOException { @@ -76,6 +81,17 @@ throw new RuntimeException("NullPointerException not thrown"); } catch (NullPointerException x) { } + List> keepAliveOpts = Arrays.asList(TCP_KEEPCOUNT, TCP_KEEPIDLE, + TCP_KEEPINTERVAL); + if (ssc.supportedOptions().containsAll(keepAliveOpts)) { + ssc.setOption(TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES); + checkOption(ssc, TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES); + ssc.setOption(TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME); + checkOption(ssc, TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME); + ssc.setOption(TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL); + checkOption(ssc, TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL); + + } // ClosedChannelException ssc.close(); diff --git a/test/java/nio/channels/SocketChannel/SocketOptionTests.java b/test/java/nio/channels/SocketChannel/SocketOptionTests.java --- a/test/java/nio/channels/SocketChannel/SocketOptionTests.java +++ b/test/java/nio/channels/SocketChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -32,7 +32,9 @@ import java.net.*; import java.io.IOException; import java.util.*; +import sun.net.ExtendedOptionsHelper; import static java.net.StandardSocketOptions.*; +import static jdk.net.ExtendedSocketOptions.*; public class SocketOptionTests { @@ -49,8 +51,20 @@ // check supported options Set> options = sc.supportedOptions(); - List expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, - SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, TCP_NODELAY); + + List> extOptions = Arrays.asList(TCP_KEEPCOUNT, TCP_KEEPIDLE, + TCP_KEEPINTERVAL); + List expected; + boolean keepAliveOptsupported; + if (keepAliveOptsupported=ExtendedOptionsHelper.keepAliveOptions() + .containsAll(extOptions)) { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE, + SO_REUSEADDR, SO_LINGER, TCP_NODELAY, TCP_KEEPCOUNT, + TCP_KEEPIDLE, TCP_KEEPINTERVAL); + } else { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE, + SO_REUSEADDR, SO_LINGER, TCP_NODELAY); + } for (SocketOption opt: expected) { if (!options.contains(opt)) throw new RuntimeException(opt.name() + " should be supported"); @@ -114,7 +128,14 @@ throw new RuntimeException("expected linger to be disabled"); sc.setOption(TCP_NODELAY, true); // can't check sc.setOption(TCP_NODELAY, false); // can't check - + if (keepAliveOptsupported) { + sc.setOption(TCP_KEEPIDLE, 1234); + checkOption(sc, TCP_KEEPIDLE, 1234); + sc.setOption(TCP_KEEPINTERVAL, 123); + checkOption(sc, TCP_KEEPINTERVAL, 123); + sc.setOption(TCP_KEEPCOUNT, 7); + checkOption(sc, TCP_KEEPCOUNT, 7); + } // NullPointerException try { sc.setOption(null, "value"); diff --git a/test/java/util/Scanner/ScanTest.java b/test/java/util/Scanner/ScanTest.java new file mode 100644 --- /dev/null +++ b/test/java/util/Scanner/ScanTest.java @@ -0,0 +1,1502 @@ +/* + * Copyright (c) 2003, 2015, 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 4313885 4926319 4927634 5032610 5032622 5049968 5059533 6223711 6277261 6269946 6288823 + * @summary Basic tests of java.util.Scanner methods + * @key randomness + * @run main/othervm ScanTest + */ + +import java.util.*; +import java.text.*; +import java.io.*; +import java.nio.*; +import java.util.regex.*; +import java.math.*; + +public class ScanTest { + + private static boolean failure = false; + private static int failCount = 0; + private static int NUM_SOURCE_TYPES = 2; + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + String lang = reservedLocale.getLanguage(); + try { + if (!"en".equals(lang) && + !"zh".equals(lang) && + !"ko".equals(lang) && + !"ja".equals(lang)) { + //Before we have resource to improve the test to be ready for + //arbitrary locale, force the default locale to be "English" + //for now. + Locale.setDefault(Locale.ENGLISH); + } + skipTest(); + findInLineTest(); + findWithinHorizonTest(); + findInEmptyLineTest(); + removeTest(); + fromFileTest(); + ioExceptionTest(); + matchTest(); + delimiterTest(); + useLocaleTest(); + closeTest(); + cacheTest(); + cacheTest2(); + nonASCIITest(); + resetTest(); + + for (int j=0; j\n]+"); + sc.next(); + String textOfRef = sc.next(); + if (!textOfRef.equals(expected[i])) + failCount++; + } + // Read some html tags using < and > as delimiters + if (!sc.next().equals("/a")) + failCount++; + if (!sc.next().equals("b")) + failCount++; + + // Scan some html tags using skip and next + Pattern nonTagStart = Pattern.compile("[^<]+"); + Pattern tag = Pattern.compile("<[^>]+?>"); + Pattern spotAfterTag = Pattern.compile("(?<=>)"); + String[] expected2 = { "", "

", "

    ", "
  • " }; + sc.useDelimiter(spotAfterTag); + int tagsFound = 0; + while(tagsFound < 4) { + if (!sc.hasNext(tag)) { + // skip text between tags + sc.skip(nonTagStart); + } + String tagContents = sc.next(tag); + if (!tagContents.equals(expected2[tagsFound])) + failCount++; + tagsFound++; + } + + report("Use case 4"); + } + + public static void useCase5() throws Exception { + File f = new File(System.getProperty("test.src", "."), "input.txt"); + Scanner sc = new Scanner(f); + String testDataTag = sc.findWithinHorizon("usage case 5\n", 0); + if (!testDataTag.equals("usage case 5\n")) + failCount++; + + sc.findWithinHorizon("Share Definitions", 0); + sc.nextLine(); + sc.next("\\[([a-z]+)\\]"); + String shareName = sc.match().group(1); + if (!shareName.equals("homes")) + failCount++; + + String[] keys = { "comment", "browseable", "writable", "valid users" }; + String[] vals = { "Home Directories", "no", "yes", "%S" }; + for (int i=0; i<4; i++) { + sc.useDelimiter("="); + String key = sc.next().trim(); + if (!key.equals(keys[i])) + failCount++; + sc.skip("[ =]+"); + sc.useDelimiter("\n"); + String value = sc.next(); + if (!value.equals(vals[i])) + failCount++; + sc.nextLine(); + } + + report("Use case 5"); + } + + public static void nonASCIITest() throws Exception { + String yourBasicTibetanNumberZero = "\u0f20"; + String yourBasicTibetanFloatingNumber = "\u0f23.\u0f27"; + String weirdMixtureOfTibetanAndASCII = "\u0f23.7"; + String weirdMixtureOfASCIIAndTibetan = "3.\u0f27"; + Scanner sc = new Scanner(yourBasicTibetanNumberZero); + int i = sc.nextInt(); + if (i != 0) + failCount++; + sc = new Scanner(yourBasicTibetanFloatingNumber); + float f = sc.nextFloat(); + if (f != Float.parseFloat("3.7")) + failCount++; + sc = new Scanner(weirdMixtureOfTibetanAndASCII); + f = sc.nextFloat(); + if (f != Float.parseFloat("3.7")) + failCount++; + sc = new Scanner(weirdMixtureOfASCIIAndTibetan); + f = sc.nextFloat(); + if (f != Float.parseFloat("3.7")) + failCount++; + report("Scanning non ASCII digits"); + } + + public static void findWithinHorizonTest() throws Exception { + // Test with a string source + Scanner sc = new Scanner("dog cat cat dog cat"); + try { + sc.findWithinHorizon("dog", -1); + failCount++; + } catch (IllegalArgumentException iae) { + // Correct result + } + if (sc.findWithinHorizon("dog", 2) != null) + failCount++; + if (!sc.findWithinHorizon("dog", 3).equals("dog")) + failCount++; + if (sc.findWithinHorizon("cat", 4) != null) + failCount++; + if (!sc.findWithinHorizon("cat", 5).equals("cat")) + failCount++; + if (sc.findWithinHorizon("cat", 7) != null) + failCount++; + if (sc.findWithinHorizon("dog", 7) != null) + failCount++; + if (!sc.findWithinHorizon("cat", 0).equals("cat")) + failCount++; + if (!sc.findWithinHorizon("dog", 0).equals("dog")) + failCount++; + if (!sc.findWithinHorizon("cat", 0).equals("cat")) + failCount++; + + // Test with a stream source + StutteringInputStream stutter = new StutteringInputStream(); + for (int index=0; index 0)) + failCount++; + stutter.reset(); + } + + // We must loop to let StutteringInputStream do its magic + for (int j=0; j<10; j++) { + // An anchor at the end of stream should work + stutter.reset(); + sc = new Scanner(stutter); + String result = sc.findWithinHorizon("phant$", 0); + if (!result.equals("phant")) + failCount++; + stutter.reset(); + sc = new Scanner(stutter); + result = sc.findWithinHorizon("phant$", 54); + if (!result.equals("phant")) + failCount++; + // An anchor at the end of horizon should not + stutter.reset(); + sc = new Scanner(stutter); + result = sc.findWithinHorizon("brummer$", 7); + if (result != null) + failCount++; + // An anchor at start should work + stutter.reset(); + sc = new Scanner(stutter); + result = sc.findWithinHorizon("^brummer", 0); + if (!result.equals("brummer")) + failCount++; + } + + report("Find to horizon test"); + } + + // StutteringInputStream returns 1 to 3 characters at a time + static class StutteringInputStream implements Readable { + StutteringInputStream() { + text = "brummer hisser tort zardzard rantrant caimagator phant"; + datalen = 54; + } + StutteringInputStream(String text) { + this.text = text; + datalen = text.length(); + } + Random generator = new Random(); + String text; + int datalen; + int index = 0; + public int length() { + return datalen; + } + public void reset() { + index = 0; + } + public String wordInIndex(int index) { + if (index < 7) return null; + if (index < 14) return "brummer"; + if (index < 19) return "hisser"; + if (index < 28) return "tort"; + if (index < 37) return "zardzard"; + if (index < 48) return "rantrant"; + return "caimagator"; + } + public String wordBeyondIndex(int index) { + if (index < 7) return "brummer"; + if (index < 14) return "hisser"; + if (index < 19) return "tort"; + if (index < 28) return "zardzard"; + if (index < 37) return "rantrant"; + if (index < 48) return "caimagator"; + return "phantphant"; + } + public int read(java.nio.CharBuffer target) throws IOException { + if (index > datalen-1) + return -1; // EOS + int len = target.remaining(); + if (len > 4) // return 1 to 3 characters + len = generator.nextInt(3) + 1; + while ((index + len) > datalen) + len--; + for (int i=0; i(radix) method caches a matched integer type + * with specified radix for the next next(radix) invoke. + * The cache value should not be used if the next(radix) + * has different radix value with the last hasNext(radix). + */ + public static void cacheTest2() throws Exception { + // Test clearing of the type cache + Scanner scanner = new Scanner("10"); + scanner.hasNextByte(16); + if (scanner.nextByte(10) != 10) { + System.out.println("wrong radix cache is used"); + failCount++; + } + scanner = new Scanner("10"); + scanner.hasNextShort(16); + if (scanner.nextShort(10) != 10) { + System.out.println("wrong radix cache is used"); + failCount++; + } + scanner = new Scanner("10"); + scanner.hasNextInt(16); + if (scanner.nextInt(10) != 10) { + System.out.println("wrong radix cache is used"); + failCount++; + } + scanner = new Scanner("10"); + scanner.hasNextLong(16); + if (scanner.nextLong(10) != 10) { + System.out.println("wrong radix cache is used"); + failCount++; + } + scanner = new Scanner("10"); + scanner.hasNextBigInteger(16); + if (scanner.nextBigInteger(10).intValue() != 10) { + System.out.println("wrong radix cache is used"); + failCount++; + } + report("Cache test2"); + } + + + public static void closeTest() throws Exception { + Scanner sc = new Scanner("testing"); + sc.close(); + sc.ioException(); + sc.delimiter(); + sc.useDelimiter("blah"); + sc.useDelimiter(Pattern.compile("blah")); + for (int i=0; i results = new ArrayList(); + while(s.hasNext()) + results.add(s.next()); + System.out.println(results); + } + + private static void example2() throws Exception { + Scanner s = new Scanner("1 fish 2 fish red fish blue fish"); + s.useDelimiter("\\s*fish\\s*"); + System.out.println(s.nextInt()); + System.out.println(s.nextInt()); + System.out.println(s.next()); + System.out.println(s.next()); + } + + private static void example3() throws Exception { + Scanner s = new Scanner("1 fish 2 fish red fish blue fish"); + s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)"); + for (int i=1; i<=s.match().groupCount(); i++) + System.out.println(s.match().group(i)); + } + + private static void findInLineTest() throws Exception { + Scanner s = new Scanner("abc def ghi jkl mno"); + Pattern letters = Pattern.compile("[a-z]+"); + Pattern frogs = Pattern.compile("frogs"); + String str = s.findInLine(letters); + if (!str.equals("abc")) + failCount++; + if (!s.hasNext(letters)) + failCount++; + try { + str = s.findInLine(frogs); + } catch (NoSuchElementException nsee) { + // Correct + } + if (!s.hasNext()) + failCount++; + if (!s.hasNext(letters)) + failCount++; + str = s.findInLine(letters); + if (!str.equals("def")) + failCount++; + + report("Find patterns"); + } + + private static void findInEmptyLineTest() throws Exception { + String eol = System.getProperty("line.separator"); + Scanner s = new Scanner("line 1" + eol + "" + eol + "line 3" + eol); + int lineNo = 0; + while (s.hasNextLine()) { + lineNo++; + s.findInLine("3"); + s.nextLine(); + } + if (lineNo != 3) + failCount++; + report("findInEmptyLine test"); + } + + private static void matchTest() throws Exception { + Scanner s = new Scanner("1 fish 2 fish red fish blue fish"); + s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)"); + + MatchResult result = s.match(); + if (!result.group(1).equals("1")) + failCount++; + if (!result.group(2).equals("2")) + failCount++; + if (!result.group(3).equals("red")) + failCount++; + if (!result.group(4).equals("blue")) + failCount++; + + report("Match patterns"); + } + + private static void skipTest() throws Exception { + Scanner s = new Scanner("abc def ghi jkl mno"); + Pattern letters = Pattern.compile("[a-z]+"); + Pattern spaceLetters = Pattern.compile(" [a-z]+"); + Pattern frogs = Pattern.compile("frogs"); + try { + s.skip(letters); + } catch (NoSuchElementException ime) { + failCount++; + } + String token = s.next(letters); + if (!token.equals("def")) { + System.out.println("expected def"); + System.out.println("I found "+token); + failCount++; + } + try { + s.skip(letters); + failCount++; + } catch (NoSuchElementException ime) { + // Correct result + } + token = s.next(letters); + if (!token.equals("ghi")) { + System.out.println("expected ghi"); + System.out.println("I found "+token); + failCount++; + } + try { + s.skip(letters); + failCount++; + } catch (NoSuchElementException ime) { + // Correct result because skip ignores delims + } + try { + s.skip(spaceLetters); + } catch (NoSuchElementException ime) { + failCount++; + } + token = s.next(letters); + if (!token.equals("mno")) { + System.out.println("expected mno"); + System.out.println("I found "+token); + failCount++; + } + try { + s.skip(letters); + failCount++; + } catch (NoSuchElementException ime) { + // Correct result + } + report("Skip patterns"); + } + + private static void byteTest(int sourceType) throws Exception { + String input = " 3 0 00 b -B 012 44 -55 12 127 129 -131 dog 0x12"; + Scanner s = scannerFor(input, sourceType); + if (!s.hasNextByte()) failCount++; + if (s.nextByte() != (byte)3) failCount++; + if (!s.hasNextByte()) failCount++; + if (s.nextByte() != (byte)0) failCount++; + if (!s.hasNextByte()) failCount++; + if (s.nextByte() != (byte)0) failCount++; + if (!s.hasNextByte(16)) failCount++; + if (s.nextByte(16) != (byte)11)failCount++; + if (!s.hasNextByte(16)) failCount++; + if (s.nextByte(16) != (byte)-11) failCount++; + if (!s.hasNextByte()) failCount++; + if (s.nextByte() != (byte)12) failCount++; + if (!s.hasNextByte()) failCount++; + if (s.nextByte() != (byte)44) failCount++; + if (!s.hasNextByte()) failCount++; + if (s.nextByte() != (byte)-55) failCount++; + if (!s.hasNextByte()) failCount++; + if (s.nextByte() != (byte)12) failCount++; + if (!s.hasNextByte()) failCount++; + if (s.nextByte() != (byte)127) failCount++; + if (s.hasNextByte()) failCount++; + + try { + s.nextByte(); + failCount++; + } catch (InputMismatchException ime) { + // Correct result + } + if (s.hasNextByte()) failCount++; + if (s.nextInt() != 129) failCount++; + if (s.hasNextByte()) failCount++; + try { + s.nextByte(); + failCount++; + } catch (InputMismatchException ime) { + // Correct result + } + if (s.nextInt() != -131) failCount++; + if (s.hasNextByte()) failCount++; + try { + s.nextByte(); + failCount++; + } catch (InputMismatchException ime) { + // Correct result + } + s.next(Pattern.compile("\\w+")); + if (s.hasNextByte()) + failCount++; + try { + s.nextByte(); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + s.next(); + if (s.hasNextByte()) + failCount++; + try { + byte bb = s.nextByte(); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + report("Scan bytes"); + } + + private static void shortTest(int sourceType) throws Exception { + String input = " 017 22 00E -34 44,333 -53999 0x19 dog"; + Scanner s = scannerFor(input, sourceType); + if (!s.hasNextShort()) failCount++; + if (s.nextShort() != (short)17) failCount++; + if (!s.hasNextShort()) failCount++; + if (s.nextShort() != (short)22) failCount++; + if (!s.hasNextShort(16)) failCount++; + if (s.nextShort(16) != (short)14) failCount++; + if (!s.hasNextShort()) failCount++; + if (s.nextShort() != (short)-34) failCount++; + for (int i=0; i<4; i++) { + if (s.hasNextShort()) + failCount++; + try { + s.nextShort(); + failCount++; + } catch (InputMismatchException ime) { + // Correct result + } + s.next(); + } + try { + s.next(); + failCount++; + } catch (InputMismatchException ime) { + failCount++; + } catch (NoSuchElementException nse) { + // Correct result + } + report("Scan shorts"); + } + + private static void intTest(int sourceType) throws Exception { + Scanner s = scannerFor( + "22 022 C -34 0x80000000 -2147483649 dog ", sourceType); + if (!s.hasNextInt()) failCount++; + if (s.nextInt() != 22) failCount++; + if (!s.hasNextInt()) failCount++; + if (s.nextInt() != 22) failCount++; + if (!s.hasNextInt(16)) failCount++; + if (s.nextInt(16) != 12) failCount++; + if (!s.hasNextInt()) failCount++; + if (s.nextInt() != -34) failCount++; + for (int i=0; i<3; i++) { + if (s.hasNextInt()) + failCount++; + try { + s.nextInt(); + failCount++; + } catch (InputMismatchException ime) { + // Correct result + } + s.next(); + } + try { + s.next(); + failCount++; + } catch (InputMismatchException ime) { + failCount++; + } catch (NoSuchElementException nse) { + // Correct result + } + report("Scan ints"); + } + + private static void longTest(int sourceType) throws Exception { + Scanner s = scannerFor( + "022 9223372036854775807 0x8000000000000000 9223372036854775808 dog ", + sourceType); + if (!s.hasNextLong()) failCount++; + if (s.nextLong() != (long)22) failCount++; + if (!s.hasNextLong()) failCount++; + if (s.nextLong() != 9223372036854775807L) failCount++; + for (int i=0; i<3; i++) { + if (s.hasNextLong()) + failCount++; + try { + s.nextLong(); + failCount++; + } catch (InputMismatchException ime) { + // Correct result + } + s.next(); + } + try { + s.next(); + failCount++; + } catch (InputMismatchException ime) { + failCount++; + } catch (NoSuchElementException nse) { + // Correct result + } + report("Scan longs"); + } + + private static void floatTest(int sourceType) throws Exception { + Scanner s = scannerFor( + "0 0. 0.0 2 2. 2.0 2.3 -2 -2.0 -2.3 -. 2-. 2..3", sourceType); + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 0f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 0f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 0f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 2f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 2f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 2f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 2.3f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != -2f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != -2f) failCount++; + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != -2.3f) failCount++; + for (int i=0; i<3; i++) { + if (s.hasNextLong()) + failCount++; + try { + s.nextFloat(); + failCount++; + } catch (InputMismatchException ime) { + // Correct result + } + s.next(); + } + try { + s.next(); + failCount++; + } catch (InputMismatchException ime) { + failCount++; + } catch (NoSuchElementException nse) { + // Correct result + } + report("Scan floats"); + } + + private static void doubleTest(int sourceType) throws Exception { + Scanner s = scannerFor( + "0 0. 0.0 2 2. 2.0 2.3 -2 -2.0 -2.3 -. 2-. 2..3", sourceType); + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != 0d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != 0d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != 0d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != 2d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != 2d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != 2d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != 2.3d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != -2d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != -2d) failCount++; + if (!s.hasNextDouble()) failCount++; + if (s.nextDouble() != -2.3d) failCount++; + for (int i=0; i<3; i++) { + if (s.hasNextLong()) + failCount++; + try { + s.nextDouble(); + failCount++; + } catch (InputMismatchException ime) { + // Correct result + } + s.next(); + } + try { + s.next(); + failCount++; + } catch (InputMismatchException ime) { + failCount++; + } catch (NoSuchElementException nse) { + // Correct result + } + report("Scan doubles"); + } + + private static void booleanTest(int sourceType) throws Exception { + Scanner s = scannerFor( + " true false\t \r\n true FaLse \n True Tru", sourceType); + if (!s.nextBoolean()) failCount++; + if (!s.hasNextBoolean()) failCount++; + if (s.nextBoolean()) failCount++; + if (!s.nextBoolean()) failCount++; + if (s.nextBoolean()) failCount++; + if (!s.nextBoolean()) failCount++; + if (s.hasNextBoolean()) failCount++; + try { + s.nextBoolean(); + failCount++; + } catch (NoSuchElementException nsee) { + // Expected result + } + report("Scan booleans"); + } + + private static void hasNextTest(int sourceType) throws Exception { + Scanner s = scannerFor( + " blah blech\t blather alongblatherindeed", sourceType); + if (!s.hasNext()) failCount++; + if (!s.hasNext()) failCount++; + String result = s.next(); + if (!result.equals("blah")) failCount++; + if (!s.hasNext()) failCount++; + if (!s.hasNext()) failCount++; + result = s.next(); + if (!result.equals("blech")) failCount++; + if (!s.hasNext()) failCount++; + result = s.next(); + if (!result.equals("blather")) failCount++; + if (!s.hasNext()) failCount++; + if (!s.hasNext()) failCount++; + result = s.next(); + if (!result.equals("alongblatherindeed")) failCount++; + if (s.hasNext()) failCount++; + try { + result = s.next(); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + report("Has next test"); + } + + private static void nextTest(int sourceType) throws Exception { + Scanner s = scannerFor( + " blah blech\t blather alongblatherindeed", sourceType); + String result = (String)s.next(); + if (!result.equals("blah")) failCount++; + result = (String)s.next(); + if (!result.equals("blech")) failCount++; + result = (String)s.next(); + if (!result.equals("blather")) failCount++; + result = (String)s.next(); + if (!result.equals("alongblatherindeed")) + failCount++; + try { + result = (String)s.next(); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + report("Next test"); + } + + private static void hasNextPatternTest(int sourceType) throws Exception { + Scanner s = scannerFor( + " blah blech\t blather alongblatherindeed", sourceType); + Pattern p1 = Pattern.compile("\\w+"); + Pattern p2 = Pattern.compile("blech"); + if (!s.hasNext(p1)) failCount++; + if (!s.hasNext(p1)) failCount++; + if (s.hasNext(p2)) failCount++; + String result = (String)s.next(); + if (!result.equals("blah")) failCount++; + if (!s.hasNext(p1)) failCount++; + if (!s.hasNext(p2)) failCount++; + result = (String)s.next(); + if (!result.equals("blech")) failCount++; + if (!s.hasNext(p1)) failCount++; + if (s.hasNext(p2)) failCount++; + result = (String)s.next(); + if (!result.equals("blather")) failCount++; + if (!s.hasNext(p1)) failCount++; + if (s.hasNext(p2)) failCount++; + result = (String)s.next(); + if (!result.equals("alongblatherindeed")) failCount++; + if (s.hasNext(p1)) failCount++; + if (s.hasNext(p2)) failCount++; + report("Has Next Pattern test"); + } + + private static void nextPatternTest(int sourceType) throws Exception { + Scanner s = scannerFor( + " blah blech\t blather alongblatherindeed", sourceType); + Pattern p1 = Pattern.compile("blah"); + Pattern p2 = Pattern.compile("blech"); + Pattern p3 = Pattern.compile("blather"); + Pattern p4 = Pattern.compile("alongblatherindeed"); + String result = null; + try { + result = (String)s.next(p2); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + result = (String)s.next(p1); + if (!result.equals("blah")) + failCount++; + try { + result = (String)s.next(p1); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + result = (String)s.next(p2); + if (!result.equals("blech")) + failCount++; + try { + result = (String)s.next(p4); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + result = (String)s.next(p3); + if (!result.equals("blather")) + failCount++; + try { + result = (String)s.next(p3); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + result = (String)s.next(p4); + if (!result.equals("alongblatherindeed")) + failCount++; + try { + result = (String)s.next(); + failCount++; + } catch (NoSuchElementException nsee) { + // Correct result + } + report("Next pattern test"); + } + + private static void useLocaleTest() throws Exception { + Scanner s = new Scanner("334.65").useLocale(Locale.ENGLISH); + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 334.65f) failCount++; + + s = new Scanner("334,65").useLocale(Locale.FRENCH); + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 334.65f) failCount++; + + s = new Scanner("4.334,65").useLocale(Locale.GERMAN); + if (!s.hasNextFloat()) failCount++; + if (s.nextFloat() != 4334.65f) failCount++; + + // Test case reported from India + try { + String Message = "123978.90 $"; + Locale locale = new Locale("hi","IN"); + NumberFormat form = NumberFormat.getInstance(locale); + double myNumber = 1902.09; + Scanner scanner = new Scanner(form.format(myNumber).toString()); + scanner.useLocale(locale); + double d = scanner.nextDouble(); + } catch (InputMismatchException ime) { + failCount++; + } + report("Use locale test"); + } + + public static void resetTest() throws Exception { + Scanner sc = new Scanner(""); + int radix = sc.radix(); + Locale locale = sc.locale(); + Pattern delimiter = sc.delimiter(); + Pattern a = Pattern.compile("A"); + sc.useDelimiter(a); + Locale dummy = new Locale("en", "US", "dummy"); + sc.useLocale(dummy); + sc.useRadix(16); + if (sc.radix() != 16 || + !sc.locale().equals(dummy) || + !sc.delimiter().pattern().equals(a.pattern())) { + failCount++; + } else { + sc.reset(); + if (sc.radix() != radix || + !sc.locale().equals(locale) || + !sc.delimiter().pattern().equals(delimiter.pattern())) { + failCount++; + } + } + sc.close(); + report("Reset test"); + } + + private static void report(String testName) { + int spacesToAdd = 30 - testName.length(); + StringBuffer paddedNameBuffer = new StringBuffer(testName); + for (int i=0; i 0) + failure = true; + failCount = 0; + } + + static Scanner scannerFor(String input, int sourceType) { + if (sourceType == 1) + return new Scanner(input); + else + return new Scanner(new StutteringInputStream(input)); + } + + static class ThrowingReadable implements Readable { + ThrowingReadable() { + } + public int read(java.nio.CharBuffer cb) throws IOException { + throw new IOException("ThrowingReadable always throws"); + } + } +} diff --git a/test/java/util/Scanner/input.txt b/test/java/util/Scanner/input.txt new file mode 100644 --- /dev/null +++ b/test/java/util/Scanner/input.txt @@ -0,0 +1,438 @@ +# Data for fromFileTest +14343441 +24134342 +34324233 +43234234 +53423425 +63424326 +74324337 + + +# Data for usage case 1 +23.4 Frank 34.8 -9.0 +2.333 6.75 Joe -2 +3.3 -888.8 -16.00 Mary +Michelle -5 -5.5 -5.555 + + +# Data for usage case 2 +cat-9-dog-6-pig-2--5- + + +# Data for usage case 3 + /** + * Returns the next string in the input that matches the specified pattern. + * This method may block while waiting for input + * to scan, even if a previous invocation of {@link #hasNext(Pattern)} + * returned true. If the match is successful, the scanner + * advances past the input that matched the pattern. + * + * @param pattern the pattern to scan for + * @return the next token + * @throws NoSuchElementException if no more tokens are available + * @throws IllegalStateException if this scanner is closed + */ + + +# Data for usage case 4 + + +Source Directory +

    tiger

    +

    +Parent workspace is /java/jdk/1.5/ws/integration/TL/j2se
    +Child workspace is /export/tiger
    +


    + +

    +Diffs +Sdiffs +Old +New +make/java/java/mapfile-vers

    +

      +
    • 4904881: JVM crash during java.io.File.deleteOnExit()
      +
    +

    +Diffs +Sdiffs +Old +New +src/share/classes/java/lang/Shutdown.java

    +

      +
    • 4904881: JVM crash during java.io.File.deleteOnExit()
      +
    +

    +Diffs +Sdiffs +Old +New +src/share/native/java/lang/Shutdown.c

    +

      +
    • 4904881: JVM crash during java.io.File.deleteOnExit()
      +
    +
    +

    + + + +# Data for usage case 5 + +# This is the main Samba configuration file. You should read the +# smb.conf(5) manual page in order to understand the options listed +# here. Samba has a huge number of configurable options (perhaps too +# many!) most of which are not shown in this example +# +# Any line which starts with a ; (semi-colon) or a # (hash) +# is a comment and is ignored. In this example we will use a # +# for commentry and a ; for parts of the config file that you +# may wish to enable +# +# NOTE: Whenever you modify this file you should run the command "testparm" +# to check that you have not many any basic syntactic errors. +# +#======================= Global Settings ===================================== +[global] + +## +## Basic Server Settings +## + + # workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 + workgroup = MYGROUP + + # server string is the equivalent of the NT Description field + server string = Samba Server + + # This option is important for security. It allows you to restrict + # connections to machines which are on your local network. The + # following example restricts access to two C class networks and + # the "loopback" interface. For more examples of the syntax see + # the smb.conf man page + ; hosts allow = 192.168.1. 192.168.2.0./24 192.168.3.0/255.255.255.0 127.0.0.1 + + # Uncomment this if you want a guest account, you must add this to /etc/passwd + # otherwise the user "nobody" is used + ; guest account = pcguest + + # this tells Samba to use a separate log file for each machine + # that connects + log file = /usr/local/samba/var/log.%m + + # How much information do you want to see in the logs? + # default is only to log critical messages + ; log level = 1 + + # Put a capping on the size of the log files (in Kb). + max log size = 50 + + # Security mode. Most people will want user level security. See + # security_level.txt for details. + security = user + + # Using the following line enables you to customise your configuration + # on a per machine basis. The %m gets replaced with the netbios name + # of the machine that is connecting. + # Note: Consider carefully the location in the configuration file of + # this line. The included file is read at that point. + ; include = /usr/local/samba/lib/smb.conf.%m + + # Most people will find that this option gives better performance. + # See speed.txt and the manual pages for details + # You may want to add the following on a Linux system: + # SO_RCVBUF=8192 SO_SNDBUF=8192 + ; socket options = TCP_NODELAY + + # Configure Samba to use multiple interfaces + # If you have multiple network interfaces and want to limit smbd will + # use, list the ones desired here. Otherwise smbd & nmbd will bind to all + # active interfaces on the system. See the man page for details. + ; interfaces = 192.168.12.2/24 192.168.13.2/24 + + # Should smbd report that it has MS-DFS Capabilities? Only available + # if --with-msdfs was passed to ./configure + ; host msdfs = yes + +## +## Network Browsing +## + # set local master to no if you don't want Samba to become a master + # browser on your network. Otherwise the normal election rules apply + ; local master = no + + # OS Level determines the precedence of this server in master browser + # elections. The default value (20) should be reasonable + ; os level = 20 + + # Domain Master specifies Samba to be the Domain Master Browser. This + # allows Samba to collate browse lists between subnets. Don't use this + # if you already have a Windows NT domain controller doing this job + ; domain master = yes + + # Preferred Master causes Samba to force a local browser election on startup + # and gives it a slightly higher chance of winning the election + ; preferred master = yes + + +## +## WINS & Name Resolution +## + # Windows Internet Name Serving Support Section: + # WINS Support - Tells the NMBD component of Samba to enable it's WINS Server + ; wins support = yes + + # WINS Server - Tells the NMBD components of Samba to be a WINS Client + # Note: Samba can be either a WINS Server, or a WINS Client, but NOT both + ; wins server = w.x.y.z + + # WINS Proxy - Tells Samba to answer name resolution queries on + # behalf of a non WINS capable client, for this to work there must be + # at least one WINS Server on the network. The default is NO. + ; wins proxy = yes + + # DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names + # via DNS nslookups. + dns proxy = no + + +## +## Passwords & Authentication +## + # Use password server option only with security = server + # The argument list may include: + # password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name] + # or to auto-locate the domain controller/s + ; password server = * + ; password server = + + # You may wish to use password encryption. Please read + # ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation. + # Do not enable this option unless you have read those documents + ; encrypt passwords = yes + + # Should smbd obey the session and account lines in /etc/pam.d/samba ? + # only available if --with-pam was used at compile time + ; obey pam restrictions = yes + + # When using encrypted passwords, Samba can synchronize the local + # UNIX password as well. You will also need the "passwd chat" parameters + ; unix password sync = yes + + # how should smbd talk to the local system when changing a UNIX + # password? See smb.conf(5) for details + ; passwd chat = + + # This is only available if you compiled Samba to include --with-pam + # Use PAM for changing the password + ; pam password change = yes + +## +## Domain Control +## + # Enable this if you want Samba act as a domain controller. + # make sure you have read the Samba-PDC-HOWTO included in the documentation + # before enabling this parameter + ; domain logons = yes + + # if you enable domain logons then you may want a per-machine or + # per user logon script + # run a specific logon batch file per workstation (machine) + ; logon script = %m.bat + # run a specific logon batch file per username + ; logon script = %U.bat + + # Where to store roving profiles (only for Win95 and WinNT) + # %L substitutes for this servers netbios name, %U is username + # You must uncomment the [Profiles] share below + ; logon path = \\%L\Profiles\%U + + # UNC path specifying the network location of the user's home directory + # only used when acting as a DC for WinNT/2k/XP. Ignored by Win9x clients + ; logon home = \\%L\%U + + # What drive should the "logon home" be mounted at upon login ? + # only used when acting as a DC for WinNT/2k/XP. Ignored by Win9x clients + ; logon drive = H: + +## +## Printing +## + + # If you want to automatically load your printer list rather + # than setting them up individually then you'll need this + load printers = yes + + # you may wish to override the location of the printcap file + ; printcap name = /etc/printcap + + # on SystemV system setting printcap name to lpstat should allow + # you to automatically obtain a printer list from the SystemV spool + # system + ; printcap name = lpstat + + # It should not be necessary to specify the print system type unless + # it is non-standard. Currently supported print systems include: + # bsd, sysv, plp, lprng, aix, hpux, qnx + ; printing = bsd + + # Enable this to make Samba 2.2 behavior just like Samba 2.0 + # not recommended nuless you are sure of what you are doing + ; disable spoolss = yes + + # list of users and groups which should be able to remotely manage + # printer drivers installed on the server + ; printer admin = root, +ntadmin + + +## +## Winbind +## + + # specify the uid range which can be used by winbindd + # to allocate uids for Windows users as necessary + ; winbind uid = 10000-65000 + + # specify the uid range which can be used by winbindd + # to allocate uids for Windows users as necessary + ; winbind gid = 10000-65000 + + # Define a home directory to be given to passwd(5) style entries + # generated by libnss_winbind.so. You can use variables here + ; winbind template homedir = /home/%D/%U + + # Specify a shell for all winbind user entries return by the + # libnss_winbind.so library. + ; winbind template shell = /bin/sh + + # What character should be used to separate the DOMAIN and Username + # for a Windows user. The default is DOMAIN\user, but many people + # prefer DOMAIN+user + ; winbind separator = + + + +#============================ Share Definitions ============================== +[homes] + comment = Home Directories + browseable = no + writable = yes + valid users = %S + +# Un-comment the following and create the netlogon directory for Domain Logons +; [netlogon] +; comment = Network Logon Service +; path = /usr/local/samba/lib/netlogon +; guest ok = yes +; writable = no +; share modes = no + + +# Un-comment the following to provide a specific roving profile share +# the default is to use the user's home directory +;[Profiles] +; path = /usr/local/samba/profiles +; browseable = no +; guest ok = yes + + +# NOTE: If you have a BSD-style print system there is no need to +# specifically define each individual printer +[printers] + comment = All Printers + path = /usr/spool/samba + browseable = no + # Set public = yes to allow user 'guest account' to print + guest ok = no + writable = no + printable = yes + +# This one is useful for people to share files +#[tmp] +# comment = Temporary file space +# path = /tmp +# read only = no +# public = yes + + +# MS-DFS support is only available if Samba was compiled to +# include --with-msdfs +;[dfsroot] +; dfs root = yes + + +# A publicly accessible directory, but read only, except for people in +# the "staff" group +;[public] +; comment = Public Stuff +; path = /home/samba +; public = yes +; writable = yes +; printable = no +; write list = @staff + + +## +## Other examples. +## + +# A private printer, usable only by fred. Spool data will be placed in fred's +# home directory. Note that fred must have write access to the spool directory, +# wherever it is. +#[fredsprn] +# comment = Fred's Printer +# valid users = fred +# path = /homes/fred +# printer = freds_printer +# public = no +# writable = no +# printable = yes + +# A private directory, usable only by fred. Note that fred requires write +# access to the directory. +#[fredsdir] +# comment = Fred's Service +# path = /usr/somewhere/private +# valid users = fred +# public = no +# writable = yes +# printable = no + +# a service which has a different directory for each machine that connects +# this allows you to tailor configurations to incoming machines. You could +# also use the %U option to tailor it by user name. +# The %m gets replaced with the machine name that is connecting. +#[pchome] +# comment = PC Directories +# path = /usr/pc/%m +# public = no +# writable = yes + +# A publicly accessible directory, read/write to all users. Note that all files +# created in the directory by users will be owned by the default user, so +# any user with access can delete any other user's files. Obviously this +# directory must be writable by the default user. Another user could of course +# be specified, in which case all files would be owned by that user instead. +#[public] +# path = /usr/somewhere/else/public +# public = yes +# only guest = yes +# writable = yes +# printable = no + +# The following two entries demonstrate how to share a directory so that two +# users can place files there that will be owned by the specific users. In this +# setup, the directory should be writable by both users and should have the +# sticky bit set on it to prevent abuse. Obviously this could be extended to +# as many users as required. +#[myshare] +# comment = Mary's and Fred's stuff +# path = /usr/somewhere/shared +# valid users = mary fred +# public = no +# writable = yes +# printable = no +# create mask = 0765 + + + + +# Data for usage case 6 diff --git a/test/javax/imageio/AllowSearch.java b/test/javax/imageio/AllowSearch.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/AllowSearch.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001, 2017, 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 4420318 8183341 + * @summary Checks that an IllegalStateException is thrown by getNumImages(true) + * when seekForwardOnly is true + */ + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +import com.sun.imageio.plugins.gif.GIFImageReader; +import com.sun.imageio.plugins.jpeg.JPEGImageReader; +import com.sun.imageio.plugins.png.PNGImageReader; + +public class AllowSearch { + private static void test(ImageReader reader, String format) + throws IOException { + boolean gotISE = false; + File f = null; + ImageInputStream stream = null; + try { + f = File.createTempFile("imageio", ".tmp"); + stream = ImageIO.createImageInputStream(f); + reader.setInput(stream, true); + + try { + int numImages = reader.getNumImages(true); + } catch (IOException ioe) { + gotISE = false; + } catch (IllegalStateException ise) { + gotISE = true; + } + } finally { + if (stream != null) { + stream.close(); + } + + reader.dispose(); + + if (f != null) { + Files.delete(f.toPath()); + } + } + + if (!gotISE) { + throw new RuntimeException("Failed to get desired exception for " + + format + " reader!"); + } + } + + public static void main(String[] args) throws IOException { + ImageReader gifReader = new GIFImageReader(null); + ImageReader jpegReader = new JPEGImageReader(null); + ImageReader pngReader = new PNGImageReader(null); + + test(gifReader, "GIF"); + test(jpegReader, "JPEG"); + test(pngReader, "PNG"); + } +} diff --git a/test/javax/imageio/AppContextTest.java b/test/javax/imageio/AppContextTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/AppContextTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2001, 2017, 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 4421190 + * @summary Tests that Image I/O statics may be referenced properly from + * multiple AppContexts, as would be the case for multiple Applets in a + * single VM. Each AppContext should get its own copy of the registry + * and the caching parameters in the ImageIO class. + */ + +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.spi.IIORegistry; + +import sun.awt.SunToolkit; + +class TestThread extends Thread { + + IIORegistry registry; + boolean useCache; + File cacheDirectory; + boolean cacheSettingsOK = false; + String threadName; + + boolean gotCrosstalk = false; + + public TestThread(ThreadGroup tg, + boolean useCache, File cacheDirectory, + String threadName) { + super(tg, threadName); + this.useCache = useCache; + this.cacheDirectory = cacheDirectory; + this.threadName = threadName; + } + + public void run() { +// System.out.println("Thread " + threadName + " in thread group " + +// getThreadGroup().getName()); + + // Create a new AppContext as though we were an applet + SunToolkit.createNewAppContext(); + + // Get default registry and store reference + this.registry = IIORegistry.getDefaultInstance(); + + for (int i = 0; i < 10; i++) { +// System.out.println(threadName + +// ": setting cache parameters to " + +// useCache + ", " + cacheDirectory); + ImageIO.setUseCache(useCache); + ImageIO.setCacheDirectory(cacheDirectory); + + try { + sleep(1000L); + } catch (InterruptedException e) { + } + +// System.out.println(threadName + ": reading cache parameters"); + boolean newUseCache = ImageIO.getUseCache(); + File newCacheDirectory = ImageIO.getCacheDirectory(); + if (newUseCache != useCache || + newCacheDirectory != cacheDirectory) { +// System.out.println(threadName + ": got " + +// newUseCache + ", " + +// newCacheDirectory); +// System.out.println(threadName + ": crosstalk encountered!"); + gotCrosstalk = true; + } + } + } + + public IIORegistry getRegistry() { + return registry; + } + + public boolean gotCrosstalk() { + return gotCrosstalk; + } +} + +public class AppContextTest { + + public AppContextTest() { + ThreadGroup tg0 = new ThreadGroup("ThreadGroup0"); + ThreadGroup tg1 = new ThreadGroup("ThreadGroup1"); + + TestThread t0 = + new TestThread(tg0, false, null, "TestThread 0"); + TestThread t1 = + new TestThread(tg1, true, new File("."), "TestThread 1"); + + t0.start(); + t1.start(); + + try { + t0.join(); + } catch (InterruptedException ie0) { + } + try { + t1.join(); + } catch (InterruptedException ie1) { + } + + if (t0.gotCrosstalk() || t1.gotCrosstalk()) { + throw new RuntimeException("ImageIO methods had crosstalk!"); + } + + if (t0.getRegistry() == t1.getRegistry()) { + throw new RuntimeException("ThreadGroups had same IIORegistry!"); + } + } + + public static void main(String[] args) throws IOException { + new AppContextTest(); + } +} diff --git a/test/javax/imageio/AppletResourceTest.html b/test/javax/imageio/AppletResourceTest.html new file mode 100644 --- /dev/null +++ b/test/javax/imageio/AppletResourceTest.html @@ -0,0 +1,40 @@ + + + + + + AppletResourceTest + + + + + diff --git a/test/javax/imageio/AppletResourceTest.java b/test/javax/imageio/AppletResourceTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/AppletResourceTest.java @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2003, 2017, 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 4481957 + * @key headful + * @summary Tests that applet-supplied ImageReader, ImageWriter, and + * IIOMetadataFormat implementations do not throw unexpected exceptions + * when indirectly attempting to access ResourceBundles + * @run main AppletResourceTest + * @run applet AppletResourceTest.html + */ + +import java.applet.Applet; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Iterator; +import java.util.ListResourceBundle; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.Vector; + +import javax.imageio.IIOException; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.event.IIOReadWarningListener; +import javax.imageio.metadata.IIOInvalidTreeException; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.spi.ImageReaderSpi; + +import org.w3c.dom.Node; + +public class AppletResourceTest extends Applet { + + public static void main(String[] argv) { + new AppletResourceTest().init(); + } + + public void init() { + DummyImageReaderImpl reader; + MyReadWarningListener listener = new MyReadWarningListener(); + Locale[] locales = {new Locale("ru"), + new Locale("fr"), + new Locale("uk")}; + + reader = new DummyImageReaderImpl(new DummyImageReaderSpiImpl()); + reader.setAvailableLocales(locales); + reader.setLocale(new Locale("fr")); + reader.addIIOReadWarningListener(listener); + + String baseName = "AppletResourceTest$BugStats"; + try { + reader.processWarningOccurred("WarningMessage"); + reader.processWarningOccurred(baseName, "water"); + } catch (MissingResourceException mre) { + throw new RuntimeException("Test failed: couldn't load resource"); + } + + + } + + private class MyReadWarningListener implements IIOReadWarningListener { + public void warningOccurred(ImageReader source, + String warning) + { + System.out.println("warning occurred: " + warning); + } + } + + public static class BugStats extends ListResourceBundle { + + public Object[][] getContents(){ + return contents; + } + + private Object[][] contents = { + {"coffee", new String("coffee from Stats class")}, + {"tea", new String("tea from Stats class")}, + {"water", new String("water from Stats class")} + }; + } + + + public static class DummyImageReaderImpl extends ImageReader { + + public DummyImageReaderImpl(ImageReaderSpi originatingProvider) { + super(originatingProvider); + } + + public int getNumImages(boolean allowSearch) throws IOException { + return 5; + } + + public int getWidth(int imageIndex) throws IOException { + if (input == null) + throw new IllegalStateException(); + if (imageIndex >= 5 || imageIndex < 0) + throw new IndexOutOfBoundsException(); + + return 10; + } + + public int getHeight(int imageIndex) throws IOException { + if (input == null) + throw new IllegalStateException(); + if (imageIndex >= 5 || imageIndex < 0) + throw new IndexOutOfBoundsException(); + + return 15; + } + + public Iterator getImageTypes(int imageIndex) throws IOException { + if (input == null) + throw new IllegalStateException(); + if (imageIndex >= 5 || imageIndex < 0) + throw new IndexOutOfBoundsException(); + + Vector imageTypes = new Vector(); + imageTypes.add(ImageTypeSpecifier.createFromBufferedImageType + (BufferedImage.TYPE_BYTE_GRAY )); + return imageTypes.iterator(); + } + + public IIOMetadata getStreamMetadata() throws IOException { + return new DummyIIOMetadataImpl(true, null, null, null, null); + } + + public IIOMetadata getImageMetadata(int imageIndex) + throws IOException { + + if (input == null) + throw new IllegalStateException(); + if (imageIndex >= 5 || imageIndex < 0) + throw new IndexOutOfBoundsException(); + if (seekForwardOnly) { + if (imageIndex < minIndex) + throw new IndexOutOfBoundsException(); + minIndex = imageIndex; + } + return new DummyIIOMetadataImpl(true, null, null, null, null); + } + + + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException { + if (input == null) + throw new IllegalStateException(); + if (imageIndex >= 5 || imageIndex < 0) + throw new IndexOutOfBoundsException(); + if (seekForwardOnly) { + if (imageIndex < minIndex) + throw new IndexOutOfBoundsException(); + minIndex = imageIndex; + } + + return getDestination(param, getImageTypes(imageIndex), 10, 15); + } + +// protected methods - now public + + public boolean abortRequested() { + return super.abortRequested(); + } + + public void clearAbortRequest() { + super.clearAbortRequest(); + } + + public void processImageComplete() { + super.processImageComplete(); + } + + public void processImageProgress(float percentageDone) { + super.processImageProgress(percentageDone); + } + + public void processImageStarted(int imageIndex) { + super.processImageStarted(imageIndex); + } + + public void processImageUpdate(BufferedImage theImage, + int minX, + int minY, + int width, + int height, + int periodX, + int periodY, + int[] bands) { + super.processImageUpdate(theImage, + minX, + minY, + width, + height, + periodX, + periodY, + bands); + } + + public void processPassComplete(BufferedImage theImage) { + super. processPassComplete(theImage); + } + + public void processPassStarted(BufferedImage theImage, + int pass, int minPass, + int maxPass, + int minX, + int minY, + int periodX, + int periodY, + int[] bands) { + super.processPassStarted(theImage, + pass, + minPass, + maxPass, + minX, + minY, + periodX, + periodY, + bands); + } + + public void processReadAborted() { + super.processReadAborted(); + } + + public void processSequenceComplete() { + super.processSequenceComplete(); + } + + public void processSequenceStarted(int minIndex) { + super.processSequenceStarted(minIndex); + } + + public void processThumbnailComplete() { + super.processThumbnailComplete(); + } + + public void processThumbnailPassComplete(BufferedImage theThumbnail) { + super.processThumbnailPassComplete(theThumbnail); + } + + public void processThumbnailPassStarted(BufferedImage theThumbnail, + int pass, + int minPass, + int maxPass, + int minX, + int minY, + int periodX, + int periodY, + int[] bands) { + super.processThumbnailPassStarted(theThumbnail, + pass, + minPass, + maxPass, + minX, + minY, + periodX, + periodY, + bands); + } + + public void processThumbnailProgress(float percentageDone) { + super.processThumbnailProgress(percentageDone); + } + + public void processThumbnailStarted(int imageIndex, int thumbnailIndex) { + super.processThumbnailStarted(imageIndex, thumbnailIndex); + } + + public void processThumbnailUpdate(BufferedImage theThumbnail, + int minX, + int minY, + int width, + int height, + int periodX, + int periodY, + int[] bands) { + super.processThumbnailUpdate(theThumbnail, + minX, + minY, + width, + height, + periodX, + periodY, + bands); + } + + public void processWarningOccurred(String warning) { + super.processWarningOccurred(warning); + } + + + + public static Rectangle getSourceRegion(ImageReadParam param, + int srcWidth, + int srcHeight) { + return ImageReader.getSourceRegion(param, srcWidth, srcHeight); + } + + public static void computeRegions(ImageReadParam param, + int srcWidth, + int srcHeight, + BufferedImage image, + Rectangle srcRegion, + Rectangle destRegion) { + ImageReader.computeRegions(param, + srcWidth, + srcHeight, + image, + srcRegion, + destRegion); + } + + public static void checkReadParamBandSettings(ImageReadParam param, + int numSrcBands, + int numDstBands) { + ImageReader.checkReadParamBandSettings( param, + numSrcBands, + numDstBands); + } + + public static BufferedImage getDestination(ImageReadParam param, + Iterator imageTypes, + int width, + int height) throws IIOException { + return ImageReader.getDestination(param, + imageTypes, + width, + height); + } + + public void setAvailableLocales(Locale[] locales) { + if (locales == null || locales.length == 0) + availableLocales = null; + else + availableLocales = (Locale[])locales.clone(); + } + + public void processWarningOccurred(String baseName, String keyword) { + super.processWarningOccurred(baseName, keyword); + } + } + + public static class DummyIIOMetadataImpl extends IIOMetadata { + + public DummyIIOMetadataImpl() { + super(); + } + + public DummyIIOMetadataImpl(boolean standardMetadataFormatSupported, + String nativeMetadataFormatName, + String nativeMetadataFormatClassName, + String[] extraMetadataFormatNames, + String[] extraMetadataFormatClassNames) { + super(standardMetadataFormatSupported, + nativeMetadataFormatName, + nativeMetadataFormatClassName, + extraMetadataFormatNames, + extraMetadataFormatClassNames); + } + + public boolean isReadOnly() { + return true; + } + + public Node getAsTree(String formatName) { + return null; + } + + public void mergeTree(String formatName, Node root) + throws IIOInvalidTreeException { + throw new IllegalStateException(); + } + + public void reset() { + throw new IllegalStateException(); + } + } + + public static class DummyImageReaderSpiImpl extends ImageReaderSpi { + + static final String[] names ={ "myformat" }; + + public DummyImageReaderSpiImpl() { + super("vendorName", + "version", + names, + null, + null, + "DummyImageReaderImpl", + STANDARD_INPUT_TYPE, + null, + true, + null, + null, + null, + null, + true, + null, + null, + null, + null); + } + public boolean canDecodeInput(Object source) + throws IOException { + return true; + } + public ImageReader createReaderInstance(Object extension) + throws IOException { + return new DummyImageReaderImpl(this); + } + public String getDescription(Locale locale) { + return "DummyImageReaderSpiImpl"; + } + } +} diff --git a/test/javax/imageio/GetNumImages.java b/test/javax/imageio/GetNumImages.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/GetNumImages.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2003, 2017, 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 4892609 + * @summary Tests that the appropriate IllegalStateException is thrown if + * ImageReader.getNumImages() is called with a null source or if + * allowSearch is specified at the same time that seekForwardOnly is + * true + */ + +import java.io.ByteArrayInputStream; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; + +public class GetNumImages { + + public static void main(String[] args) throws Exception { + IIORegistry registry = IIORegistry.getDefaultInstance(); + + // test ImageReader.getNumImages() for all available ImageReaders, + // with no source set + Iterator readerspis = registry.getServiceProviders(ImageReaderSpi.class, + false); + while (readerspis.hasNext()) { + boolean caughtEx = false; + ImageReaderSpi readerspi = (ImageReaderSpi)readerspis.next(); + ImageReader reader = readerspi.createReaderInstance(); + try { + reader.getNumImages(false); + } catch (IllegalStateException ise) { + // caught exception, everything's okay + caughtEx = true; + } + + if (!caughtEx) { + throw new RuntimeException("Test failed: exception was not " + + "thrown for null input: " + + reader); + } + } + + // test ImageReader.getNumImages() for all available ImageReaders, + // with source set, seekForwardOnly and allowSearch both true + readerspis = registry.getServiceProviders(ImageReaderSpi.class, + false); + while (readerspis.hasNext()) { + boolean caughtEx = false; + ImageReaderSpi readerspi = (ImageReaderSpi)readerspis.next(); + ImageReader reader = readerspi.createReaderInstance(); + byte[] barr = new byte[100]; + ByteArrayInputStream bais = new ByteArrayInputStream(barr); + ImageInputStream iis = ImageIO.createImageInputStream(bais); + try { + reader.setInput(iis, true); + reader.getNumImages(true); + } catch (IllegalStateException ise) { + // caught exception, everything's okay + caughtEx = true; + } + + if (!caughtEx) { + throw new RuntimeException("Test failed: exception was not " + + "thrown when allowSearch and " + + "seekForwardOnly are both true: " + + reader); + } + } + } +} diff --git a/test/javax/imageio/GetReaderWriterInfo.java b/test/javax/imageio/GetReaderWriterInfo.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/GetReaderWriterInfo.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2006, 2017, 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 4703112 + * @summary Verifies that ImageIO.getReaderFileSuffixes() and similar methods + * return appropriate values + */ + +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriter; + +public class GetReaderWriterInfo { + + private static void testGetReaderFormatNames() { + String[] names = ImageIO.getReaderFormatNames(); + for (String n : names) { + Iterator it = ImageIO.getImageReadersByFormatName(n); + if (!it.hasNext()) { + throw new RuntimeException("getReaderFormatNames returned " + + "an unknown name: " + n); + } + } + } + + private static void testGetReaderMIMETypes() { + String[] types = ImageIO.getReaderMIMETypes(); + for (String t : types) { + Iterator it = ImageIO.getImageReadersByMIMEType(t); + if (!it.hasNext()) { + throw new RuntimeException("getReaderMIMETypes returned " + + "an unknown type: " + t); + } + } + } + + private static void testGetReaderFileSuffixes() { + String[] suffixes = ImageIO.getReaderFileSuffixes(); + for (String s : suffixes) { + Iterator it = ImageIO.getImageReadersBySuffix(s); + if (!it.hasNext()) { + throw new RuntimeException("getReaderFileSuffixes returned " + + "an unknown suffix: " + s); + } + } + } + + private static void testGetWriterFormatNames() { + String[] names = ImageIO.getWriterFormatNames(); + for (String n : names) { + Iterator it = ImageIO.getImageWritersByFormatName(n); + if (!it.hasNext()) { + throw new RuntimeException("getWriterFormatNames returned " + + "an unknown name: " + n); + } + } + } + + private static void testGetWriterMIMETypes() { + String[] types = ImageIO.getWriterMIMETypes(); + for (String t : types) { + Iterator it = ImageIO.getImageWritersByMIMEType(t); + if (!it.hasNext()) { + throw new RuntimeException("getWriterMIMETypes returned " + + "an unknown type: " + t); + } + } + } + + private static void testGetWriterFileSuffixes() { + String[] suffixes = ImageIO.getWriterFileSuffixes(); + for (String s : suffixes) { + Iterator it = ImageIO.getImageWritersBySuffix(s); + if (!it.hasNext()) { + throw new RuntimeException("getWriterFileSuffixes returned " + + "an unknown suffix: " + s); + } + } + } + + public static void main(String[] args) { + testGetReaderFormatNames(); + testGetReaderMIMETypes(); + testGetReaderFileSuffixes(); + testGetWriterFormatNames(); + testGetWriterMIMETypes(); + testGetWriterFileSuffixes(); + } +} diff --git a/test/javax/imageio/IIOImageConstructor.java b/test/javax/imageio/IIOImageConstructor.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/IIOImageConstructor.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2000, 2017, 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 4392024 + * @summary Checks for IllegalArgumentException in IIOImage constructor + */ + +import java.awt.image.BufferedImage; + +import javax.imageio.IIOImage; + +public class IIOImageConstructor { + + public static void main(String[] args) { + BufferedImage image = new BufferedImage(1, 1, + BufferedImage.TYPE_INT_RGB); + try { + IIOImage iioi = new IIOImage(image, null, null); + } catch (IllegalArgumentException iae) { + throw new RuntimeException + ("IIOImage constructor taking a RenderedImage fails!"); + } + } +} diff --git a/test/javax/imageio/ITSDataType.java b/test/javax/imageio/ITSDataType.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ITSDataType.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2017, 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 4506450 + * @summary Tests whether ImageTypeSpecifier.createBanded() and + * ImageTypeSpecifier.createInterleaved() can accept all supported + * DataBuffer types + */ + +import java.awt.color.ColorSpace; +import java.awt.image.DataBuffer; + +import javax.imageio.ImageTypeSpecifier; + +public class ITSDataType { + + public static final int[] dataTypes = new int[] { + DataBuffer.TYPE_BYTE, + DataBuffer.TYPE_SHORT, + DataBuffer.TYPE_USHORT, + DataBuffer.TYPE_INT, + DataBuffer.TYPE_FLOAT, + DataBuffer.TYPE_DOUBLE, + }; + + public static void main(String[] args) { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); + int[] bankIndices = new int[] { 1 }; + int[] bandOffsets = new int[] { 0 }; + + // test createBanded() + for (int i = 0; i < dataTypes.length; i++) { + int dataType = dataTypes[i]; + + try { + ImageTypeSpecifier.createBanded(cs, bankIndices, bandOffsets, + dataType, false, false); + } catch (IllegalArgumentException e) { + throw new RuntimeException("createBanded() test failed for " + + "dataType = " + dataType); + } + } + + // test createInterleaved() + for (int i = 0; i < dataTypes.length; i++) { + int dataType = dataTypes[i]; + + try { + ImageTypeSpecifier.createInterleaved(cs, bandOffsets, + dataType, false, false); + } catch (IllegalArgumentException e) { + throw new RuntimeException("createInterleaved() test failed " + + "for dataType = " + dataType); + } + } + } +} diff --git a/test/javax/imageio/ImageIOGetImageReaders.java b/test/javax/imageio/ImageIOGetImageReaders.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageIOGetImageReaders.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2001, 2017, 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 4432107 + * @summary Checks if ImageIO.getImageReaders(null) throws an IAE + */ + +import javax.imageio.ImageIO; + +public class ImageIOGetImageReaders { + + public static void main(String[] args) { + boolean gotIAE = false; + try { + ImageIO.getImageReaders(null); + } catch (IllegalArgumentException e) { + gotIAE = true; + } + + if (!gotIAE) { + throw new RuntimeException("Failed to get IAE!"); + } + } +} diff --git a/test/javax/imageio/ImageIOWriteFile.java b/test/javax/imageio/ImageIOWriteFile.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageIOWriteFile.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2000, 2017, 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 4393174 + * @summary Checks that ImageIO.write(..., ..., File) truncates the file + */ + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; + +import javax.imageio.ImageIO; + +public class ImageIOWriteFile { + + public static void main(String[] args) { + long length0 = -1L; + long length1 = -1L; + + try { + BufferedImage bi = + new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + + File outFile = File.createTempFile("imageiowritefile", ".tmp"); + + // Write image to an empty file + outFile.delete(); + ImageIO.write(bi, "png", outFile); + length0 = outFile.length(); + + // Write a larger file full of junk + outFile.delete(); + FileOutputStream fos = new FileOutputStream(outFile); + for (int i = 0; i < length0*2; i++) { + fos.write(1); + } + fos.close(); + + // Write image again + ImageIO.write(bi, "png", outFile); + length1 = outFile.length(); + + outFile.delete(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Unexpected exception!"); + } + + if (length0 == 0) { + throw new RuntimeException("File length is zero!"); + } + if (length1 != length0) { + throw new RuntimeException("File length changed!"); + } + } +} diff --git a/test/javax/imageio/ImageIOWriteNull.java b/test/javax/imageio/ImageIOWriteNull.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageIOWriteNull.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2001, 2017, 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 4434855 + * @summary Checks that ImageIO.write(null, null, (File)null) throws an IAE + */ + +import java.io.File; + +import javax.imageio.ImageIO; + +public class ImageIOWriteNull { + + public static void main(String[] args) { + try { + ImageIO.write(null, null, (File)null); + throw new RuntimeException("Failed to get IAE!"); + } catch (IllegalArgumentException iae) { + } catch (Exception e) { + throw new RuntimeException("Unexpected exception: " + e); + } + } +} diff --git a/test/javax/imageio/ImageReadParamPasses.java b/test/javax/imageio/ImageReadParamPasses.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageReadParamPasses.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001, 2017, 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 4429365 + * @summary Checks that ImageReadParam.setSourceProgressivePasses handles + * overflow correctly + */ + +import javax.imageio.ImageReadParam; + +public class ImageReadParamPasses { + + private static final int maxint = Integer.MAX_VALUE; + + private static void expect(int i, int j) { + if (i != j) { + throw new RuntimeException("Expected " + i + ", got " + j); + } + } + + private static void checkForIAE(int minPass, int numPasses) { + ImageReadParam param = new ImageReadParam(); + + boolean gotIAE = false; + try { + param.setSourceProgressivePasses(minPass, numPasses); + } catch (IllegalArgumentException iae) { + gotIAE = true; + } + if (!gotIAE) { + throw new RuntimeException("Failed to get IAE for wraparound!"); + } + } + + private static void test(int minPass, int numPasses) { + ImageReadParam param = new ImageReadParam(); + + param.setSourceProgressivePasses(minPass, numPasses); + expect(param.getSourceMinProgressivePass(), minPass); + expect(param.getSourceNumProgressivePasses(), numPasses); + + int maxPass = numPasses == maxint ? maxint : minPass + numPasses - 1; + expect(param.getSourceMaxProgressivePass(), maxPass); + } + + public static void main(String[] args) { + // Typical case + test(17, 30); + + // Read all passes + test(0, maxint); + + // Start at pass 17, continue indefinitely + test(17, maxint); + + // Start at pass maxint - 10, continue indefinitely + test(maxint - 10, maxint); + + // Start at pass maxint - 10, go up to maxint - 1 + test(maxint - 10, 10); + + // Start at pass maxint - 10, go up to maxint + test(maxint - 10, 11); + + // Start at maxint, continue indefinitely :-) + test(maxint, maxint); + + // Start at maxint, go up to maxint + test(maxint, 1); + + // Check that an IllegalArgumentException is thrown if + // wraparound occurs + checkForIAE(maxint, 2); + checkForIAE(maxint - 5, 10); + checkForIAE(10, maxint - 5); + checkForIAE(maxint - 1000, maxint - 1000); + checkForIAE(maxint - 1, maxint - 1); + } +} diff --git a/test/javax/imageio/ImageReaderGetDestination.java b/test/javax/imageio/ImageReaderGetDestination.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageReaderGetDestination.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001, 2017, 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 4449211 + * @summary Checks that ImageReader.getDestination throws correct exceptions + */ + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Iterator; +import java.util.Vector; + +import javax.imageio.IIOException; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.spi.ImageReaderSpi; + +public class ImageReaderGetDestination { + + public static void main(String argv[]) { + Vector imageTypes = new Vector(); + boolean gotIAE1 = false; + boolean gotIAE2 = false; + boolean gotIAE3 = false; + boolean gotIAE4 = false; + + try { + DummyImageReaderImpl.getDestination(null, null, 5, 10); + } catch (IllegalArgumentException iae) { + gotIAE1 = true; + } catch (Throwable ee) { + System.out.println("Unexpected exception 1:"); + ee.printStackTrace(); + } + if (!gotIAE1) { + throw new RuntimeException("Failed to get IAE #1!"); + } + + try { + DummyImageReaderImpl.getDestination(null, imageTypes.iterator(), + 5, 10); + } catch (IllegalArgumentException iae) { + gotIAE2 = true; + } catch (Throwable ee) { + System.out.println("Unexpected exception 2:"); + ee.printStackTrace(); + } + if (!gotIAE2) { + throw new RuntimeException("Failed to get IAE #2!"); + } + + imageTypes.add("abc"); + try { + DummyImageReaderImpl.getDestination(null, imageTypes.iterator(), + 5, 10); + } catch (IllegalArgumentException iae) { + gotIAE3 = true; + } catch (Throwable ee) { + System.out.println("Unexpected exception 3:"); + ee.printStackTrace(); + } + if (!gotIAE3) { + throw new RuntimeException("Failed to get IAE #3!"); + } + + imageTypes.clear(); + ImageTypeSpecifier its = ImageTypeSpecifier.createFromBufferedImageType + (BufferedImage.TYPE_INT_RGB); + imageTypes.add(its); + try { + DummyImageReaderImpl.getDestination(null, + imageTypes.iterator(), + Integer.MAX_VALUE, + Integer.MAX_VALUE); + } catch (IllegalArgumentException iae) { + gotIAE4 = true; + } catch (Throwable ee) { + System.out.println("Unexpected exception 4: "); + ee.printStackTrace(); + } + if (!gotIAE4) { + throw new RuntimeException("Failed to get IAE #4!"); + } + } + + public static class DummyImageReaderImpl extends ImageReader { + public DummyImageReaderImpl(ImageReaderSpi originatingProvider) { + super(originatingProvider); + } + public static BufferedImage getDestination(ImageReadParam param, + Iterator imageTypes, + int width, + int height) + throws IIOException { + return ImageReader.getDestination(param, imageTypes, width, height); + } + public int getNumImages(boolean allowSearch) throws IOException {return 1;} + public int getWidth(int imageIndex) throws IOException {return 1;} + public int getHeight(int imageIndex) throws IOException {return 1;} + public Iterator getImageTypes(int imageIndex) + throws IOException {return null;} + public IIOMetadata getStreamMetadata() throws IOException {return null;} + public IIOMetadata getImageMetadata(int imageIndex) + throws IOException {return null;} + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException {return null;} + } +} diff --git a/test/javax/imageio/ImageReaderReadAll.java b/test/javax/imageio/ImageReaderReadAll.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageReaderReadAll.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001, 2017, 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 4450319 + * @summary Checks that ImageReader.readAll(int, ImageReadParam) makes use of + * the ImageReadParam object + */ + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Iterator; +import java.util.Vector; + +import javax.imageio.IIOImage; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.MemoryCacheImageInputStream; + +public class ImageReaderReadAll { + + private final static byte[] ba = {}; + + public static void main(String argv[]) { + ImageReader ireader; + ImageReadParam irp; + IIOImage image; + BufferedImage bi; + BufferedImage bi_1; + BufferedImage bi_2; + + ireader = new DummyImageReaderImpl(null); + MemoryCacheImageInputStream mciis = new MemoryCacheImageInputStream + (new ByteArrayInputStream(ba)); + ireader.setInput(mciis); + + irp = new ImageReadParam(); + irp.setDestination(new BufferedImage(10, 10, + BufferedImage.TYPE_3BYTE_BGR)); + try { + image = ireader.readAll(0, irp); + bi_1 = ireader.read(0, irp); + bi_2 = ireader.read(0); + } catch (java.io.IOException ee) { + throw new RuntimeException("Unexpected exception: " + ee); + } + + bi = (BufferedImage)image.getRenderedImage(); + if (bi.getType() != bi_1.getType()) { + throw new RuntimeException("Images have different type!"); + } + } + + + public static class DummyImageReaderImpl extends ImageReader { + + public DummyImageReaderImpl(ImageReaderSpi originatingProvider) { + super(originatingProvider); + } + + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException { + if (input == null) + throw new IllegalStateException(); + if (imageIndex >= 1 || imageIndex < 0) + throw new IndexOutOfBoundsException(); + if (seekForwardOnly) { + if (imageIndex < minIndex) + throw new IndexOutOfBoundsException(); + minIndex = imageIndex; + } + + return getDestination(param, getImageTypes(imageIndex), 10, 15); + } + + public Iterator getImageTypes(int imageIndex) throws IOException { + if (input == null) + throw new IllegalStateException(); + if (imageIndex >= 1 || imageIndex < 0) + throw new IndexOutOfBoundsException(); + + Vector imageTypes = new Vector(); + imageTypes.add(ImageTypeSpecifier.createFromBufferedImageType + (BufferedImage.TYPE_BYTE_GRAY )); + return imageTypes.iterator(); + } + + public int getNumImages(boolean allowSearch) throws IOException {return 1;} + public int getWidth(int imageIndex) throws IOException {return 1;} + public int getHeight(int imageIndex) throws IOException {return 1;} + public IIOMetadata getStreamMetadata() throws IOException {return null;} + public IIOMetadata getImageMetadata(int imageIndex) + throws IOException {return null;} + } +} diff --git a/test/javax/imageio/ImageStreamFromRAF.java b/test/javax/imageio/ImageStreamFromRAF.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageStreamFromRAF.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001, 2017, 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 4395378 + * @summary Checks that ImageIO.createImageInputStream and + * createImageOutputStream produce correct output when given a + * RandomAccessFile + */ + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; + +import javax.imageio.ImageIO; +import javax.imageio.stream.FileImageInputStream; +import javax.imageio.stream.FileImageOutputStream; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class ImageStreamFromRAF { + + public static void main(String[] args) { + try { + File f = new File("ImageInputStreamFromRAF.tmp"); + RandomAccessFile raf = new RandomAccessFile(f, "rw"); + ImageInputStream istream = ImageIO.createImageInputStream(raf); + ImageOutputStream ostream = ImageIO.createImageOutputStream(raf); + f.delete(); + if (istream == null) { + throw new RuntimeException("ImageIO.createImageInputStream(RandomAccessFile) returned null!"); + } + if (ostream == null) { + throw new RuntimeException("ImageIO.createImageOutputStream(RandomAccessFile) returned null!"); + } + if (!(istream instanceof FileImageInputStream)) { + throw new RuntimeException("ImageIO.createImageInputStream(RandomAccessFile) did not return a FileImageInputStream!"); + } + if (!(ostream instanceof FileImageOutputStream)) { + throw new RuntimeException("ImageIO.createImageOutputStream(RandomAccessFile) did not return a FileImageOutputStream!"); + } + } catch (IOException ioe) { + throw new RuntimeException("Unexpected IOException: " + ioe); + } + } +} diff --git a/test/javax/imageio/ImageTypeSpecifierBitsPerBand.java b/test/javax/imageio/ImageTypeSpecifierBitsPerBand.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageTypeSpecifierBitsPerBand.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2000, 2017, 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 4392669 + * @summary Checks contract of ImageTypeSpecifier.getBitsPerBand + */ + +import java.awt.image.BufferedImage; + +import javax.imageio.ImageTypeSpecifier; + +public class ImageTypeSpecifierBitsPerBand { + + public static void main(String[] args) { + int biType = BufferedImage.TYPE_USHORT_565_RGB; + ImageTypeSpecifier type = + ImageTypeSpecifier.createFromBufferedImageType(biType); + + int b0 = type.getBitsPerBand(0); + int b1 = type.getBitsPerBand(1); + int b2 = type.getBitsPerBand(2); + + if (b0 != 5 || b1 != 6 || b2 != 5) { + throw new RuntimeException("Got incorrect bits per band value!"); + } + + boolean gotIAE = false; + try { + int b3 = type.getBitsPerBand(3); + } catch (IllegalArgumentException e) { + gotIAE = true; + } + if (!gotIAE) { + throw new RuntimeException + ("Failed to get IllegalArgumentException for band == 3!"); + } + } +} diff --git a/test/javax/imageio/ImageTypeSpecifierTest.java b/test/javax/imageio/ImageTypeSpecifierTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageTypeSpecifierTest.java @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2001, 2017, 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 4429934 4429950 4430991 4430993 + * @summary Checks various aspects of ImageTypeSpecifier functionality + */ + +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.SampleModel; + +import javax.imageio.ImageTypeSpecifier; + +public class ImageTypeSpecifierTest { + + private static void fail(String message) { + throw new RuntimeException(message); + } + + private static void test4429934() { + try { + ImageTypeSpecifier itspecifier = + new ImageTypeSpecifier(null, null); + fail("Failed to get IAE!"); + } catch( IllegalArgumentException e ) { + } + + try { + ImageTypeSpecifier itspecifier = new ImageTypeSpecifier(null); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e ) { + } + } + + private static void test4429950() { + createPackedTest(); + createInterleavedTest(); + createBandedTest(); + createIndexedTest(); + } + + public static void createPackedTest() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int rmask = 0x00ff0000; + int gmask = 0x0000ff00; + int bmask = 0x000000ff; + int amask = 0xff000000; + try { + ImageTypeSpecifier.createPacked(null, rmask, gmask, bmask, amask, 0, +false); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + ColorSpace cs1 = ColorSpace.getInstance(ColorSpace.CS_GRAY); + try { + ImageTypeSpecifier.createPacked + (cs1, rmask, gmask, bmask, amask, 0, false); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createPacked(cs, 0, 0, 0, 0, 0, false); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createPacked(cs, rmask, gmask, bmask, amask, -1, +false); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + public static void createInterleavedTest() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] bandOffsets = {0,0,0,0}; + int dataType = 0; + boolean hasAlpha = true; + boolean isAlphaPremultiplied = true; + + try { + ImageTypeSpecifier.createInterleaved + (null, bandOffsets, dataType, hasAlpha, isAlphaPremultiplied); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createInterleaved + (cs, null, dataType, hasAlpha, isAlphaPremultiplied); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + int[] bad_bandOffsets = {0,100,1000}; + try { + ImageTypeSpecifier.createInterleaved + (cs, bad_bandOffsets, dataType, hasAlpha, isAlphaPremultiplied); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + int[] bad_bandOffsets_1 = {}; + try { + ImageTypeSpecifier.createInterleaved + (cs, bad_bandOffsets_1, dataType, hasAlpha, isAlphaPremultiplied); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + public static void createBandedTest() { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] bankIndices = {0, 100, 1000, 10000}; + int[] bandOffsets = {0, 100, 1000, 10000}; + int dataType = 0; + boolean hasAlpha = true; + boolean isAlphaPremultiplied = true; + + try { + ImageTypeSpecifier.createBanded(null, bankIndices, bandOffsets, + dataType, hasAlpha, isAlphaPremultiplied); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + int[] bad_bankIndices = {}; + int[] bad_bandOffsets = {}; + try { + ImageTypeSpecifier.createBanded(cs, bad_bankIndices, bad_bandOffsets, + dataType, hasAlpha, isAlphaPremultiplied); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createBanded(cs, bankIndices, bandOffsets, + 99999, hasAlpha, isAlphaPremultiplied); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + public static void createGrayscaleTest() { + int bits = 8; + int dataType = DataBuffer.TYPE_BYTE; + boolean isSigned = true; + // testcase 1 + try { + ImageTypeSpecifier.createGrayscale(100, dataType, isSigned); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createGrayscale(10, dataType, isSigned); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createGrayscale(bits, 100, isSigned); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + public static void createIndexedTest() { + byte[] redLUT = {0}; + byte[] greenLUT = {0}; + byte[] blueLUT = {0}; + byte[] alphaLUT = {0}; + int bits = 8; + int dataType = DataBuffer.TYPE_BYTE; + + try { + ImageTypeSpecifier.createIndexed(redLUT, greenLUT, + blueLUT, alphaLUT, 0, dataType); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createIndexed(redLUT, greenLUT, + blueLUT, alphaLUT, 17, dataType); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createIndexed(redLUT, greenLUT, + blueLUT, alphaLUT, 10, dataType); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + byte[] greenLUT_4 = {}; + try { + ImageTypeSpecifier.createIndexed(redLUT, greenLUT_4, + blueLUT, alphaLUT, bits, dataType); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + byte[] redLUT_5 = {}; + try { + ImageTypeSpecifier.createIndexed(redLUT_5, greenLUT, + blueLUT, alphaLUT, bits, dataType); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + byte[] alphaLUT_6 = {}; + try { + ImageTypeSpecifier.createIndexed(redLUT, greenLUT, + blueLUT, alphaLUT_6 , bits, dataType); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + ImageTypeSpecifier.createIndexed(redLUT, greenLUT, + blueLUT, alphaLUT , bits, 100); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + private static void test4430991() { + ImageTypeSpecifier itspecifier; + + itspecifier = ImageTypeSpecifier.createFromBufferedImageType + (BufferedImage.TYPE_INT_RGB); + + try { + itspecifier.createBufferedImage(Integer.MAX_VALUE, + Integer.MAX_VALUE); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + + try { + itspecifier.getSampleModel(Integer.MAX_VALUE, Integer.MAX_VALUE); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + private static void test4430993() { + ImageTypeSpecifier itspecifier; + + int bits = 32; + int rmask = 0x00ff0000; + int gmask = 0x0000ff00; + int bmask = 0x000000ff; + ColorModel dcm = new java.awt.image.DirectColorModel + (bits, rmask, gmask, bmask); + int[] bandOffsets = new int[2]; + bandOffsets[1] = 1; + SampleModel sm = new java.awt.image.ComponentSampleModel + (DataBuffer.TYPE_SHORT, 1, 1, 2, 2, bandOffsets); + + try { + itspecifier = new ImageTypeSpecifier(dcm, sm); + fail("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + public static void main(String[] args) { + try { + test4429934(); + test4429950(); + test4430991(); + test4430993(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Unexpected exception: " + e); + } + } +} diff --git a/test/javax/imageio/ImageWriteParamMisc.java b/test/javax/imageio/ImageWriteParamMisc.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ImageWriteParamMisc.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2001, 2017, 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 4434870 4434886 4441315 4446842 + * @summary Checks that miscellaneous ImageWriteParam methods work properly + */ + +import java.awt.Dimension; + +import javax.imageio.ImageWriteParam; + +public class ImageWriteParamMisc { + + public static void main(String[] args) { + test4434870(); + test4434886(); + test4441315(); + test4446842(); + } + + public static class ImageWriteParam4434870 extends ImageWriteParam { + public ImageWriteParam4434870() { + super(null); + super.canWriteTiles = true; + super.preferredTileSizes = + new Dimension[] {new Dimension(1, 2), new Dimension(5, 6)}; + } + } + + private static void test4434870() { + ImageWriteParam iwp = new ImageWriteParam4434870(); + try { + Dimension[] dimensions = iwp.getPreferredTileSizes(); + iwp.setTilingMode(ImageWriteParam.MODE_EXPLICIT); + iwp.setTiling(100, 100, 0,0); + throw new RuntimeException("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + public static class ImageWriteParam4434886 extends ImageWriteParam { + public ImageWriteParam4434886() { + super(null); + super.canWriteTiles = true; + super.canOffsetTiles = true; + } + } + + private static void test4434886() { + ImageWriteParam iwp = new ImageWriteParam4434886(); + iwp.setTilingMode(ImageWriteParam.MODE_EXPLICIT); + try { + iwp.setTiling(-1,-2,-3,-4); + throw new RuntimeException("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + public static class ImageWriteParam4441315 extends ImageWriteParam { + public ImageWriteParam4441315() { + super(null); + super.canWriteProgressive = true; + } + } + + private static void test4441315() { + ImageWriteParam iwp = new ImageWriteParam4441315(); + try { + iwp.setProgressiveMode(ImageWriteParam.MODE_EXPLICIT); + throw new RuntimeException("Failed to get IAE!"); + } catch (IllegalArgumentException e) { + } + } + + private static void test4446842() { + ImageWriteParam iwp = new ImageWriteParam(null); + try { + iwp.getCompressionTypes(); + throw new RuntimeException("Failed to get UOE!"); + } catch (UnsupportedOperationException e) { + } + } +} diff --git a/test/javax/imageio/NullInputOutput.java b/test/javax/imageio/NullInputOutput.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/NullInputOutput.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2003, 2017, 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 4892682 4892698 + * @summary Tests that the appropriate IllegalStateException is thrown if + * ImageReader.read() or ImageWriter.write() is called without having + * first set the input/output stream + */ + +import java.awt.image.BufferedImage; +import java.util.Iterator; + +import javax.imageio.ImageReader; +import javax.imageio.ImageWriter; +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.spi.ImageWriterSpi; + +public class NullInputOutput { + + public static void main(String[] args) throws Exception { + IIORegistry registry = IIORegistry.getDefaultInstance(); + + // test ImageReader.read() for all available ImageReaders + Iterator readerspis = registry.getServiceProviders(ImageReaderSpi.class, + false); + while (readerspis.hasNext()) { + ImageReaderSpi readerspi = (ImageReaderSpi)readerspis.next(); + ImageReader reader = readerspi.createReaderInstance(); + try { + reader.read(0); + } catch (IllegalStateException ise) { + // caught exception, everything's okay + } + } + + // test ImageWriter.write() for all available ImageWriters + BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + Iterator writerspis = registry.getServiceProviders(ImageWriterSpi.class, + false); + while (writerspis.hasNext()) { + ImageWriterSpi writerspi = (ImageWriterSpi)writerspis.next(); + ImageWriter writer = writerspi.createWriterInstance(); + try { + writer.write(bi); + } catch (IllegalStateException ise) { + // caught exception, everything's okay + } + } + } +} diff --git a/test/javax/imageio/PNGSpiStreamMetadata.java b/test/javax/imageio/PNGSpiStreamMetadata.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/PNGSpiStreamMetadata.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001, 2017, 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 4403355 + * @summary Checks that PNGImage{Reader,Writer}Spi.getStreamMetadataFormatNames + * and getNativeStreamMetadataFormatName return null + */ + +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.spi.ImageWriterSpi; + +import com.sun.imageio.plugins.png.PNGImageReaderSpi; +import com.sun.imageio.plugins.png.PNGImageWriterSpi; + +public class PNGSpiStreamMetadata { + + private static void fatal() { + throw new RuntimeException("Got a non-null stream metadata format!"); + } + + public static void main(String[] args) { + ImageReaderSpi rspi = new PNGImageReaderSpi(); + if (rspi.getNativeStreamMetadataFormatName() != null) { + fatal(); + } + if (rspi.isStandardStreamMetadataFormatSupported() != false) { + fatal(); + } + if (rspi.getExtraStreamMetadataFormatNames() != null) { + fatal(); + } + + ImageWriterSpi wspi = new PNGImageWriterSpi(); + if (wspi.getNativeStreamMetadataFormatName() != null) { + fatal(); + } + if (wspi.isStandardStreamMetadataFormatSupported() != false) { + fatal(); + } + if (wspi.getExtraStreamMetadataFormatNames() != null) { + fatal(); + } + } +} diff --git a/test/javax/imageio/PNGSuffixes.java b/test/javax/imageio/PNGSuffixes.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/PNGSuffixes.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000, 2017, 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 4394924 + * @summary Checks for spurious leading "." in PNG file suffixes + */ + +import com.sun.imageio.plugins.png.PNGImageWriterSpi; + +public class PNGSuffixes { + + public static void main(String[] args) { + String[] suffixes = new PNGImageWriterSpi().getFileSuffixes(); + for (int i = 0; i < suffixes.length; i++) { + if (suffixes[i].startsWith(".")) { + throw new RuntimeException("Found a \".\" in a suffix!"); + } + } + } +} diff --git a/test/javax/imageio/ReadBitsTest.java b/test/javax/imageio/ReadBitsTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/ReadBitsTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2017, 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 4416800 + * @summary Checks that ImageInputStreamImpl.readBit and readBits handle the bit + * offset correctly + */ + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.stream.FileCacheImageInputStream; +import javax.imageio.stream.ImageInputStream; + +public class ReadBitsTest { + public static void main(String[] args) throws IOException { + byte[] buffer = new byte[] {(byte)169, (byte)85}; // 10101001 01010101 + InputStream ins = new ByteArrayInputStream(buffer); + ImageInputStream in = new FileCacheImageInputStream(ins,null); + + if (in.getBitOffset() != 0) { + throw new RuntimeException("Initial bit offset != 0!"); + } + + int bit0 = in.readBit(); // 1 + if (bit0 != 1) { + throw new RuntimeException("First bit != 1"); + } + if (in.getBitOffset() != 1) { + throw new RuntimeException("Second bit offset != 1"); + } + + long bits1 = in.readBits(5); // 01010 = 10 + if (bits1 != 10) { + throw new RuntimeException("Bits 1-5 != 10 (= " + bits1 + ")"); + } + if (in.getBitOffset() != 6) { + throw new RuntimeException("Third bit offset != 6"); + } + + int bit1 = in.readBit(); // 0 + if (bit1 != 0) { + throw new RuntimeException("Bit 6 != 0"); + } + if (in.getBitOffset() != 7) { + throw new RuntimeException("Third bit offset != 7"); + } + + long bits2 = in.readBits(8); // 10101010 = 170 + if (bits2 != 170) { + throw new RuntimeException("Bits 7-14 != 170 (= " + bits2 + ")"); + } + if (in.getBitOffset() != 7) { + throw new RuntimeException("Fourth bit offset != 7"); + } + + int bit2 = in.readBit(); // 1 + if (bit2 != 1) { + throw new RuntimeException("Bit 15 != 1"); + } + if (in.getBitOffset() != 0) { + throw new RuntimeException("Fifth bit offset != 0"); + } + + in.close(); + } +} diff --git a/test/javax/imageio/SetOutput.java b/test/javax/imageio/SetOutput.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/SetOutput.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2001, 2017, 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 4414455 + * @summary Checks for NPE from ImageWriter.setOutput when the writer has no + * originating service provider + */ + +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +import com.sun.imageio.plugins.png.PNGImageWriter; + +public class SetOutput { + + public static void main(String[] args) throws IOException { + ImageWriter iw = new PNGImageWriter(null); + File f = File.createTempFile("imageio", "tmp"); + ImageOutputStream ios = ImageIO.createImageOutputStream(f); + try { + iw.setOutput(ios); + } catch (NullPointerException npe) { + f.delete(); + throw new RuntimeException("Got NullPointerException!"); + } + f.delete(); + } +} diff --git a/test/javax/imageio/WriteNullImageTest.java b/test/javax/imageio/WriteNullImageTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/WriteNullImageTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2003, 2017, 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 4954545 + * @summary This test verifies whether the ImageWriter implementations throw + * IllegalArgumentException when a null image is passed to the write + * method. This is tested for all the image writers available with the + * IIORegistry. + */ + +import java.io.FileOutputStream; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.stream.ImageOutputStream; + +public class WriteNullImageTest { + + public WriteNullImageTest() { + boolean testFailed = false; + String failMsg = "FAIL: IllegalArgumentException is not thrown by the " + + "ImageWriter when the image passed to the write() method is " + + "null, for the image formats: "; + + try { + IIORegistry reg = IIORegistry.getDefaultInstance(); + ImageWriter writer = null; + Iterator writerSpiIter = reg.getServiceProviders(ImageWriterSpi.class, true); + + while (writerSpiIter.hasNext()) { + ImageWriterSpi writerSpi = (ImageWriterSpi) writerSpiIter.next(); + writer = writerSpi.createWriterInstance(); + String names[] = writerSpi.getFormatNames(); + + FileOutputStream fos = new FileOutputStream("temp"); + ImageOutputStream ios = ImageIO.createImageOutputStream(fos); + writer.setOutput(ios); + + try { + writer.write(null, null, null); + } catch (IllegalArgumentException iae) { + System.out.println("PASS: Expected exception is thrown when null img is passed " + + "to the write method, for the image format: " + names[0]); + System.out.println("\n"); + } catch (Exception e) { + testFailed = true; + failMsg = failMsg + names[0] + ", "; + } + } + + } catch (Exception e) { + testFailed = true; + throw new RuntimeException("Test Failed. Exception thrown: " + e.toString()); + } + if (testFailed) { + failMsg = failMsg.substring(0, failMsg.lastIndexOf(",")); + throw new RuntimeException(failMsg); + } + } + + public static void main(String args[]) { + WriteNullImageTest test = new WriteNullImageTest(); + } +} diff --git a/test/javax/imageio/event/WriteProgressListenerTest.java b/test/javax/imageio/event/WriteProgressListenerTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/event/WriteProgressListenerTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001, 2017, 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 4420342 4421831 + * @summary Checks that IIOWriteProgressListener methods are called in proper + * sequence for the JPEG and PNG writers + */ + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Iterator; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.event.IIOWriteProgressListener; +import javax.imageio.stream.ImageOutputStream; + +public class WriteProgressListenerTest implements IIOWriteProgressListener { + + final static int UNINITIALIZED = 0; + final static int IMAGE_STARTED = 1; + final static int IMAGE_COMPLETE = 2; + + int state = UNINITIALIZED; + float prevPercentageDone = 0.0F; + File tempFile = null; + + public WriteProgressListenerTest(String format) throws IOException { + ImageWriter writer = null; + Iterator witer = ImageIO.getImageWritersByFormatName(format); + if (!witer.hasNext()) { + error("No writer for format " + format + "!"); + } + writer = (ImageWriter)witer.next(); + + System.out.println("Got writer " + writer); + writer.addIIOWriteProgressListener(this); + + this.tempFile = File.createTempFile("imageio", ".tmp"); + tempFile.deleteOnExit(); + ImageOutputStream stream = ImageIO.createImageOutputStream(tempFile); + writer.setOutput(stream); + + BufferedImage im = + new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR); + + this.state = UNINITIALIZED; + + writer.write(im); + + if (this.state == UNINITIALIZED) { + error("imageStarted never called!"); + } + if (this.state != IMAGE_COMPLETE) { + error("imageComplete not called!"); + } + + print("Passed!"); + } + + private void error(String s) { + if (tempFile != null) { + tempFile.delete(); + } + throw new RuntimeException(s); + } + + private void print(String s) { + System.out.println(s); + } + + public void sequenceStarted(ImageWriter source) { + error("Obsolete method sequenceStarted was called!"); + } + + public void sequenceComplete(ImageWriter source) { + error("Obsolete method sequenceComplete was called!"); + } + + public void imageStarted(ImageWriter source, int imageIndex) { + print("imageStarted: imageIndex = " + imageIndex); + + if (state != UNINITIALIZED) { + error("imageStarted not called first!"); + } + state = IMAGE_STARTED; + prevPercentageDone = 0.0F; + } + + public void imageProgress(ImageWriter source, + float percentageDone) { + print("imageProgress: percentageDone = " + percentageDone); + + if (state != IMAGE_STARTED) { + error("imageProgress called without prior imageStarted!"); + } + if (percentageDone < prevPercentageDone) { + error("percentageDone did not increase!"); + } + prevPercentageDone = percentageDone; + } + + public void imageComplete(ImageWriter source) { + print("imageComplete"); + + if (state != IMAGE_STARTED) { + error("imageComplete called without imageStarted!"); + } + if (prevPercentageDone == 0.0F) { + error("percentageDone was never updated!"); + } + state = IMAGE_COMPLETE; + } + + public void thumbnailStarted(ImageWriter source, + int imageIndex, int thumbnailIndex) { + } + + public void thumbnailProgress(ImageWriter source, float percentageDone) { + } + + public void thumbnailComplete(ImageWriter source) { + } + + public void writeAborted(ImageWriter source) { + } + + public static void main(String[] args) throws IOException { + new WriteProgressListenerTest("jpeg"); + new WriteProgressListenerTest("png"); + } +} diff --git a/test/javax/imageio/plugins/bmp/BMPCompressionTest.java b/test/javax/imageio/plugins/bmp/BMPCompressionTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/BMPCompressionTest.java @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2003, 2017, 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 4641872 + * @summary Tests writing compression modes of BMP plugin + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DirectColorModel; +import java.awt.image.IndexColorModel; +import java.awt.image.PixelInterleavedSampleModel; +import java.awt.image.Raster; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.WritableRaster; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.plugins.bmp.BMPImageWriteParam; +import javax.imageio.stream.ImageOutputStream; +import javax.swing.JComponent; +import javax.swing.JFrame; + +import com.sun.imageio.plugins.bmp.BMPMetadata; + +public class BMPCompressionTest { + + static final String format = "BMP"; + + public static void main(String[] args) { + + ImageWriter iw = null; + Iterator writers = ImageIO.getImageWritersByFormatName(format); + if (!writers.hasNext()) { + throw new RuntimeException("No available Image writer for "+format); + } + iw = (ImageWriter)writers.next(); + + + Iterator tests = Test.createTestSet(iw); + + while(tests.hasNext()) { + + Test t = (Test)tests.next(); + System.out.println(t.getDescription()); + t.doTest(); + } + + } + + + static class Test { + static ImageWriter iw; + private BufferedImage img; + private String description; + private BMPImageWriteParam param; + private IIOMetadata meta; + + + public static Iterator createTestSet(ImageWriter w) { + List l = new LinkedList(); + + Test.iw = w; + + // variate compression types + BMPImageWriteParam param = (BMPImageWriteParam)iw.getDefaultWriteParam(); + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionType("BI_RGB"); + if (param.canWriteCompressed()) { + String[] cTypes = param.getCompressionTypes(); + String[] cDescr = param.getCompressionQualityDescriptions(); + float[] cValues = param.getCompressionQualityValues(); + + if (cDescr == null) { + System.out.println("There are no compression quality description!"); + } else { + for(int i=0; i 0) { + format = args[0]; + System.out.println("Test format " + format); + } + + init(); + System.out.println("IR="+ir); + System.out.println("IW="+iw); + ImageIO.setUseCache(false); + + for (int i=0; i " + iw.toString()); + } + if (iw==null) { + throw new RuntimeException("No available Image writer for "+format); + } + ImageWriteParam param = iw.getDefaultWriteParam(); + + param.setSourceRegion(new Rectangle(10, 10, 31, 31)); + param.setSourceSubsampling(3, 3, 0, 0); + + IIOMetadata meta = iw.getDefaultImageMetadata(new ImageTypeSpecifier(img), param); + + IIOImage iio_img = new IIOImage(img, null, meta); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + iw.setOutput(ios); + iw.write(meta, iio_img, param); + ios.flush(); + + byte[] ba_image = baos.toByteArray(); + + ByteArrayInputStream bais = new ByteArrayInputStream(ba_image); + + ImageReader ir = null; + + Iterator readers = ImageIO.getImageReadersByFormatName(format); + while (readers.hasNext()) { + ir = (ImageReader)readers.next(); + System.out.println(format + " -> " + ir.toString()); + } + if (ir==null) { + throw new RuntimeException("No available Image reader for "+format); + } + + ir.setInput(ImageIO.createImageInputStream(bais)); + + BufferedImage res = ir.read(0); + return res; + } + + private static BufferedImage createTestImage() + throws IOException { + + int w = 50; + int h = 50; + BufferedImage b = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics2D g = b.createGraphics(); + g.setColor(Color.red); + g.fillRect(0,0, w, h); + g.setColor(Color.white); + for (int i=10; i<=10+30; i+= 3) { + g.drawLine(i, 10, i, 40); + g.drawLine(10, i, 40, i); + } + return b; + } + + private static boolean compare(final BufferedImage in, + final BufferedImage out) + { + final int width = in.getWidth(); + int height = in.getHeight(); + if (out.getWidth() != width || out.getHeight() != height) { + throw new RuntimeException("Dimensions changed!"); + } + + Raster oldras = in.getRaster(); + ColorModel oldcm = in.getColorModel(); + Raster newras = out.getRaster(); + ColorModel newcm = out.getColorModel(); + + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + Object oldpixel = oldras.getDataElements(i, j, null); + int oldrgb = oldcm.getRGB(oldpixel); + int oldalpha = oldcm.getAlpha(oldpixel); + + Object newpixel = newras.getDataElements(i, j, null); + int newrgb = newcm.getRGB(newpixel); + int newalpha = newcm.getAlpha(newpixel); + + if (newrgb != oldrgb || + newalpha != oldalpha) { + // showDiff(in, out); + throw new RuntimeException("Pixels differ at " + i + + ", " + j + " new = " + Integer.toHexString(newrgb) + " old = " + Integer.toHexString(oldrgb)); + } + } + } + return true; + } +} diff --git a/test/javax/imageio/plugins/bmp/BmpBigDestinationTest.java b/test/javax/imageio/plugins/bmp/BmpBigDestinationTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/BmpBigDestinationTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003, 2017, 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 4929367 + * @summary tests what BMP image was decoded correctly if destination buffered + * image is bigger than source image + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriter; + +public class BmpBigDestinationTest { + static String format = "BMP"; + public static void main(String[] args) { + try { + BufferedImage src = new BufferedImage(100, 100, + BufferedImage.TYPE_INT_RGB); + Graphics2D g = src.createGraphics(); + g.setColor(Color.red); + g.fillRect(0,0,100, 100); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + ImageWriter iw = + (ImageWriter)ImageIO.getImageWritersByFormatName(format).next(); + if (iw == null) { + throw new RuntimeException("No writer available. Test failed."); + } + + iw.setOutput(ImageIO.createImageOutputStream(baos)); + iw.write(src); + + byte[] data = baos.toByteArray(); + + ImageReader ir = + (ImageReader)ImageIO.getImageReadersByFormatName(format).next(); + ir.setInput( + ImageIO.createImageInputStream( + new ByteArrayInputStream(data))); + + Iterator specifiers = ir.getImageTypes(0); + ImageTypeSpecifier typeSpecifier = null; + + if (specifiers.hasNext()) { + typeSpecifier = (ImageTypeSpecifier) specifiers.next(); + } + ImageReadParam param = new ImageReadParam(); + BufferedImage dst = typeSpecifier.createBufferedImage(200, 200); + param.setDestination(dst); + + ir.read(0, param); + + checkResults(src,dst); + + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("Unexpected exception. Test failed."); + } + } + + private static void checkResults(BufferedImage src, BufferedImage dst) { + for(int x=0; x"); + indent(level); + System.out.println(node.getNodeValue()); + indent(level); // emit close tag + System.out.println(""); + } else if (child != null) { + System.out.println(">"); // close current tag + while (child != null) { // emit child tags recursively + displayMetadata(child, level + 1); + child = child.getNextSibling(); + } + indent(level); // emit close tag + System.out.println(""); + } else { + System.out.println("/>"); + } + } + + public static void main(String args[]) { + BmpDefaultImageMetadataTest test = new BmpDefaultImageMetadataTest("bmp"); + } +} diff --git a/test/javax/imageio/plugins/bmp/CompressionModeTest.java b/test/javax/imageio/plugins/bmp/CompressionModeTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/CompressionModeTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2003, 2017, 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 4893464 + * @summary Tests bmp writer behavior with different compression modes + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class CompressionModeTest { + + public static void main(String args[]) { + int[] iModes = { ImageWriteParam.MODE_DISABLED, + ImageWriteParam.MODE_EXPLICIT, + ImageWriteParam.MODE_COPY_FROM_METADATA, + ImageWriteParam.MODE_DEFAULT }; + + String[] strModes = { "ImageWriteParam.MODE_DISABLED", + "ImageWriteParam.MODE_EXPLICIT", + "ImageWriteParam.MODE_COPY_FROM_METADATA", + "ImageWriteParam.MODE_DEFAULT" }; + + for(int i=0; i tests = null; + private static Color[] usedColors = new Color[] { Color.red, Color.green, Color.blue, Color.yellow, Color.white, Color.black }; + + private static final int TYPE_INT_GRB = 0x100; + private static final int TYPE_INT_GBR = 0x101; + private static final int TYPE_INT_RBG = 0x102; + private static final int TYPE_INT_BRG = 0x103; + private static final int TYPE_INT_555_GRB = 0x104; + private static final int TYPE_3BYTE_RGB = 0x105; + private static final int TYPE_3BYTE_GRB = 0x106; + + private static final int w = 300; + private static final int h = 200; + private static final int dx = w / usedColors.length; + + public static void main(String[] args) throws IOException { + initTests(); + + for (Integer type : tests.keySet()) { + new NoExtraBytesTest(type.intValue(), tests.get(type).intValue()).doTest(); + } + System.out.println("Test passed."); + } + + private static void initTests() { + tests = new Hashtable(); + + tests.put(new Integer(BufferedImage.TYPE_INT_RGB), new Integer(24)); + tests.put(new Integer(BufferedImage.TYPE_INT_BGR), new Integer(24)); + tests.put(new Integer(BufferedImage.TYPE_3BYTE_BGR), new Integer(24)); + tests.put(new Integer(TYPE_INT_GRB), new Integer(24)); + tests.put(new Integer(TYPE_INT_GBR), new Integer(24)); + tests.put(new Integer(TYPE_INT_RBG), new Integer(24)); + tests.put(new Integer(TYPE_INT_BRG), new Integer(24)); + tests.put(new Integer(BufferedImage.TYPE_USHORT_555_RGB), new Integer(16)); + tests.put(new Integer(BufferedImage.TYPE_USHORT_565_RGB), new Integer(16)); + tests.put(new Integer(TYPE_INT_555_GRB), new Integer(16)); + tests.put(new Integer(TYPE_3BYTE_RGB), new Integer(24)); + tests.put(new Integer(TYPE_3BYTE_GRB), new Integer(24)); + } + + private static String getImageTypeName(int t) { + switch(t) { + case BufferedImage.TYPE_INT_RGB: + return "TYPE_INT_RGB"; + case BufferedImage.TYPE_INT_BGR: + return "TYPE_INT_BGR"; + case BufferedImage.TYPE_3BYTE_BGR: + return "TYPE_3BYTE_BGR"; + case BufferedImage.TYPE_USHORT_555_RGB: + return "TYPE_USHORT_555_RGB"; + case BufferedImage.TYPE_USHORT_565_RGB: + return "TYPE_USHORT_565_RGB"; + case TYPE_INT_GRB: + return "TYPE_INT_GRB"; + case TYPE_INT_GBR: + return "TYPE_INT_GBR"; + case TYPE_INT_RBG: + return "TYPE_INT_RBG"; + case TYPE_INT_BRG: + return "TYPE_INT_BRG"; + case TYPE_INT_555_GRB: + return "TYPE_INT_555_GRB"; + case TYPE_3BYTE_RGB: + return "TYPE_3BYTE_RGB"; + case TYPE_3BYTE_GRB: + return "TYPE_3BYTE_GRB"; + default: + throw new IllegalArgumentException("Unknown image type: " + t); + } + } + private static BufferedImage createTestImage(int type) { + BufferedImage dst = null; + ColorModel colorModel = null; + WritableRaster raster = null; + ColorSpace cs = null; + System.out.println("Create image for " + getImageTypeName(type)); + switch(type) { + case TYPE_INT_GRB: + colorModel = new DirectColorModel(24, + 0x0000ff00, + 0x00ff0000, + 0x000000ff); + break; + case TYPE_INT_GBR: + colorModel = new DirectColorModel(24, + 0x000000ff, + 0x00ff0000, + 0x0000ff00); + break; + case TYPE_INT_RBG: + colorModel = new DirectColorModel(24, + 0x00ff0000, + 0x000000ff, + 0x0000ff00); + break; + case TYPE_INT_BRG: + colorModel = new DirectColorModel(24, + 0x0000ff00, + 0x000000ff, + 0x00ff0000); + break; + case TYPE_INT_555_GRB: + colorModel = new DirectColorModel(24, + 0x0000001F, + 0x000003e0, + 0x00007c00); + break; + case TYPE_3BYTE_RGB: + cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + int[] nBits = {8, 8, 8}; + int[] bOffs = {0, 1, 2}; + colorModel = new ComponentColorModel(cs, nBits, false, false, + Transparency.OPAQUE, + DataBuffer.TYPE_BYTE); + raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + w, h, + w*3, 3, + bOffs, null); + break; + case TYPE_3BYTE_GRB: + cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + //nBits = {8, 8, 8}; + //bOffs = {0, 1, 2}; + colorModel = new ComponentColorModel(cs, new int[] { 8, 8, 8 }, false, false, + Transparency.OPAQUE, + DataBuffer.TYPE_BYTE); + raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + w, h, + w*3, 3, + new int[] { 1, 0, 2}, null); + break; + default: + dst = new BufferedImage(w, h, type); + //colorModel = ImageTypeSpecifier.createFromBufferedImageType(type).getColorModel(); + } + + if (dst == null) { + if (raster == null) { + raster = colorModel.createCompatibleWritableRaster(w, h); + } + + dst = new BufferedImage(colorModel, raster, false, null); + } + Graphics g = dst.createGraphics(); + for (int i = 0; i < usedColors.length; i ++) { + g.setColor(usedColors[i]); + g.fillRect(i * dx, 0, dx, h); + } + g.dispose(); + + return dst; + } + + private BufferedImage src; + private int expectedColorDepth; + private int type; + + private IIOImage iio_dst; + + public NoExtraBytesTest(int type, int expectedColorDepth) { + this.type = type; + this.src = createTestImage(type); + this.expectedColorDepth = expectedColorDepth; + } + + public void doTest() throws IOException { + // write src as BMP + System.out.println("Test for image: " + getImageTypeName(type)); + System.out.println("image is " + src); + + File f = File.createTempFile("sizeTest_", ".bmp", new File(".")); + System.out.println("Use file " + f.getCanonicalPath()); + ImageIO.write(src, "BMP", f); + + //read it again + read(f); + + checkColorDepth(); + + checkImageContent(); + } + + private void read(File f) throws IOException { + ImageReader reader = ImageIO.getImageReadersByFormatName("BMP").next(); + + ImageInputStream iis = + ImageIO.createImageInputStream(new FileInputStream(f)); + + reader.setInput(iis); + + iio_dst = reader.readAll(0, reader.getDefaultReadParam()); + } + + private void checkColorDepth() { + IIOMetadata dst = iio_dst.getMetadata(); + + Node data = dst.getAsTree("javax_imageio_bmp_1.0"); + + Node n = data.getFirstChild(); + + while (n != null && !("BitsPerPixel".equals(n.getNodeName()))) { + System.out.println("Node " + n.getNodeName()); + n = n.getNextSibling(); + } + if (n == null) { + throw new RuntimeException("No BitsPerSample node!"); + } + + int bpp = 0; + String value = n.getNodeValue(); + System.out.println("value = " + value); + try { + bpp = Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new RuntimeException("Wrong bpp value: " + value, e); + } + + if (bpp != this.expectedColorDepth) { + throw new RuntimeException("Wrong color depth: " + bpp + + " (should be " + this.expectedColorDepth + ")"); + } + } + + private void checkImageContent() { + BufferedImage dst = + (BufferedImage)iio_dst.getRenderedImage(); + int y = h / 2; + int x = dx / 2; + + for (int i = 0; i < usedColors.length; i++, x += dx) { + int srcRgb = src.getRGB(x, y); + int dstRgb = dst.getRGB(x, y); + int rgb = usedColors[i].getRGB(); + + if (dstRgb != srcRgb || dstRgb != rgb) { + throw new RuntimeException("Wrong color at [" + x + ", " + y + + "] " + Integer.toHexString(dstRgb) + + " (srcRgb=" + Integer.toHexString(srcRgb) + + ", original color is " + Integer.toHexString(rgb) + ")"); + } + + } + System.out.println("Image colors are OK."); + } +} diff --git a/test/javax/imageio/plugins/bmp/RLECompressionTest.java b/test/javax/imageio/plugins/bmp/RLECompressionTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/RLECompressionTest.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2005, 2017, 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 6332480 + * @summary Test verifies that images encoded as BMP with RLE4 or RLE8 + * compression type are read correctly + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +public class RLECompressionTest { + public static final int TEST_RLE8 = 0x01; + public static final int TEST_RLE4 = 0x02; + + private static Color[] usedColors = new Color[] { + Color.black, Color.white, Color.red, + Color.green, Color.blue, Color.yellow }; + + int w = 100; + // NB: problem occurs when image height > width + // The problem manifestation is that only first w + // lines of image are filled by decoded data, + // rest of image (all lines below (w-1)-th line) + // is leaved uninitialized (black). + // In order to verify that this problem is solved, + // we use image with height > width. + int h = 2 * w; + + private IndexColorModel getTestColorModel(int type) { + IndexColorModel icm = null; + int bpp = 8; + int size = 256; + + switch(type) { + case TEST_RLE8: + bpp = 8; + size = 256; + break; + case TEST_RLE4: + bpp = 4; + size = 16; + break; + default: + throw new IllegalArgumentException("Wrong test type: " + type); + } + + byte[] palette = new byte[size * 3]; + for (int i = 0; i < usedColors.length; i++) { + palette[3 * i] = (byte)(0xff & usedColors[i].getRed()); + palette[3 * i + 1] = (byte)(0xff & usedColors[i].getGreen()); + palette[3 * i + 2] = (byte)(0xff & usedColors[i].getBlue()); + } + // rest of palette is black + + icm = new IndexColorModel(bpp, size, palette, 0, false); + return icm; + } + + private BufferedImage getTestImage(int type) { + BufferedImage src = null; + IndexColorModel icm = getTestColorModel(type); + src = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED, icm); + Graphics2D g = src.createGraphics(); + g.setColor(Color.white); + g.fillRect(0, 0, w, h); + g.dispose(); + + return src; + } + + public void doTest(int type) throws IOException { + BufferedImage src = getTestImage(type); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + + ImageWriter writer = ImageIO.getImageWritersByFormatName("BMP").next(); + writer.setOutput(ios); + + ImageWriteParam wparam = writer.getDefaultWriteParam(); + wparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + switch(type) { + case TEST_RLE8: + wparam.setCompressionType("BI_RLE8"); + break; + case TEST_RLE4: + wparam.setCompressionType("BI_RLE4"); + break; + default: + throw new IllegalArgumentException("Wrong test type: " + type); + } + + writer.write(null, new IIOImage(src, null, null), wparam); + + ios.close(); + baos.close(); + + // read result + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + BufferedImage dst = ImageIO.read(bais); + + checkResult(src, dst); + } + + private void checkResult(BufferedImage src, BufferedImage dst) { + int x = w / 2; + for (int y = 0; y < h; y++) { + int srcRgb = src.getRGB(x, y); + int dstRgb = dst.getRGB(x, y); + + if (srcRgb != dstRgb) { + throw new RuntimeException("Test failed due to color difference: " + + Integer.toHexString(dstRgb) + " instead of " + Integer.toHexString(srcRgb) + + " at [" + x + ", " + y + "]"); + } + } + } + + public static void main(String[] args) throws IOException { + RLECompressionTest test = new RLECompressionTest(); + test.doTest(TEST_RLE8); + test.doTest(TEST_RLE4); + } +} diff --git a/test/javax/imageio/plugins/bmp/ReaderListenersTest.java b/test/javax/imageio/plugins/bmp/ReaderListenersTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/ReaderListenersTest.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2003, 2017, 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 4924507 + * @summary Test that listeners of bmp reader receive correct events in case of + * BI_JPEG and BI_PNG compression types + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.event.IIOReadProgressListener; +import javax.imageio.event.IIOReadUpdateListener; + +public class ReaderListenersTest { + public static final String[] compTypes = { "BI_JPEG", "BI_PNG" }; + + public static void main(String[] args) { + for (int i=0; i< compTypes.length; i++) { + doTest(compTypes[i]); + } + } + + private static void doTest(String compression) { + try { + BufferedImage img = createTestImage(); + + ImageWriter iw = (ImageWriter) + ImageIO.getImageWritersByFormatName("bmp").next(); + if (iw == null) { + throw new RuntimeException("No writers for bmp format." + + " Test failed."); + } + + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + iw.setOutput(ImageIO.createImageOutputStream(baos)); + ImageWriteParam param = iw.getDefaultWriteParam(); + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionType(compression); + + iw.write(null, new IIOImage(img, null, null), param); + baos.close(); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + ImageReader ir = (ImageReader) + ImageIO.getImageReadersByFormatName("bmp").next(); + if (ir == null) { + throw new RuntimeException("No readers for bmp format." + + " Test failed."); + } + + IIOReadUpdateAdapter updateAdapter = new IIOReadUpdateAdapter(); + IIOReadProgressAdapter progressAdapter = new IIOReadProgressAdapter(); + ir.addIIOReadProgressListener(progressAdapter); + ir.addIIOReadUpdateListener(updateAdapter); + ir.setInput(ImageIO.createImageInputStream(bais)); + BufferedImage dst = ir.read(0); + + progressAdapter.checkResults(); + + if (!updateAdapter.isImageUpdateUsed) { + throw new RuntimeException("imageUpdate was not used." + + " Test failed."); + } + } catch(IOException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed"); + } + } + + protected static BufferedImage createTestImage() { + BufferedImage res = new BufferedImage(100, 100, + BufferedImage.TYPE_INT_RGB); + Graphics2D g = res.createGraphics(); + g.setColor(Color.red); + g.fillRect(0,0, 100,100); + return res; + } + + static class IIOReadProgressAdapter implements IIOReadProgressListener { + List progress = new ArrayList(); + public boolean isTestPassed = false; + private boolean isImageStarted = false; + private boolean isImageComplete = false; + private boolean isSequenceComplete = false; + private boolean isSequenceStarted = false; + + public void imageComplete(ImageReader source) { + System.out.println("Image completed"); + if (!isImageComplete) { + isImageComplete = true; + } else { + throw new RuntimeException("The imageComplete() is called twice." + + " Test failed."); + } + checkProgress(); + } + + public void imageProgress(ImageReader source, float percentageDone) { + System.out.println("Image Progress "+percentageDone); + progress.add(new Float(percentageDone)); + } + + public void imageStarted(ImageReader source, int imageIndex) { + System.out.println("Image Started "+imageIndex); + if (!isImageStarted) { + isImageStarted = true; + } else { + throw new RuntimeException("The imageStarted() was called twice. " + + " Test failed."); + } + progress.clear(); + } + + public void thumbnailComplete(ImageReader source) { + System.out.println("Thubnail completed"); + } + + public void thumbnailProgress(ImageReader source, + float percentageDone) + { + System.out.println("Thubnail Progress " + percentageDone); + } + + public void thumbnailStarted(ImageReader source, + int imageIndex, int thumbnailIndex) + { + System.out.println("Thubnail started " + imageIndex); + } + + public void sequenceComplete(ImageReader source) { + if (!isSequenceComplete) { + isSequenceComplete = true; + } else { + throw new RuntimeException("The imageComplete() is called twice." + + " Test failed."); + } + } + + public void sequenceStarted(ImageReader source, int minIndex) { + if (!isSequenceStarted) { + isSequenceStarted = true; + } else { + throw new RuntimeException("The imageComplete() is called twice." + + " Test failed."); + } + } + + public void readAborted(ImageReader source) { + System.out.println("read Aborted"); + checkProgress(); + } + + private void checkProgress() { + Iterator i = progress.iterator(); + if (!i.hasNext()) { + throw new RuntimeException("progress values list is empty!"); + } + float val = ((Float)i.next()).floatValue(); + while(i.hasNext()) { + float next = ((Float)i.next()).floatValue(); + if (val >= next) { + throw new RuntimeException("progress values do not increase!"); + } + val = next; + } + isTestPassed = true; + System.out.println("Test passed."); + } + + public void checkResults() { + if (isImageStarted && !isImageComplete) { + throw new RuntimeException("The imageCompleted was not called." + + " Test failed."); + } + } + } + + static class IIOReadUpdateAdapter implements IIOReadUpdateListener { + boolean isImageUpdateUsed = false; + public void imageUpdate(ImageReader source, BufferedImage theImage, + int minX, int minY, int width, int height, + int periodX, int periodY, int[] bands) + { + System.out.println("imageUpdate"); + isImageUpdateUsed = true; + } + public void passComplete(ImageReader source, BufferedImage theImage) { + System.out.println("passComplete"); + } + public void passStarted(ImageReader source, BufferedImage theImage, + int pass, int minPass, int maxPass, + int minX, int minY, int periodX, int periodY, + int[] bands) + { + System.out.println("passStarted"); + } + public void thumbnailPassComplete(ImageReader source, + BufferedImage theThumbnail) + { + System.out.println("thumbnailPassComplete"); + } + public void thumbnailPassStarted(ImageReader source, + BufferedImage theThumbnail, + int pass, int minPass, int maxPass, + int minX, int minY, + int periodX, int periodY, + int[] bands) + { + System.out.println("thumbnailPassStarted"); + } + public void thumbnailUpdate(ImageReader source, + BufferedImage theThumbnail, + int minX, int minY, + int width, int height, + int periodX, int periodY, int[] bands) + { + System.out.println("thumbnailUpdate"); + } + } +} diff --git a/test/javax/imageio/plugins/bmp/RleEncodingTest.java b/test/javax/imageio/plugins/bmp/RleEncodingTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/RleEncodingTest.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2003, 2017, 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 4893446 + * @summary Tests that we get IOException if we try to encode the incompatible + * image with RLE compression + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class RleEncodingTest { + + private static int testIdx = 1; + + public static void main(String args[]) throws Exception { + try { + int mode = ImageWriteParam.MODE_EXPLICIT; + String type = "BI_RLE4"; + doTest(type, mode); + + type = "BI_RLE8"; + doTest(type, mode); + + mode = ImageWriteParam.MODE_DEFAULT; + type = "BI_RLE4"; + doTest(type, mode); + + type = "BI_RLE8"; + doTest(type, mode); + + System.out.println("Test 4bpp image."); + encodeRLE4Test(); + + System.out.println("Test 8bpp image."); + encodeRLE8Test(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("Unexpected exception. Test failed"); + } + } + + private static void doTest(String compressionType, + int compressionMode) throws IOException + { + BufferedImage bimg = new BufferedImage(100, 100, + BufferedImage.TYPE_INT_RGB); + Graphics g = bimg.getGraphics(); + g.setColor(Color.green); + g.fillRect(0, 0, 100, 100); + + doTest(bimg, compressionType, compressionMode); + } + + private static void encodeRLE4Test() throws IOException { + // create 4bpp image + byte[] r = new byte[16]; + r[0] = (byte)0xff; + byte[] g = new byte[16]; + g[1] = (byte)0xff; + byte[] b = new byte[16]; + b[2] = (byte)0xff; + IndexColorModel icm = new IndexColorModel(4, 16, r, g, b); + + BufferedImage bimg = new BufferedImage(100, 100, + BufferedImage.TYPE_BYTE_BINARY, + icm); + + Graphics gr = bimg.getGraphics(); + gr.setColor(Color.green); + gr.fillRect(0, 0, 100, 100); + + doTest(bimg, "BI_RLE4", ImageWriteParam.MODE_EXPLICIT); + } + + private static void encodeRLE8Test() throws IOException { + // create 8bpp image + byte[] r = new byte[256]; + r[0] = (byte)0xff; + byte[] g = new byte[256]; + g[1] = (byte)0xff; + byte[] b = new byte[256]; + b[2] = (byte)0xff; + IndexColorModel icm = new IndexColorModel(8, 256, r, g, b); + + BufferedImage bimg = new BufferedImage(100, 100, + BufferedImage.TYPE_BYTE_INDEXED, + icm); + Graphics gr = bimg.getGraphics(); + gr.setColor(Color.green); + gr.fillRect(0, 0, 100, 100); + + doTest(bimg, "BI_RLE8", ImageWriteParam.MODE_EXPLICIT); + } + + private static void doTest(BufferedImage src, + String compressionType, + int compressionMode) throws IOException + { + + ImageWriter iw = (ImageWriter)ImageIO.getImageWritersBySuffix("bmp").next(); + if (iw == null) { + throw new RuntimeException("No available writer. Test failed."); + } + + IIOImage iioImg = new IIOImage(src, null, null); + ImageWriteParam param = iw.getDefaultWriteParam(); + + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + iw.setOutput(ios); + + System.out.println("Compression Type is " + compressionType); + System.out.println("Compression Mode is " + compressionMode); + + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionType(compressionType); + if (compressionMode != ImageWriteParam.MODE_EXPLICIT) { + param.setCompressionMode(compressionMode); + } + try { + iw.write(null, iioImg, param); + } catch (IOException e) { + int bpp = src.getColorModel().getPixelSize(); + if (compressionMode == ImageWriteParam.MODE_EXPLICIT) { + if ((compressionType.equals("BI_RLE4") && bpp != 4) + || (compressionType.equals("BI_RLE8") && bpp != 8)) + { + System.out.println("Can not encode "+ bpp+ "bpp image as" + + compressionType); + return; + } else { + throw new RuntimeException("Unable to encode " + + bpp + "bpp image as " + + compressionType + + ". Test failed"); + } + } + } + baos.close(); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ImageInputStream iis = ImageIO.createImageInputStream(bais); + + BufferedImage dst = ImageIO.read(iis); + + int w = src.getWidth(); + int h = src.getHeight(); + + Object dstPixel = dst.getRaster().getDataElements(w/2, h/2, null); + Object srcPixel = src.getRaster().getDataElements(w/2, h/2, null); + + if ( (src.getColorModel().getRed(srcPixel) + != dst.getColorModel().getRed(dstPixel)) + || (src.getColorModel().getGreen(srcPixel) + != dst.getColorModel().getGreen(dstPixel)) + || (src.getColorModel().getBlue(srcPixel) + != dst.getColorModel().getBlue(dstPixel)) + || (src.getColorModel().getAlpha(srcPixel) + != dst.getColorModel().getAlpha(dstPixel)) ) { + + showPixel(src, w/2, h/2); + showPixel(dst, w/2, h/2); + + throw new RuntimeException( + "Colors are different: " + + Integer.toHexString(src.getColorModel().getRGB(srcPixel)) + + " and " + + Integer.toHexString(dst.getColorModel().getRGB(dstPixel))); + } + + } + + private static void showPixel(BufferedImage src, int x, int y) { + System.out.println("Img is " + src); + Object p = src.getRaster().getDataElements(x, y, null); + System.out.println("RGB: " + + Integer.toHexString(src.getColorModel().getRGB(p))); + System.out.println("Red: " + + Integer.toHexString(src.getColorModel().getRed(p))); + System.out.println("Green: " + + Integer.toHexString(src.getColorModel().getGreen(p))); + System.out.println("Blue: " + + Integer.toHexString(src.getColorModel().getBlue(p))); + System.out.println("Alpha: " + + Integer.toHexString(src.getColorModel().getAlpha(p))); + } +} diff --git a/test/javax/imageio/plugins/bmp/TestCompressionBI_BITFIELDS.java b/test/javax/imageio/plugins/bmp/TestCompressionBI_BITFIELDS.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/TestCompressionBI_BITFIELDS.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2005, 2017, 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 6297016 6294960 6294965 6294984 + * @summary Test verifies that buffered images are written correctly if + * compression BI_BITFIELDS is used + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; + +public class TestCompressionBI_BITFIELDS { + + protected String format = "BMP"; + + protected ImageReader reader; + + protected ImageWriter writer; + + protected boolean doSave = true; + + Color[] colors = { + Color.red, Color.green, Color.blue, + Color.yellow, Color.white, Color.black}; + + int dx = 50; + int h = 200; + + public TestCompressionBI_BITFIELDS() { + this("BMP"); + } + + public TestCompressionBI_BITFIELDS(String format) { + this.format = format; + reader = ImageIO.getImageReadersByFormatName(format).next(); + writer = ImageIO.getImageWritersByFormatName(format).next(); + } + + protected ImageWriteParam prepareWriteParam(BufferedImage src) { + ImageWriteParam wparam = writer.getDefaultWriteParam(); + wparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + wparam.setCompressionType("BI_BITFIELDS"); + + return wparam; + } + + public BufferedImage writeAndRead(BufferedImage src) throws IOException { + writer.reset(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + writer.setOutput(ImageIO.createImageOutputStream(baos)); + + ImageWriteParam wparam = prepareWriteParam(src); + + IIOImage img = new IIOImage(src, null, null); + + writer.write(null, img, wparam); + + if (doSave) { + // save images to file in order to be able to check + // that image is well-formed using standard windows tools. + File f = File.createTempFile("wr_test_", "." + format, new File(".")); + System.out.println("Save to file: " + f.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(f); + fos.write(baos.toByteArray()); + fos.flush(); + fos.close(); + } + + // read result + reader.reset(); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + reader.setInput(ImageIO.createImageInputStream(bais)); + + return reader.read(0); + } + + public static void main(String[] args) throws IOException { + // buffered image types listed below can be saved as BI_BITFIELDS BMP + int[] types = {BufferedImage.TYPE_3BYTE_BGR, + BufferedImage.TYPE_USHORT_555_RGB, + BufferedImage.TYPE_USHORT_565_RGB, + BufferedImage.TYPE_BYTE_GRAY, + BufferedImage.TYPE_BYTE_BINARY, + BufferedImage.TYPE_BYTE_INDEXED, + BufferedImage.TYPE_INT_BGR, + BufferedImage.TYPE_INT_RGB}; + + for (int i = 0; i < types.length; i++) { + System.out.println("Test image " + types[i]); + TestCompressionBI_BITFIELDS t = new TestCompressionBI_BITFIELDS(); + + BufferedImage src = + t.createTestImage(types[i]); + System.out.println("Image for test: " + src); + System.out.println("SampleModel: " + src.getSampleModel()); + + BufferedImage dst = null; + try { + dst = t.writeAndRead(src); + } catch (IOException e) { + e.printStackTrace(System.out); + } + + + t.compareImages(src, dst); + } + } + + protected BufferedImage createTestImage(int type) { + BufferedImage bimg = new BufferedImage(dx * colors.length, h, type); + Graphics2D g = bimg.createGraphics(); + + for (int i = 0; i < colors.length; i++) { + g.setColor(colors[i]); + g.fillRect(dx * i, 0, dx, h); + } + return bimg; + } + + protected void compareImages(BufferedImage src, BufferedImage dst) { + ColorSpace srcCS = src.getColorModel().getColorSpace(); + ColorSpace dstCS = dst.getColorModel().getColorSpace(); + if (!srcCS.equals(dstCS) && srcCS.getType() == ColorSpace.TYPE_GRAY) { + System.out.println("Workaround color difference with GRAY."); + BufferedImage tmp = + new BufferedImage(src.getWidth(), src.getHeight(), + BufferedImage.TYPE_INT_RGB); + Graphics g = tmp.createGraphics(); + g.drawImage(src, 0, 0, null); + src = tmp; + } + int y = h / 2; + for (int i = 0; i < colors.length; i++) { + int x = dx * i + dx / 2; + int srcRgb = src.getRGB(x, y); + int dstRgb = dst.getRGB(x, y); + + if (srcRgb != dstRgb) { + throw new RuntimeException("Test failed due to color difference: " + + "src_pixel=" + Integer.toHexString(srcRgb) + + "dst_pixel=" + Integer.toHexString(dstRgb)); + } + } + } +} diff --git a/test/javax/imageio/plugins/bmp/Write3ByteBgrTest.java b/test/javax/imageio/plugins/bmp/Write3ByteBgrTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/Write3ByteBgrTest.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2003, 2017, 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 4892194 8014427 + * @summary Test checks that we able to encode TYPE_3BYTE_BGR images to bmp + * format. Test failed if ArrayIndexOutOfBoundsException will be thrown + * or pixel colors will be changed by the writing/reading. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; +import javax.swing.JComponent; +import javax.swing.JFrame; + +public class Write3ByteBgrTest { + private static int width = 100; + private static int height = 100; + private static Color color = new Color(0x10, 0x20, 0x30); + + static int bufferedImageType[] = { + BufferedImage.TYPE_CUSTOM, + BufferedImage.TYPE_BYTE_BINARY, + BufferedImage.TYPE_3BYTE_BGR + }; + + static String bufferedImageStringType[] = { + "BufferedImage.TYPE_CUSTOM: test for BandedSampleModel", + "BufferedImage.TYPE_BYTE_BINARY", + "BufferedImage.TYPE_3BYTE_BGR" + }; + + private static String writingFormat = "BMP"; + private static ImageWriter writer = (ImageWriter)ImageIO.getImageWritersByFormatName(writingFormat).next(); + private int type; + + public static void main(String[] args) { + + //int i = 0; + for(int i=0; i= next) { + throw new RuntimeException("progress values do not increase!"); + } + val = next; + } + isTestPassed = true; + System.out.println("Test passed."); + } + } + +} diff --git a/test/javax/imageio/plugins/bmp/WritingColorChangeTest.java b/test/javax/imageio/plugins/bmp/WritingColorChangeTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/bmp/WritingColorChangeTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2003, 2017, 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 4892214 + * @summary Test checks that colors are not changed by the writing/reading in + * the BMP format for TYPE_INT_BGR and TYPE_USHORT_555_RGB buffered + * images + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; +import javax.swing.JComponent; +import javax.swing.JFrame; + +public class WritingColorChangeTest { + private static int width = 100; + private static int height = 100; + private static Color color = new Color(0x10, 0x20, 0x30); + + static int bufferedImageType[] = { + BufferedImage.TYPE_USHORT_565_RGB, + BufferedImage.TYPE_INT_BGR, + BufferedImage.TYPE_INT_RGB, + BufferedImage.TYPE_USHORT_555_RGB, + }; + + static String bufferedImageStringType[] = { + "BufferedImage.TYPE_USHORT_565_RGB", + "BufferedImage.TYPE_INT_BGR", + "BufferedImage.TYPE_INT_RGB", + "BufferedImage.TYPE_USHORT_555_RGB", + }; + private static String writingFormat = "BMP"; + private static ImageWriter writer = (ImageWriter)ImageIO.getImageWritersByFormatName(writingFormat).next(); + private int type; + + public static void main(String[] args) { + + //int i = 7; //3; //7; + for(int i=0; i 0) { + int x = rnd.nextInt(w); + int y = rnd.nextInt(h); + + int pSrc = src.getRGB(x, y); + int pDst = src.getRGB(x, y); + + if (pSrc != pDst) { + throw new RuntimeException("Images are different"); + } + } + } + + public static void main(String[] args) { + IndexingTest t = new IndexingTest(); + t.doTest(); + } +} diff --git a/test/javax/imageio/plugins/gif/LogicalScreenDimensionTest.java b/test/javax/imageio/plugins/gif/LogicalScreenDimensionTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/LogicalScreenDimensionTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2005, 2017, 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 6307618 + * @summary Test verifies that GIF image writer updates the dimension of the + * logical screen according to image dimension + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +import com.sun.imageio.plugins.gif.GIFStreamMetadata; + +public class LogicalScreenDimensionTest { + public static void main(String[] args) throws IOException { + String format = "GIF"; + ImageWriter writer = + ImageIO.getImageWritersByFormatName(format).next(); + if (writer == null) { + throw new RuntimeException("No available writers for " + format); + } + + BufferedImage img = createTestImage(100, 100, BufferedImage.TYPE_BYTE_GRAY); + + ImageWriteParam p = writer.getDefaultWriteParam(); + ImageTypeSpecifier type = + ImageTypeSpecifier.createFromRenderedImage(img); + IIOMetadata inImageMetadata = + writer.getDefaultImageMetadata(type, p); + + IIOMetadata inStreamMetadata = writer.getDefaultStreamMetadata(p); + + // write and read image + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + writer.setOutput(ios); + + writer.write(inStreamMetadata, new IIOImage(img, null, inImageMetadata), p); + + ios.flush(); + ios.close(); + + // read result + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ImageInputStream iis = ImageIO.createImageInputStream(bais); + ImageReader reader = ImageIO.getImageReader(writer); + reader.setInput(iis); + + IIOMetadata outStreamMetadata = reader.getStreamMetadata(); + + GIFStreamMetadata gifStreamMetadata = (GIFStreamMetadata)outStreamMetadata; + + if (gifStreamMetadata.logicalScreenWidth != img.getWidth() || + gifStreamMetadata.logicalScreenHeight != img.getHeight()) { + throw new RuntimeException("Test failed due to wrong logical screen dimension."); + } + } + + private static BufferedImage createTestImage(int w, int h, int type) { + BufferedImage res = new BufferedImage(w, h, type); + Graphics2D g = res.createGraphics(); + g.setColor(Color.white); + g.fillRect(0, 0, w, h); + g.setColor(Color.black); + g.fillRect(w/4, h/4, w/2, h/2); + + + return res; + } +} diff --git a/test/javax/imageio/plugins/gif/OddPaletteTest.java b/test/javax/imageio/plugins/gif/OddPaletteTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/OddPaletteTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2005, 2017, 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 6275211 6276621 + * @summary Tests that GIF writer plugin is able to write indexed images if + * palette size is not a power of two + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +public class OddPaletteTest { + + private static int w = 100; + private static int h = 100; + + public static void main(String[] args) { + BufferedImage[] srcs = new BufferedImage[2]; + srcs[0] = createTestImage(7); // bug 6275211 + srcs[1] = createTestImage(1); // bug 6276621 + + for (int i = 0; i < srcs.length; i++) { + doTest(srcs[i]); + } + } + + private static void doTest(BufferedImage src) { + ImageWriter w = ImageIO.getImageWritersByFormatName("GIF").next(); + if (w == null) { + throw new RuntimeException("No writer available!"); + } + + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + w.setOutput(ios); + w.write(src); + } catch (IOException e) { + throw new RuntimeException("Test failed.", e); + } catch (IllegalArgumentException e) { + throw new RuntimeException("Test failed.", e); + } + } + + private static BufferedImage createTestImage(int paletteSize) { + byte[] r = new byte[paletteSize]; + byte[] g = new byte[paletteSize]; + byte[] b = new byte[paletteSize]; + + int shift = 256 / paletteSize; + for (int i = 0; i < paletteSize; i++) { + r[i] = g[i] = b[i] = (byte)(shift * i); + } + + int numBits = getNumBits(paletteSize); + + System.out.println("num of bits " + numBits); + + IndexColorModel icm = + new IndexColorModel(numBits, paletteSize, r, g, b); + + BufferedImage img = new BufferedImage(w, h, + BufferedImage.TYPE_BYTE_INDEXED, + icm); + Graphics2D g2d = img.createGraphics(); + g2d.setColor(Color.white); + g2d.fillRect(0, 0, w, h); + g2d.setColor(Color.black); + g2d.drawLine(0, 0, w, h); + g2d.drawLine(0, h, w, 0); + + return img; + } + + private static int getNumBits(int paletteSize) { + if (paletteSize < 0) { + throw new IllegalArgumentException("negative palette size: " + + paletteSize); + } + if (paletteSize < 2) { + return 1; + } + int numBits = 0; + + paletteSize--; + + while (paletteSize > 0) { + numBits++; + paletteSize = paletteSize >> 1; + } + return numBits; + } +} diff --git a/test/javax/imageio/plugins/gif/PrepareWriteSequenceTest.java b/test/javax/imageio/plugins/gif/PrepareWriteSequenceTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/PrepareWriteSequenceTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2005, 2017, 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 6284538 + * @summary Test verifies whether IllegalStateException is thrown if the output + * stream have not set to the GIF image writer instance + */ + +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; + +public class PrepareWriteSequenceTest { + public static void main(String[] args) throws IOException { + String format = "GIF"; + ImageWriter writer = ImageIO.getImageWritersByFormatName(format).next(); + + ImageWriteParam param = writer.getDefaultWriteParam(); + + IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(param); + + boolean gotException = false; + try { + writer.prepareWriteSequence(streamMetadata); + } catch (IllegalStateException e) { + gotException = true; + System.out.println("Test passed."); + e.printStackTrace(System.out); + } + + if (!gotException) { + throw new RuntimeException("Test failed."); + } + } +} diff --git a/test/javax/imageio/plugins/gif/RGBAnimationTest.java b/test/javax/imageio/plugins/gif/RGBAnimationTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/RGBAnimationTest.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2005, 2017, 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 6324581 + * @summary Test verifies that RGB images are written to animated GIF image use + * local color table if image palette is not equals to the global color + * table + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +import com.sun.imageio.plugins.gif.GIFImageMetadata; + +public class RGBAnimationTest { + protected static String format = "GIF"; + protected static boolean doSave = true; + + Frame[] frames; + ImageWriter writer; + ImageReader reader; + + public static void main(String[] args) throws IOException { + RGBAnimationTest test = new RGBAnimationTest(); + test.doTest(); + } + /** Creates a new instance of RGBAnimationTest */ + public RGBAnimationTest() { + frames = new Frame[4]; + + + frames[0] = new Frame(new Color[] {Color.red, Color.green}); + frames[1] = new Frame(new Color[] {Color.green, Color.cyan}); + frames[2] = new Frame(new Color[] {Color.cyan, Color.yellow}); + frames[3] = new Frame(new Color[] {Color.yellow, Color.red}); + + writer = ImageIO.getImageWritersByFormatName(format).next(); + reader = ImageIO.getImageReadersByFormatName(format).next(); + } + + public void doTest() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + writer.reset(); + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + writer.setOutput(ios); + + ImageWriteParam wparam = prepareWriteParam(); + + IIOMetadata streamMetadata = prepareStreamMetadata(wparam); + + writer.prepareWriteSequence(streamMetadata); + + for (int i = 0; i < frames.length; i++) { + BufferedImage src = frames[i].getImage(); + IIOMetadata imageMetadata = prepareImageMetadata(i, src, wparam); + IIOImage img = new IIOImage(src, null, imageMetadata); + + writer.writeToSequence(img, wparam); + } + writer.endWriteSequence(); + ios.flush(); + ios.close(); + + if (doSave) { + File f = File.createTempFile("wr_test_", "." + format, new File(".")); + System.out.println("Save to file: " + f.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(f); + fos.write(baos.toByteArray()); + fos.flush(); + fos.close(); + } + // read result + reader.reset(); + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + reader.setInput(ImageIO.createImageInputStream(bais)); + + int minIndex = reader.getMinIndex(); + int numImages = reader.getNumImages(true); + + for (int i = 0; i < numImages; i++) { + BufferedImage dst = reader.read(i + minIndex); + frames[i].checkResult(dst); + } + } + + protected IIOMetadata prepareImageMetadata(int i, BufferedImage img, ImageWriteParam wparam) { + GIFImageMetadata idata = (GIFImageMetadata) + writer.getDefaultImageMetadata(ImageTypeSpecifier.createFromRenderedImage(img), wparam); + + idata.delayTime = 100; + idata.disposalMethod = 0; + idata.transparentColorFlag = false; + + if (i == 0) { + ArrayList appIDs = new ArrayList(); + appIDs.add(new String("NETSCAPE").getBytes()); + ArrayList authCodes = new ArrayList(); + authCodes.add(new String("2.0").getBytes()); + ArrayList appData = new ArrayList(); + byte[] authData = {1, 0, 0}; + appData.add(authData); + + idata.applicationIDs = appIDs; + idata.authenticationCodes = authCodes; + idata.applicationData = appData; + } + return idata; + } + + protected ImageWriteParam prepareWriteParam() { + return writer.getDefaultWriteParam(); + } + + protected IIOMetadata prepareStreamMetadata(ImageWriteParam wparam) { + return writer.getDefaultStreamMetadata(wparam); + } + +} + +class Frame { + protected static int type = BufferedImage.TYPE_INT_RGB; + protected static int dx = 100; + protected static int h = 100; + + protected Color[] colors; + protected BufferedImage img; + + public Frame(Color[] colors) { + this.colors = colors; + img = null; + } + + public BufferedImage getImage() { + if (img == null) { + img = new BufferedImage(dx * colors.length, h, type); + Graphics2D g = img.createGraphics(); + for (int i = 0; i < colors.length; i++) { + g.setColor(colors[i]); + g.fillRect(dx * i, 0, dx, h); + } + } + return img; + } + + public void checkResult(BufferedImage dst) { + int y = h / 2; + int x = dx / 2; + for (int i = 0; i < colors.length; i++) { + + int srcRgb = img.getRGB(i * dx + x, y); + int dstRgb = dst.getRGB(i * dx + x, y); + + if (srcRgb != dstRgb) { + throw new RuntimeException("Test failed due to color difference: " + + Integer.toHexString(dstRgb) + " instead of " + + Integer.toHexString(srcRgb)); + } + } + } +} diff --git a/test/javax/imageio/plugins/gif/RGBImageTest.java b/test/javax/imageio/plugins/gif/RGBImageTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/RGBImageTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2005, 2017, 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 6286578 + * @summary Test verifies that RGB images does not convert to gray-scaled if + * default image metadata is used + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class RGBImageTest { + + Color[] usedColors = { + Color.red, Color.green, Color.blue, Color.yellow, + Color.cyan, Color.magenta, Color.white, Color.black }; + + BufferedImage src = null; + int dx= 20; + int height = 100; + + protected BufferedImage getSrc() { + if (src == null) { + src = new BufferedImage(dx * usedColors.length, height, + BufferedImage.TYPE_INT_RGB); + Graphics g = src.createGraphics(); + for (int i = 0; i < usedColors.length; i++) { + g.setColor(usedColors[i]); + g.fillRect(dx * i, 0, dx, height); + } + } + return src; + } + + protected void doTest() throws IOException { + BufferedImage biSrc = getSrc(); + + ImageWriter writer = ImageIO.getImageWritersByFormatName("GIF").next(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + writer.setOutput(ios); + + ImageWriteParam writeParam = writer.getDefaultWriteParam(); + IIOMetadata imageMetadata = + writer.getDefaultImageMetadata(new ImageTypeSpecifier(biSrc), writeParam); + + IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(writeParam); + + IIOImage iioImg = new IIOImage(biSrc, null, imageMetadata); + writer.write(streamMetadata, iioImg, writeParam); + ios.close(); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ImageInputStream iis = ImageIO.createImageInputStream(bais); + ImageReader reader = ImageIO.getImageReader(writer); + reader.setInput(iis); + BufferedImage dst = reader.read(0); + + // do test + int x = dx / 2; + int y = height / 2; + + for (int i = 0; i < usedColors.length; i++) { + int dstRgb = dst.getRGB(x, y); + System.out.println("dstColor: " + Integer.toHexString(dstRgb)); + int srcRgb = usedColors[i].getRGB(); + System.out.println("srcColor: " + Integer.toHexString(srcRgb)); + if (dstRgb != srcRgb) { + throw new RuntimeException("wrong color " + i + ": " + Integer.toHexString(dstRgb)); + } + x += dx; + } + + } + + public static void main(String[] args) throws IOException { + RGBImageTest t = new RGBImageTest(); + t.doTest(); + } +} diff --git a/test/javax/imageio/plugins/gif/StreamMetadataTest.java b/test/javax/imageio/plugins/gif/StreamMetadataTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/StreamMetadataTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005, 2017, 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 6319418 + * @summary Test verifies that GIF stream metadata could be merged with tree + * representation for all supported formats + */ + +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOInvalidTreeException; +import javax.imageio.metadata.IIOMetadata; + +import org.w3c.dom.Node; + +public class StreamMetadataTest { + protected static final String format = "GIF"; + + ImageWriter writer = null; + IIOMetadata streamData = null; + ImageWriteParam wparam = null; + boolean doMerge = true; + + public StreamMetadataTest() { + writer = ImageIO.getImageWritersByFormatName(format).next(); + wparam = writer.getDefaultWriteParam(); + streamData = writer.getDefaultStreamMetadata(wparam); + } + + public void doTest() throws IIOInvalidTreeException { + if (streamData == null) { + throw new RuntimeException("No stream metadata available"); + } + + String[] formatNames = streamData.getMetadataFormatNames(); + for(String fname : formatNames) { + System.out.println("Format name: " + fname); + Node root = streamData.getAsTree(fname); + if (streamData.isReadOnly()) { + throw new RuntimeException("Stream metadata is readonly!"); + } + streamData.reset(); + streamData.mergeTree(fname, root); + } + } + + public static void main(String args[]) { + StreamMetadataTest test = new StreamMetadataTest(); + try { + test.doTest(); + } catch (Exception e) { + throw new RuntimeException("Test failed.", e); + } + } +} diff --git a/test/javax/imageio/plugins/gif/TransparencyTest.java b/test/javax/imageio/plugins/gif/TransparencyTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/TransparencyTest.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2005, 2017, 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 4339415 + * @summary Tests that GIF writer plugin is able to write images with BITMASK + * transparency + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.awt.image.WritableRaster; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; + +public class TransparencyTest { + + protected static final String fname = "ttest.gif"; + protected BufferedImage src; + protected BufferedImage dst; + + public static void main(String[] args) { + System.out.println("Test indexed image..."); + IndexColorModel icm = createIndexedBitmaskColorModel(); + BufferedImage img = createIndexedImage(200, 200, icm); + TransparencyTest t = new TransparencyTest(img); + + try { + t.doTest(); + } catch (Exception e) { + throw new RuntimeException("Test failed!", e); + } + System.out.println("Test passed."); + } + + protected TransparencyTest(BufferedImage src) { + this.src = src; + } + + protected void doTest() throws IOException { + int w = src.getWidth(); + int h = src.getHeight(); + + System.out.println("Write image..."); + try { + ImageWriter writer = + ImageIO.getImageWritersByFormatName("GIF").next(); + writer.setOutput(ImageIO.createImageOutputStream(new File(fname))); + writer.write(src); + } catch (Exception e) { + throw new RuntimeException("Test failed.", e); + } + System.out.println("Read image...."); + dst = ImageIO.read(new File(fname)); + + BufferedImage tmp = new BufferedImage(w, 2 * h, + BufferedImage.TYPE_INT_ARGB); + Graphics2D g = tmp.createGraphics(); + g.setColor(Color.pink); + g.fillRect(0, 0, tmp.getWidth(), tmp.getHeight()); + + g.drawImage(src, 0, 0, null); + g.drawImage(dst, 0, h, null); + + int width = w / 8; + int x = 5 * width + width / 2; + for (int y = 0; y < h; y++) { + int argb = tmp.getRGB(x, y); + if (Color.pink.getRGB() != argb) { + throw new RuntimeException("Bad color at " + x + "," + y + + " - " + Integer.toHexString(argb)); + } + } + } + + protected static BufferedImage createIndexedImage(int w, int h, + IndexColorModel icm) + { + BufferedImage img = new BufferedImage(w, h, + BufferedImage.TYPE_BYTE_INDEXED, + icm); + + int mapSize = icm.getMapSize(); + int width = w / mapSize; + + WritableRaster wr = img.getRaster(); + for (int i = 0; i < mapSize; i++) { + for (int y = 0; y < h; y++) { + for (int x = 0; x < width; x++) { + wr.setSample(i * width + x, y, 0, i); + } + } + } + return img; + } + + protected static IndexColorModel createIndexedBitmaskColorModel() { + int paletteSize = 8; + byte[] red = new byte[paletteSize]; + byte[] green = new byte[paletteSize]; + byte[] blue = new byte[paletteSize]; + + red[0] = (byte)0xff; green[0] = (byte)0x00; blue[0] = (byte)0x00; + red[1] = (byte)0x00; green[1] = (byte)0xff; blue[1] = (byte)0x00; + red[2] = (byte)0x00; green[2] = (byte)0x00; blue[2] = (byte)0xff; + red[3] = (byte)0xff; green[3] = (byte)0xff; blue[3] = (byte)0xff; + red[4] = (byte)0x00; green[4] = (byte)0x00; blue[4] = (byte)0x00; + red[5] = (byte)0x80; green[5] = (byte)0x80; blue[5] = (byte)0x80; + red[6] = (byte)0xff; green[6] = (byte)0xff; blue[6] = (byte)0x00; + red[7] = (byte)0x00; green[7] = (byte)0xff; blue[7] = (byte)0xff; + + int numBits = 3; + + IndexColorModel icm = new IndexColorModel(numBits, paletteSize, + red, green, blue, 5); + + return icm; + } +} diff --git a/test/javax/imageio/plugins/gif/UshortOutOfMemoryTest.java b/test/javax/imageio/plugins/gif/UshortOutOfMemoryTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/UshortOutOfMemoryTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2005, 2017, 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 6294363 + * @summary Test verifies that creation of tree representation of the native + * image metadata for USHORT_GRAY images does not cause the + * OutOfMemoryError + * @run main/othervm -Xms32M -Xmx32M UshortOutOfMemoryTest + */ + +import java.awt.image.BufferedImage; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; + +public class UshortOutOfMemoryTest { + private int type; + private ImageWriter w; + + public UshortOutOfMemoryTest(int type) { + this.type = type; + w = ImageIO.getImageWritersByFormatName("GIF").next(); + } + + public void testGetAsTree() { + ImageWriteParam p = w.getDefaultWriteParam(); + IIOMetadata m = + w.getDefaultImageMetadata(ImageTypeSpecifier.createFromBufferedImageType(type), p); + + String format = m.getNativeMetadataFormatName(); + System.out.println("native format: " + format); + + int count = 0; + try { + while (count < 100) { + System.out.println(" test " + count++); + m.getAsTree(format); + } + } catch (OutOfMemoryError e) { + System.gc(); + throw new RuntimeException("Test failed. Number of performed operations: " + count, e); + } + } + + + public static void main(String[] args) throws IOException { + UshortOutOfMemoryTest t = new UshortOutOfMemoryTest( + BufferedImage.TYPE_USHORT_GRAY); + t.testGetAsTree(); + } +} diff --git a/test/javax/imageio/plugins/gif/WriteMetadataTest.java b/test/javax/imageio/plugins/gif/WriteMetadataTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/WriteMetadataTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2005, 2017, 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 6287880 + * @summary Test verifies that default metadata for stream and image returned by + * GIFImageWriter can be modified by the tree representation + */ + +import java.awt.image.BufferedImage; + +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOInvalidTreeException; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.metadata.IIOMetadataNode; + +public class WriteMetadataTest { + private static String format = "GIF"; + + public static void main(String[] args) { + ImageWriter w = ImageIO.getImageWritersByFormatName(format).next(); + if (w == null) { + throw new RuntimeException("No available writers for format " + format); + } + ImageWriteParam p = w.getDefaultWriteParam(); + + ImageTypeSpecifier t = + ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB); + + IIOMetadata m = w.getDefaultImageMetadata(t, p); + System.out.println("Default image metadata is " + m); + testWritableMetadata(m); + + IIOMetadata sm = w.getDefaultStreamMetadata(p); + System.out.println("Default stream metadata is " + sm); + testWritableMetadata(sm); + } + + public static void testWritableMetadata(IIOMetadata m) { + String nativeFormatName = + m.getNativeMetadataFormatName(); + System.out.println("Format: " + nativeFormatName); + IIOMetadataNode root = (IIOMetadataNode)m.getAsTree(nativeFormatName); + if (m.isReadOnly()) { + throw new RuntimeException("Metadata is read only!"); + } + try { + m.setFromTree(nativeFormatName, root); + } catch (IIOInvalidTreeException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed!", e); + } catch (IllegalStateException e) { + throw new RuntimeException("Test failed!", e); + } + System.out.println("Test passed.\n\n"); + } +} diff --git a/test/javax/imageio/plugins/gif/WriterResetTest.java b/test/javax/imageio/plugins/gif/WriterResetTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/WriterResetTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2005, 2017, 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 6275251 + * @summary Verifies that GIF image writer throws IllegalStateException if + * assigned output stream was cleared by reset() method + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +public class WriterResetTest { + public static void main(String[] args) throws IOException { + ImageWriter w = ImageIO.getImageWritersByFormatName("GIF").next(); + if (w == null) { + throw new RuntimeException("No writers available!"); + } + + ByteArrayOutputStream baos = + new ByteArrayOutputStream(); + + ImageOutputStream ios = + ImageIO.createImageOutputStream(baos); + + w.setOutput(ios); + + BufferedImage img = createTestImage(); + + try { + w.reset(); + w.write(img); + } catch (IllegalStateException e) { + System.out.println("Test passed"); + } catch (Throwable e) { + throw new RuntimeException("Test failed", e); + } + } + + private static BufferedImage createTestImage() { + BufferedImage img = new BufferedImage(100, 100, + BufferedImage.TYPE_INT_RGB); + Graphics2D g = img.createGraphics(); + g.setColor(Color.white); + g.fillRect(0, 0, 100, 100); + g.setColor(Color.black); + g.fillRect(20, 20, 60, 60); + + return img; + } +} diff --git a/test/javax/imageio/plugins/gif/WriterReuseTest.java b/test/javax/imageio/plugins/gif/WriterReuseTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/gif/WriterReuseTest.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2005, 2017, 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 6283089 + * @summary Test verifies that abort flag is cleared by the next write() call + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.event.IIOWriteProgressListener; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class WriterReuseTest implements IIOWriteProgressListener { + + boolean isFirst = true; + boolean isWritingCompleted = false; + boolean isWritingAborted = false; + + public static void main(String[] args) throws IOException { + doTest(false); + doTest(true); + } + + public static void doTest(boolean writeSequence) throws IOException { + String format = "GIF"; + ImageWriter writer = + ImageIO.getImageWritersByFormatName(format).next(); + if (writer == null) { + throw new RuntimeException("No writer available for " + format); + } + + BufferedImage img = createTestImage(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + writer.setOutput(ios); + + WriterReuseTest t = new WriterReuseTest(); + writer.addIIOWriteProgressListener(t); + + ImageWriteParam param = writer.getDefaultWriteParam(); + IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(param); + IIOImage iioImg = new IIOImage(img, null, null); + if (writeSequence) { + writer.prepareWriteSequence(streamMetadata); + writer.writeToSequence(iioImg, param); + } else { + writer.write(img); + } + + if (!t.isWritingAborted || t.isWritingCompleted) { + throw new RuntimeException("Test failed."); + } + t.reset(); + + // next attempt after abort + ImageOutputStream ios2 = + ImageIO.createImageOutputStream(new ByteArrayOutputStream()); + writer.setOutput(ios2); + if (writeSequence) { + writer.writeToSequence(iioImg, param); + } else { + writer.write(img); + } + + if (t.isWritingAborted || !t.isWritingCompleted) { + throw new RuntimeException("Test failed."); + } + System.out.println("Test passed."); + } + + public static BufferedImage createTestImage() { + BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_INDEXED); + Graphics g = img.createGraphics(); + g.setColor(Color.black); + g.fillRect(0, 0, 100, 100); + + g.setColor(Color.white); + g.fillRect(10, 10, 80, 80); + + return img; + } + + public WriterReuseTest() { + isFirst = true; + reset(); + } + + public void reset() { + isWritingAborted = false; + isWritingCompleted = false; + } + + public void imageComplete(ImageWriter source) { + System.out.println("Image Completed"); + this.isWritingCompleted = true; + } + + public void imageProgress(ImageWriter source, float percentageDone) { + System.out.println("Image Progress "+percentageDone); + if (percentageDone > 50 && isFirst) { + isFirst = false; + source.abort(); + } + } + + public void imageStarted(ImageWriter source, int imageIndex) { + System.out.println("Image Started "+imageIndex); + } + + public void thumbnailComplete(ImageWriter source) { + System.out.println("Thubnail completed"); + } + + public void thumbnailProgress(ImageWriter source, float percentageDone) { + System.out.println("Thubnail Progress " + percentageDone); + } + + public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) { + System.out.println("Thubnail started " + imageIndex); + } + + public void writeAborted(ImageWriter source) { + System.out.println("Writing Aborted"); + this.isWritingAborted = true; + } +} diff --git a/test/javax/imageio/plugins/jpeg/ByteBinaryTest.java b/test/javax/imageio/plugins/jpeg/ByteBinaryTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/jpeg/ByteBinaryTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002, 2017, 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 4450894 + * @summary Tests if the JPEG writer properly encodes IndexColorModel images + * that contain less than 8-bit indices (such as TYPE_BYTE_BINARY) + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; + +public class ByteBinaryTest { + + private static final int[] expectedVals = + { 0xffffffff, 0xff000000, 0xffffffff }; + + public static void main(String[] args) { + BufferedImage bi = new BufferedImage(100, 100, + BufferedImage.TYPE_BYTE_BINARY); + + Graphics g = bi.createGraphics(); + g.setColor(Color.white); + g.fillRect(0, 0, 100, 100); + g.setColor(Color.black); + g.fillRect(20, 20, 40, 40); + g.setColor(Color.white); + g.fillRect(25, 25, 25, 25); + g.dispose(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + boolean success; + + try { + success = ImageIO.write(bi, "jpeg", baos); + } catch (IOException ioe) { + throw new RuntimeException("Could not write JPEG to stream"); + } + + if (!success) { + throw new RuntimeException("Could not find valid JPEG writer..."); + } + + byte[] bytearr = baos.toByteArray(); + ByteArrayInputStream bais = new ByteArrayInputStream(bytearr); + BufferedImage bi2 = null; + + try { + bi2 = ImageIO.read(bais); + } catch (IOException ioe) { + throw new RuntimeException("Could not read JPEG stream"); + } + + int[] actualVals = new int[3]; + + actualVals[0] = bi2.getRGB(27, 5); + actualVals[1] = bi2.getRGB(27, 22); + actualVals[2] = bi2.getRGB(35, 35); + + for (int i = 0; i < actualVals.length; i++) { + if (actualVals[i] != expectedVals[i]) { + throw new RuntimeException("Pixel mismatch at index: " + i); + } + } + } +} diff --git a/test/javax/imageio/plugins/jpeg/CanEncodeIndexed.java b/test/javax/imageio/plugins/jpeg/CanEncodeIndexed.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/jpeg/CanEncodeIndexed.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2002, 2017, 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 4528585 + * @summary Tests whether the JPEGImageWriterSpi advertises that it is capable + * of writing images using an IndexColorModel. The test fails if an + * exception is thrown. + */ + +import java.awt.image.BufferedImage; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; + +public class CanEncodeIndexed { + + public static void main(String[] args) { + BufferedImage img = new BufferedImage(32, 32, + BufferedImage.TYPE_BYTE_INDEXED); + + ImageTypeSpecifier spec = + ImageTypeSpecifier.createFromRenderedImage(img); + + Iterator writers = ImageIO.getImageWriters(spec, "jpeg"); + + if (!writers.hasNext()) { + throw new RuntimeException("Test failed: " + + "no JPEG writer found for " + + "image with IndexColorModel"); + } + } +} diff --git a/test/javax/imageio/plugins/jpeg/CompressionBug.java b/test/javax/imageio/plugins/jpeg/CompressionBug.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/jpeg/CompressionBug.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001, 2017, 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 4415068 4622201 + * @summary Tests if the JPEG writer responds to the compression quality setting + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Iterator; +import java.util.Random; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +public class CompressionBug { + + public CompressionBug() throws IOException { + File fileHighComp = File.createTempFile("CompressionHigh", ".jpg"); + File fileLowComp = File.createTempFile("CompressionLow", ".jpg"); + + fileHighComp.deleteOnExit(); + fileLowComp.deleteOnExit(); + + ImageOutputStream iosHighComp = + ImageIO.createImageOutputStream(fileHighComp); + ImageOutputStream iosLowComp = + ImageIO.createImageOutputStream(fileLowComp); + + int width = 100; + int height = 100; + BufferedImage bi = + new BufferedImage(width, height, + BufferedImage.TYPE_INT_RGB); + Graphics g = bi.createGraphics(); + Random r = new Random(); + for (int i = 0; i < 100; i++) { + Color c = new Color(r.nextInt(256), + r.nextInt(256), + r.nextInt(256)); + int x = r.nextInt(width); + int y = r.nextInt(height); + int w = r.nextInt(width - x); + int h = r.nextInt(height - y); + g.setColor(c); + g.fillRect(x, y, w, h); + } + + ImageTypeSpecifier typeSpecifier = + new ImageTypeSpecifier(bi.getColorModel(), + bi.getSampleModel()); + + ImageWriter writer = null; + Iterator iter = ImageIO.getImageWriters(typeSpecifier,"jpeg"); + while (iter.hasNext()) { + writer = (ImageWriter)iter.next(); + break; + } + + IIOImage iioImg = new IIOImage(bi, null, null); + ImageWriteParam wParam = writer.getDefaultWriteParam(); + wParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + + // write the highly compressed image (a compression quality setting of + // 0.1f means low visual quality and small file size) + wParam.setCompressionQuality(0.1f); + writer.setOutput(iosHighComp); + writer.write(null, iioImg, wParam); + + // write the somewhat compressed image (a compression quality setting + // of 0.9f means high visual quality and large file size) + wParam.setCompressionQuality(0.9f); + writer.setOutput(iosLowComp); + writer.write(null, iioImg, wParam); + + long sizeOfFileLowComp = fileLowComp.length(); + long sizeOfFileHighComp = fileHighComp.length(); + + // the highly compressed image file should have a smaller file size + // than the image file with low compression; throw an exception if + // this isn't the case + if (sizeOfFileLowComp < sizeOfFileHighComp) { + throw new RuntimeException("Lower compression quality did not " + + "reduce file size!"); + } + } + + public static void main(String args[]) throws IOException { + new CompressionBug(); + } +} diff --git a/test/javax/imageio/plugins/jpeg/CompressionVals.java b/test/javax/imageio/plugins/jpeg/CompressionVals.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/jpeg/CompressionVals.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2005, 2017, 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 4972087 + * @summary Verifies that JPEGImageWriteParam.getCompressionQualityValues() + * returns an array that is one longer than the one returned by + * getCompressionQualityDescriptions() + */ + +import javax.imageio.ImageWriteParam; +import javax.imageio.plugins.jpeg.JPEGImageWriteParam; + +public class CompressionVals { + + public static void main(String[] args) { + ImageWriteParam iwp = new JPEGImageWriteParam(null); + iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + float[] vals = iwp.getCompressionQualityValues(); + String[] descs = iwp.getCompressionQualityDescriptions(); + if (vals.length != (descs.length + 1)) { + throw new RuntimeException("Test failed: Values array is not " + + "one larger than descriptions array"); + } + } +} diff --git a/test/javax/imageio/plugins/jpeg/CrashAfterDispose.java b/test/javax/imageio/plugins/jpeg/CrashAfterDispose.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/jpeg/CrashAfterDispose.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2002, 2017, 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 4660047 + * @summary Tests if the JPEG reader/writer crashes the VM if certain methods + * are called after a call to dispose() + */ + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class CrashAfterDispose { + + public static void main(String[] args) throws IOException { + InputStream bais = new ByteArrayInputStream(new byte[100]); + ImageInputStream iis = ImageIO.createImageInputStream(bais); + + // find the JPEG reader + ImageReader reader = null; + Iterator readers = ImageIO.getImageReadersByFormatName("jpeg"); + if (readers.hasNext()) { + reader = (ImageReader)readers.next(); + } else { + throw new RuntimeException("Unable to find a reader!"); + } + + // dispose the reader, then poke and prod it... the reader should + // throw exceptions (which will be caught by this test), but it + // should not crash the VM + reader.dispose(); + + try { + reader.setInput(iis); + } catch (IllegalStateException e) { + } + + try { + reader.read(0); + } catch (IllegalStateException e) { + } + + try { + reader.abort(); + } catch (IllegalStateException e) { + } + + try { + reader.reset(); + } catch (IllegalStateException e) { + } + + try { + reader.dispose(); + } catch (IllegalStateException e) { + } + + // find the JPEG writer + ImageWriter writer = null; + Iterator writers = ImageIO.getImageWritersByFormatName("jpeg"); + if (writers.hasNext()) { + writer = (ImageWriter)writers.next(); + } else { + throw new RuntimeException("Unable to find a writer!"); + } + + // set up output stream + OutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + BufferedImage bi = new BufferedImage(10, 10, + BufferedImage.TYPE_INT_RGB); + + // dispose the writer, then poke and prod it... the writer should + // throw exceptions (which will be caught by this test), but it + // should not crash the VM + writer.dispose(); + + try { + writer.setOutput(ios); + } catch (IllegalStateException e) { + } + + try { + writer.write(bi); + } catch (IllegalStateException e) { + } + + try { + writer.abort(); + } catch (IllegalStateException e) { + } + + try { + writer.reset(); + } catch (IllegalStateException e) { + } + + try { + writer.dispose(); + } catch (IllegalStateException e) { + } + } +} diff --git a/test/javax/imageio/plugins/jpeg/DestTypeTest.java b/test/javax/imageio/plugins/jpeg/DestTypeTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/jpeg/DestTypeTest.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2004, 2017, 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 5028259 + * @summary Verifies that usage of the destination type does not cause the + * increase of size of the result jpeg file + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.event.IIOReadWarningListener; +import javax.imageio.event.IIOWriteWarningListener; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class DestTypeTest implements IIOWriteWarningListener, IIOReadWarningListener { + + ImageWriter w; + ImageReader r; + + public static void main(String[] args) throws IOException { + BufferedImage bi_rgb = createTestImage(BufferedImage.TYPE_INT_RGB); + + DestTypeTest bug = new DestTypeTest(); + byte[] rgb_data = bug.writeTest(bi_rgb); + + System.out.println("rgb jpeg data length is " + rgb_data.length); + + BufferedImage bi_argb = createTestImage(BufferedImage.TYPE_INT_ARGB); + + ImageWriteParam p = bug.getWriteParam(); + IIOMetadata m = bug.getMetadata(p); + + byte[] submeta_data = bug.writeTest(bi_argb, p, m); + System.out.println("desttype and metadata jpeg data length is " + submeta_data.length); + + p = bug.getWriteParam(); + byte[] subbanded_data = bug.writeTest(bi_argb, p); + System.out.println("desttype jpeg data length is " + subbanded_data.length); + + if (submeta_data.length > rgb_data.length) { + throw new RuntimeException("Too big result jpeg: " + submeta_data.length + + "(rgb image size is " + rgb_data.length + ")"); + } + if (subbanded_data.length > rgb_data.length) { + throw new RuntimeException("Too big result jpeg: " + subbanded_data.length + + "(rgb image size is " + rgb_data.length + ")"); + } + } + + public DestTypeTest() { + w = (ImageWriter) + ImageIO.getImageWritersByFormatName("jpeg").next(); + w.addIIOWriteWarningListener(this); + + r = (ImageReader) + ImageIO.getImageReadersByFormatName("jpeg").next(); + r.addIIOReadWarningListener(this); + } + + public ImageWriteParam getWriteParam() { + ImageWriteParam p = w.getDefaultWriteParam(); + p.setSourceBands(new int[] {0, 1, 2}); + ImageTypeSpecifier type = + ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB); + p.setDestinationType(type); + + return p; + } + + public IIOMetadata getMetadata(ImageWriteParam p) { + return w.getDefaultImageMetadata(p.getDestinationType(), null); + } + + public byte[] writeTest(BufferedImage bi) throws IOException { + return writeTest(bi, null); + } + + public byte[] writeTest(BufferedImage bi, + ImageWriteParam p) throws IOException { + return writeTest(bi, p, null); + } + public byte[] writeTest(BufferedImage bi, + ImageWriteParam p, + IIOMetadata m) throws IOException { + ByteArrayOutputStream baos = + new ByteArrayOutputStream(); + + // write test image as jpeg + ImageOutputStream ios = + ImageIO.createImageOutputStream(baos); + w.setOutput(ios); + w.write(null, + new IIOImage(bi, null, m), + p); + ios.close(); + return baos.toByteArray(); + } + + public static BufferedImage createTestImage(int type) { + int w = 100; + int h = 500; + BufferedImage bi = new BufferedImage(3*w, h, type); + Graphics g = bi.createGraphics(); + g.setColor(Color.red); + g.fillRect(0,0,w,h); + g.setColor(Color.green); + g.fillRect(w, 0,w,h); + g.setColor(Color.blue); + g.fillRect(2*w,0,w,h); + + return bi; + } + + public void warningOccurred(ImageWriter source, + int imageIndex, + String warning) { + System.out.println("WRITING WARNING: " + warning); + } + + public void warningOccurred(ImageReader source, + String warning) { + System.out.println("READING WARNING: " + warning); + } +} diff --git a/test/javax/imageio/plugins/jpeg/JPEGsNotAcceleratedTest.java b/test/javax/imageio/plugins/jpeg/JPEGsNotAcceleratedTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/jpeg/JPEGsNotAcceleratedTest.java @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2004, 2017, 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 4994702 + * @key headful + * @summary verifies that no regression were introduced with the fix for this + * bug + */ + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.ImageCapabilities; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.VolatileImage; +import java.awt.image.WritableRaster; +import java.io.File; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.FileImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class JPEGsNotAcceleratedTest { + + public static final int testRGB = Color.red.getRGB(); + public static final int TEST_W = 100; + public static final int TEST_H = 100; + public static final Rectangle roi = + new Rectangle(TEST_W/4, TEST_H/4, TEST_W/2, TEST_H/2); + + static Frame f; + static boolean showRes = false; + static int testsFinished = 0; + static int testsStarted = 0; + static boolean lowCompression = false; + + static boolean failed = false; + + public JPEGsNotAcceleratedTest(String name) { + BufferedImage bi = readTestImage(name, null, null); + runTestOnImage("no dest image, no region of interest", bi, null); + + BufferedImage destBI = getDestImage(); + bi = readTestImage(name, destBI, null); + runTestOnImage("w/ dest image, no region of interest", bi, null); + + // steal the raster, see if the destination image + // gets accelerated + destBI = getDestImage(); + DataBuffer db = + ((WritableRaster)destBI.getRaster()).getDataBuffer(); + bi = readTestImage(name, destBI, null); + runTestOnImage("w/ dest image (with stolen raster),"+ + " no region of interest", bi, null); + + bi = readTestImage(name, null, roi); + runTestOnImage("no dest image, region of interest", bi, roi); + + destBI = getDestImage(); + bi = readTestImage(name, destBI, roi); + runTestOnImage("w/ dest image, region of interest", bi, roi); + + // accelerate the destination image first, then load + // an image into it. Check that the accelerated copy gets + // updated + destBI = getDestImage(); + accelerateImage(destBI); + bi = readTestImage(name, destBI, roi); + runTestOnImage("w/ accelerated dest image,"+ + " region of interest", bi, roi); + + synchronized (JPEGsNotAcceleratedTest.class) { + testsFinished++; + JPEGsNotAcceleratedTest.class.notify(); + } + + } + + public static BufferedImage readTestImage(String fileName, + BufferedImage dest, + Rectangle srcROI) + { + BufferedImage bi = null; + + try { + FileImageInputStream is = + new FileImageInputStream(new File(fileName)); + ImageReader reader = + (ImageReader)ImageIO.getImageReaders(is).next(); + ImageReadParam param = reader.getDefaultReadParam(); + if (dest != null) { + param.setDestination(dest); + } + if (srcROI != null) { + param.setSourceRegion(srcROI); + } + reader.setInput(is); + bi = reader.read(0, param); + } catch (IOException e) { + System.err.println("Error " + e + + " when reading file: " + fileName); + throw new RuntimeException(e); + } + + return bi; + } + + public static void writeTestImage(String fileName) { + BufferedImage bi = + new BufferedImage(TEST_W, TEST_H, BufferedImage.TYPE_INT_RGB); + Graphics g = bi.getGraphics(); + g.setColor(new Color(testRGB)); + g.fillRect(0, 0, TEST_W, TEST_H); + try { + System.err.printf("Writing %s\n", fileName); + if (lowCompression) { + ImageWriter iw = (ImageWriter)ImageIO.getImageWritersBySuffix("jpeg").next(); + if(iw == null) { + throw new RuntimeException("No available image writer for " + + "jpeg " + + " Test failed."); + } + + File file = new File(fileName); + ImageOutputStream ios = ImageIO.createImageOutputStream(file); + iw.setOutput(ios); + + ImageWriteParam param = iw.getDefaultWriteParam(); + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionQuality(1); + + IIOImage iioImg = new IIOImage(bi, null, null); + iw.write(null, iioImg, param); + + } else { + ImageIO.write(bi, "jpeg", new File(fileName)); + } + } catch (IOException e) { + System.err.println("Error " + e + + " when writing file: " + fileName); + throw new RuntimeException(e); + } + } + + public VolatileImage accelerateImage(BufferedImage bi) { + VolatileImage testVI = f.createVolatileImage(TEST_W, TEST_H); + do { + if (testVI.validate(f.getGraphicsConfiguration()) == + VolatileImage.IMAGE_INCOMPATIBLE) + { + testVI = f.createVolatileImage(TEST_W, TEST_H); + } + Graphics2D g = testVI.createGraphics(); + g.setComposite(AlphaComposite.Src); + g.setColor(Color.green); + g.fillRect(0, 0, TEST_W, TEST_H); + + g.drawImage(bi, 0, 0, null); + g.drawImage(bi, 0, 0, null); + g.drawImage(bi, 0, 0, null); + g.dispose(); + } while (testVI.contentsLost()); + + return testVI; + } + + public BufferedImage getDestImage() { + BufferedImage destBI = + new BufferedImage(TEST_W, TEST_H, BufferedImage.TYPE_INT_RGB); + Graphics2D g = (Graphics2D)destBI.getGraphics(); + g.setComposite(AlphaComposite.Src); + g.setColor(Color.blue); + g.fillRect(0, 0, TEST_W, TEST_H); + return destBI; + } + + public void runTestOnImage(String desc, BufferedImage bi, + Rectangle srcROI) + { + + if (srcROI == null) { + srcROI = new Rectangle(0, 0, TEST_W, TEST_H); + } + + VolatileImage testVI = accelerateImage(bi); + + ImageCapabilities ic = + bi.getCapabilities(f.getGraphicsConfiguration()); + boolean accelerated = ic.isAccelerated(); + + System.err.println("Testing: " + desc + + " -- bi.isAccelerated(): " + accelerated ); + + BufferedImage snapshot = testVI.getSnapshot(); + if (showRes) { + showRes(desc, snapshot); + } + + for (int y = 0; y < srcROI.height; y++) { + for (int x = 0; x < srcROI.width; x++) { + int destRGB = snapshot.getRGB(x, y); + if (destRGB != testRGB && destRGB != 0xfffe0000) { + failed = true; + System.err.printf("Test failed at %dx%d pixel=%x\n", + x, y, snapshot.getRGB(x, y)); + if (!showRes) { + showRes(desc, snapshot); + } + break; + } + } + } + } + + static int startX = 64, startY = 0; + static int frameX = startX, frameY = startY; + private static void showRes(String desc, final BufferedImage src) { + final int w = src.getWidth(); + final int h = src.getHeight(); + + Frame f = new Frame(desc+": dbl-click to exit"); + Component c; + f.add(c = new Component() { + public Dimension getPreferredSize() { + return new Dimension(w,h); + } + + public void paint(Graphics g) { + g.clearRect(0, 0, getWidth(), getHeight()); + g.drawImage(src, 0,0, null); + } + }); + c.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() > 1) { + System.exit(0); + } + } + }); + f.pack(); + synchronized (JPEGsNotAcceleratedTest.class) { + f.setLocation(frameX, frameY); + frameX += f.getWidth(); + if ((frameX + f.getWidth()) > + f.getGraphicsConfiguration().getBounds().width) + { + frameY += TEST_H; + if ((frameY + f.getHeight()) > + f.getGraphicsConfiguration().getBounds().height) + { + startY += 30; + startX += 30; + frameY = startY; + } + frameX = startX; + } + }; + f.setVisible(true); + } + + public static void usage() { + System.err.println("Usage: java Test [file name] [-write][-show][-low]"); + System.exit(0); + } + + public static void main(String[] args) { + System.setProperty("sun.java2d.pmoffscreen", "true"); + System.setProperty("sun.java2d.ddforcevram", "true"); + String name = "red.jpg"; + + f = new Frame(); + f.pack(); + + if (f.getGraphicsConfiguration().getColorModel().getPixelSize() < 16) { + System.err.println("8-bit display mode detected, dithering issues possible, "+ + "considering test passed."); + f.dispose(); + return; + } + + + for (String arg : args) { + if (arg.equals("-write")) { + writeTestImage(name); + System.exit(0); + } else if (arg.equals("-show")) { + showRes = true; + } else if (arg.equals("-low")) { + lowCompression = true; + name ="red_low.jpg"; + System.err.println("Using low jpeg compression"); + } else if (arg.equals("-help")) { + usage(); + } else { + final String filename = arg; + testsStarted++; + new Thread(new Runnable() { + public void run() { + new JPEGsNotAcceleratedTest(filename); + } + }).start(); + } + } + + if (testsStarted == 0) { + writeTestImage(name); + testsStarted++; + new JPEGsNotAcceleratedTest(name); + } + + + synchronized (JPEGsNotAcceleratedTest.class) { + while (testsFinished < testsStarted) { + try { + JPEGsNotAcceleratedTest.class.wait(100); + } catch (InterruptedException e) { + failed = true; break; + } + } + } + + f.dispose(); + if (failed) { + throw new RuntimeException("Test failed"); + } + + System.err.println("Passed."); + } +} diff --git a/test/javax/imageio/plugins/jpeg/MergeTreeTest.java b/test/javax/imageio/plugins/jpeg/MergeTreeTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/jpeg/MergeTreeTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004, 2017, 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 4895547 + * @summary Test verifies that mergeTree() of JPEGMetadata does not throw the + * NPE + */ + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +import org.w3c.dom.Node; + +public class MergeTreeTest { + public static void main(String[] args) throws IOException { + ImageWriter iw = + (ImageWriter)ImageIO.getImageWritersByFormatName("jpeg").next(); + + ImageTypeSpecifier type = + ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB); + + ImageOutputStream ios = + ImageIO.createImageOutputStream(new File("MergeTreeTest.jpeg")); + iw.setOutput(ios); + + IIOMetadata meta = iw.getDefaultImageMetadata(type, null); + + boolean isFailed = false; + + String[] fmts = meta.getMetadataFormatNames(); + for (int i=0; i 8-bit samples to + * be written. Also tests the JPEGImageWriterSpi.canEncodeImage() + * mechanism for this same behavior. + */ + +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +public class UshortGrayTest { + + public static void main(String[] args) { + Iterator iter; + BufferedImage bi = new BufferedImage(10, 10, + BufferedImage.TYPE_USHORT_GRAY); + + // Part 1: ensure that JPEGImageWriter throws an exception if it + // encounters an image with 16-bit samples + ImageWriter writer = null; + iter = ImageIO.getImageWritersByFormatName("jpeg"); + if (iter.hasNext()) { + writer = (ImageWriter)iter.next(); + } else { + throw new RuntimeException("No JPEG reader found"); + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream ios = null; + boolean exceptionThrown = false; + + try { + ios = ImageIO.createImageOutputStream(baos); + } catch (IOException ioe) { + throw new RuntimeException("Could not create ImageOutputStream"); + } + + try { + writer.setOutput(ios); + writer.write(bi); + } catch (IOException ioe) { + exceptionThrown = true; + } + + if (!exceptionThrown) { + throw new RuntimeException("JPEG writer should not be able to " + + "write USHORT_GRAY images"); + } + + // Part 2: ensure that JPEGImageWriterSpi.canEncodeImage() returns + // false for images with 16-bit samples + ImageTypeSpecifier its = + ImageTypeSpecifier.createFromRenderedImage(bi); + + iter = ImageIO.getImageWriters(its, "jpeg"); + if (iter.hasNext()) { + throw new RuntimeException("JPEG writer should not be available" + + " for USHORT_GRAY images"); + } + } +} diff --git a/test/javax/imageio/plugins/png/CanEncodeShort.java b/test/javax/imageio/plugins/png/CanEncodeShort.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/png/CanEncodeShort.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2017, 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 4474819 + * @summary Tests whether the PNGImageWriterSpi advertises that it is capable of + * writing images of TYPE_USHORT_565_RGB and TYPE_USHORT_555_RGB. The + * test fails if an exception is thrown. + */ + +import java.awt.image.BufferedImage; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; + +public class CanEncodeShort { + + private static final int[] types = new int[] { + BufferedImage.TYPE_USHORT_565_RGB, + BufferedImage.TYPE_USHORT_555_RGB, + }; + + private static final String[] typeNames = new String[] { + "TYPE_USHORT_565_RGB", + "TYPE_USHORT_555_RGB", + }; + + public static void main(String[] args) { + for (int i = 0; i < types.length; i++) { + BufferedImage img = new BufferedImage(32, 32, types[i]); + + ImageTypeSpecifier spec = + ImageTypeSpecifier.createFromRenderedImage(img); + + Iterator writers = ImageIO.getImageWriters(spec, "png"); + + if (!writers.hasNext()) { + throw new RuntimeException("Test failed: " + + "no PNG writer found for type " + + typeNames[i]); + } + } + } +} diff --git a/test/javax/imageio/plugins/png/ImageCompare.java b/test/javax/imageio/plugins/png/ImageCompare.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/png/ImageCompare.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2000, 2017, 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. + */ + +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.Raster; + +// Utility to compare two BufferedImages for RGB equality +public class ImageCompare { + + public static void compare(BufferedImage oldimg, + BufferedImage newimg) { + int width = oldimg.getWidth(); + int height = oldimg.getHeight(); + if (newimg.getWidth() != width || newimg.getHeight() != height) { + throw new RuntimeException("Dimensions changed!"); + } + + Raster oldras = oldimg.getRaster(); + ColorModel oldcm = oldimg.getColorModel(); + Raster newras = newimg.getRaster(); + ColorModel newcm = newimg.getColorModel(); + + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + Object oldpixel = oldras.getDataElements(i, j, null); + int oldrgb = oldcm.getRGB(oldpixel); + int oldalpha = oldcm.getAlpha(oldpixel); + + Object newpixel = newras.getDataElements(i, j, null); + int newrgb = newcm.getRGB(newpixel); + int newalpha = newcm.getAlpha(newpixel); + + if (newrgb != oldrgb || + newalpha != oldalpha) { + throw new RuntimeException("Pixels differ at " + i + + ", " + j); + } + } + } + } +} diff --git a/test/javax/imageio/plugins/png/PngPremultAlphaTest.java b/test/javax/imageio/plugins/png/PngPremultAlphaTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/png/PngPremultAlphaTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003, 2017, 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 4888478 + * @summary Test that colors do not distort when buffered image with + * premultiplied alpha is encoded to png format + */ + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import javax.imageio.ImageIO; + +public class PngPremultAlphaTest { + protected static int width = 100; + protected static int height = 100; + + protected static String format = "png"; + + protected static int[] iBufferedImageTypes = { + BufferedImage.TYPE_INT_RGB, + BufferedImage.TYPE_INT_ARGB, + BufferedImage.TYPE_4BYTE_ABGR_PRE, + BufferedImage.TYPE_INT_ARGB_PRE + }; + + protected static String[] strBufferedImageTypes = { + "TYPE_INT_RGB", + "TYPE_INT_ARGB", + "BufferedImage.TYPE_4BYTE_ABGR_PRE", + "BufferedImage.TYPE_INT_ARGB_PRE" + }; + + public static void main(String[] arg) { + for(int i=0; i 1 + || Math.abs(src.getColorModel().getGreen(srcPixel) - dst.getColorModel().getGreen(dstPixel)) > 1 + || Math.abs(src.getColorModel().getBlue(srcPixel) - dst.getColorModel().getBlue(dstPixel)) > 1) { + showPixel(src, width/2, height/2); + showPixel(dst, width/2, height/2); + + throw new RuntimeException( "Colors are different: " + + Integer.toHexString(src.getColorModel().getRGB(srcPixel)) + + " and " + + Integer.toHexString(dst.getColorModel().getRGB(dstPixel))); + } + return true; + } + + private static void showPixel(BufferedImage src, int x, int y) { + System.out.println("Img is " + src); + System.out.println("CM is " + src.getColorModel().getClass().getName()); + Object p = src.getRaster().getDataElements(x, y, null); + System.out.println("RGB: " + + Integer.toHexString(src.getColorModel().getRGB(p))); + System.out.println("Red: " + + Integer.toHexString(src.getColorModel().getRed(p))); + System.out.println("Green: " + + Integer.toHexString(src.getColorModel().getGreen(p))); + System.out.println("Blue: " + + Integer.toHexString(src.getColorModel().getBlue(p))); + System.out.println("Alpha: " + + Integer.toHexString(src.getColorModel().getAlpha(p))); + } +} diff --git a/test/javax/imageio/plugins/png/ShortPaletteTest.java b/test/javax/imageio/plugins/png/ShortPaletteTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/png/ShortPaletteTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2003, 2017, 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 4826548 + * @summary Tests for reading PNG images with 5,6,7 and 8 colors in palette + */ + +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; + +public class ShortPaletteTest { + + public static void main(String[] args) { + + for (int numberColors = 2; numberColors <= 16; numberColors++) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + BufferedImage image = createImage(numberColors); + ImageIO.write(image, "png", baos); + baos.close(); + System.out.println("Number of colors: " + numberColors); + byte[] buffer = baos.toByteArray(); + ByteArrayInputStream bais = new ByteArrayInputStream(buffer); + ImageIO.read(bais); + System.out.println("OK"); + } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed."); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("Unexpected exception was thrown." + + " Test failed."); + } + } + } + + private static IndexColorModel createColorModel(int numberColors) { + + byte[] colors = new byte[numberColors*3]; + int depth = 4; + int startIndex = 0; + + return new IndexColorModel(depth, + numberColors, + colors, + startIndex, + false); + } + + private static BufferedImage createImage(int numberColors) { + return new BufferedImage(32, + 32, + BufferedImage.TYPE_BYTE_BINARY, + createColorModel(numberColors)); + } +} diff --git a/test/javax/imageio/plugins/png/WriteProgressive.java b/test/javax/imageio/plugins/png/WriteProgressive.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/png/WriteProgressive.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2001, 2017, 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 4432615 + * @summary Tests progressive writing in the PNG encoder + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Iterator; +import java.util.Random; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +public class WriteProgressive { + + public static void main(String[] args) throws IOException { + Iterator witer = ImageIO.getImageWritersByFormatName("png"); + ImageWriter w = (ImageWriter)witer.next(); + + File f = File.createTempFile("WriteProgressive", ".png"); + ImageOutputStream ios = ImageIO.createImageOutputStream(f); + w.setOutput(ios); + + BufferedImage bi = new BufferedImage(100, 100, + BufferedImage.TYPE_3BYTE_BGR); + Graphics2D g = bi.createGraphics(); + Random r = new Random(10); + for (int i = 0; i < 10000; i++) { + Color c = + new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256)); + g.setColor(c); + g.fillRect(r.nextInt(100), r.nextInt(100), 1, 1); + } + + IIOImage iioimage = new IIOImage(bi, null, null); + + ImageWriteParam param = w.getDefaultWriteParam(); + param.setProgressiveMode(ImageWriteParam.MODE_DEFAULT); + + try { + w.write(null, iioimage, param); + } catch (NullPointerException npe) { + throw new RuntimeException("Got NPE during write!"); + } + + ios.close(); + + BufferedImage bi2 = ImageIO.read(f); + f.delete(); + + ImageCompare.compare(bi, bi2); + } +} diff --git a/test/javax/imageio/plugins/wbmp/EmptyInputWbmpMetadataTest.java b/test/javax/imageio/plugins/wbmp/EmptyInputWbmpMetadataTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/wbmp/EmptyInputWbmpMetadataTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003, 2017, 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 4895483 + * @summary Test checks that the IllegalStateException was thrown if input was + * not set to the WBMPImageReader + */ + +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.metadata.IIOMetadata; + +public class EmptyInputWbmpMetadataTest { + private static String fmt = "BMP"; + + public static void main(String[] args) { + boolean isPassed = false; + ImageReader ir = (ImageReader)ImageIO.getImageReadersByFormatName(fmt).next(); + + if (ir == null) { + throw new RuntimeException("No available reader for " + fmt); + } + IIOMetadata meta = null; + try { + meta = ir.getImageMetadata(0); + } catch (IllegalStateException e) { + System.out.println("Correct exception was thrown. Test passed."); + isPassed = true; + } catch (IOException e) { + e.printStackTrace(); + } + if (!isPassed) { + throw new RuntimeException("The IllegalStateException was not thrown." + +"Test failed."); + } + } +} diff --git a/test/javax/imageio/plugins/wbmp/GetImageTypesTest.java b/test/javax/imageio/plugins/wbmp/GetImageTypesTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/wbmp/GetImageTypesTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003, 2017, 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 4928273 + * @summary Verifies what IllegalStateException is thrown if image input was not + * set + */ + +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; + +public class GetImageTypesTest { + + private static final String format = "wbmp"; + + public static void main(String[] args) { + + boolean passed = false; + ImageReader ir = (ImageReader)ImageIO.getImageReadersByFormatName(format).next(); + + if (ir == null) { + throw new RuntimeException("No matching reader found. Test Failed"); + } + + try { + Iterator types = ir.getImageTypes(0); + } catch (IllegalStateException e) { + System.out.println("Test passed."); + passed = true; + } catch (Exception e) { + throw new RuntimeException("Unexpected exception was thrown. " + + "Test failed."); + } + + if (!passed) { + throw new RuntimeException("IllegalStateException is not thrown when " + + "calling getImageTypes() without setting " + + "the input source for the image format: " + + format + + ". Test failed"); + } + + } +} diff --git a/test/javax/imageio/plugins/wbmp/ValidWbmpTest.java b/test/javax/imageio/plugins/wbmp/ValidWbmpTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/plugins/wbmp/ValidWbmpTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003, 2017, 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 4924512 + * @summary Test that wbmp image reader detects incorrect image format + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import javax.imageio.IIOException; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +public class ValidWbmpTest { + + public static void main(String[] args) { + try { + String[] formats = { "JPEG", "PNG", "BMP" }; + + BufferedImage img = new BufferedImage(100, 100, + BufferedImage.TYPE_BYTE_GRAY); + Graphics g = img.createGraphics(); + g.setColor(Color.white); + g.fillRect(0,0,100,100); + g.setColor(Color.black); + g.fillRect(10,10,80,80); + + ImageReader ir = (ImageReader)ImageIO.getImageReadersByFormatName("WBMP").next(); + if (ir==null) { + throw new RuntimeException("No readers for WBMP format!"); + } + for(int i=0; i 0) { + format = args[0]; + System.out.println("Test format " + format); + } + + init(); + ImageIO.setUseCache(false); + + for (int i=0; i"); + indent(level); + System.out.println(node.getNodeValue()); + indent(level); // emit close tag + System.out.println(""); + } else if (child != null) { + System.out.println(">"); // close current tag + while (child != null) { // emit child tags recursively + displayMetadata(child, level + 1); + child = child.getNextSibling(); + } + indent(level); // emit close tag + System.out.println(""); + } else { + System.out.println("/>"); + } + } + + public static void main(String args[]) { + WbmpDefaultImageMetadataTest test = + new WbmpDefaultImageMetadataTest("wbmp"); + } +} diff --git a/test/javax/imageio/spi/AppletContextTest/BadPluginConfigurationTest.sh b/test/javax/imageio/spi/AppletContextTest/BadPluginConfigurationTest.sh new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/AppletContextTest/BadPluginConfigurationTest.sh @@ -0,0 +1,280 @@ +#!/bin/ksh -p +# Copyright (c) 2005, 2017, 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 6342404 7078379 8167503 8183351 +# +# @summary Test verifies that incorrectly configured ImageIO plugin spi +# does not affect registration of other ImageIO plugin in the +# applet context. +# +# +# @compile IIOPluginTest.java +# @compile DummyReaderPluginSpi.java +# @run shell BadPluginConfigurationTest.sh + +# There are several resources which need to be present before many +# shell scripts can run. Following are examples of how to check for +# many common ones. +# +# Note that the shell used is the Korn Shell, KSH +# +# Also note, it is recommended that make files NOT be used. Rather, +# put the individual commands directly into this file. That way, +# it is possible to use command line arguments and other shell tech- +# niques to find the compiler, etc on different systems. For example, +# a different path could be used depending on whether this were a +# Solaris or Win32 machine, which is more difficult (if even possible) +# in a make file. + + +# Beginning of subroutines: +status=1 + +#Call this from anywhere to fail the test with an error message +# usage: fail "reason why the test failed" +fail() + { echo "The test failed :-(" + echo "$*" 1>&2 + echo "exit status was $status" + clean + exit $status + } #end of fail() + +#Call this from anywhere to pass the test with a message +# usage: pass "reason why the test passed if applicable" +pass() + { echo "The test passed!!!" + echo "$*" 1>&2 + clean + exit 0 + } #end of pass() + +#Clean up the test_ext directory (PLUGINDST_DIR) before leaving +clean() + { + echo "Removing PLUGINDST_DIR ${PLUGINDST_DIR}" + if [ -n "${PLUGINDST_DIR}" -a -d "${PLUGINDST_DIR}" ] ; then + rm -rf "${PLUGINDST_DIR}" + fi + } + +# end of subroutines + + +# The beginning of the script proper + +# Checking for proper OS +OS=`uname -s` +case "$OS" in + SunOS | Linux | Darwin ) + FILESEP="/" + PATHSEP=":" + TMP=`cd /tmp; pwd -P` + ;; + + Windows* ) + FILESEP="\\" + PATHSEP=";" + TMP=`cd "${SystemRoot}/Temp"; echo ${PWD}` + ;; + + CYGWIN* ) + FILESEP="/" + PATHSEP=";" + TMP="/tmp" + ;; + + # catch all other OSs + * ) + echo "Unrecognized system! $OS" + fail "Unrecognized system! $OS" + ;; +esac + +# Want this test to run standalone as well as in the harness, so do the +# following to copy the test's directory into the harness's scratch directory +# and set all appropriate variables: + +if [ -z "${TESTJAVA}" ] ; then + # TESTJAVA is not set, so the test is running stand-alone. + # TESTJAVA holds the path to the root directory of the build of the JDK + # to be tested. That is, any java files run explicitly in this shell + # should use TESTJAVA in the path to the java interpreter. + # So, we'll set this to the JDK spec'd on the command line. If none + # is given on the command line, tell the user that and use a cheesy + # default. + # THIS IS THE JDK BEING TESTED. + if [ -n "$1" ] ; + then TESTJAVA=$1 + else fail "no JDK specified on command line!" + fi + TESTSRC=. + TESTCLASSES=. + STANDALONE=1; +fi +echo "JDK under test is: $TESTJAVA" + +#Deal with .class files: +if [ -n "${STANDALONE}" ] ; + then + #if standalone, remind user to cd to dir. containing test before running it + echo "Just a reminder: cd to the dir containing this test when running it" + # then compile all .java files (if there are any) into .class files + if [ -a *.java ] ; + then echo "Reminder, this test should be in its own directory with all" + echo "supporting files it needs in the directory with it." + ${COMPILEJAVA}/bin/javac ./*.java ; + fi + # else in harness so copy all the class files from where jtreg put them + # over to the scratch directory this test is running in. + else cp ${TESTCLASSES}/*.class . ; +fi + +#if in test harness, then copy the entire directory that the test is in over +# to the scratch directory. This catches any support files needed by the test. +if [ -z "${STANDALONE}" ] ; + then cp ${TESTSRC}/*.java . +fi + +#Just before executing anything, make sure it has executable permission! +chmod 777 ./* + +############### YOUR TEST CODE HERE!!!!!!! ############# + +#All files required for the test should be in the same directory with +# this file. If converting a standalone test to run with the harness, +# as long as all files are in the same directory and it returns 0 for +# pass, you should be able to cut and paste it into here and it will +# run with the test harness. + +# This is an example of running something -- test +# The stuff below catches the exit status of test then passes or fails +# this shell test as appropriate ( 0 status is considered a pass here ) + +echo +echo ------ PREPARE TEST PLUGIN --------- + +# note that we can not use some subdirectory of the +# scratch dir as the plugin dst dir because the test +# app have file read permission for all subdirs of the +# scratch dir + +PLUGINDST_DIR=$(mktemp -d ${TMP}/iio_test.XXXXXXXX) +echo "Created PLUGINDST_DIR as ${PLUGINDST_DIR}" + +TEST_PLUGIN=dummy.jar + +# remove old service declaration +if [ -d META-INF ] ; then + rm -rf META-INF +fi + +# generate the service declaration +if [ ! -d META_INF ] ; then + mkdir META-INF + mkdir META-INF/services +fi + +# add wrong record to the service configuration +echo "BadReaderPluginSpi" > META-INF/services/javax.imageio.spi.ImageReaderSpi + +echo "DummyReaderPluginSpi" >> META-INF/services/javax.imageio.spi.ImageReaderSpi + + +${TESTJAVA}/bin/jar -cvf ${TEST_PLUGIN} DummyReaderPluginSpi*.class META-INF/services/javax.imageio.spi.ImageReaderSpi + +echo ----- TEST PLUGIN IS READY -------- +echo +echo ----- INSTALL PLUGIN -------- +echo "Install test plugin to ${PLUGINDST_DIR}" +if [ -f ${PLUGINDST_DIR}/${TEST_PLUGIN} ] ; then + echo "Remove old plugin..." + rm -f ${PLUGINDST_DIR}/${TEST_PLUGIN} +fi +mv -f ${TEST_PLUGIN} ${PLUGINDST_DIR} +if [ -f ${PLUGINDST_DIR}/${TEST_PLUGIN} ] ; then + echo Test plugin is installed. +else + fail "Unable to install test plugin to $PLUGINDST_DIR" +fi +echo ----- PLUGIN IS INSTALLED ------ +echo +echo ----- CLEAN PLUGIN TEMPORARY FILES ----- +rm -rf DummyReaderPluginSpi*.class META-INF +echo ----- CLEANING IS COMPLETE ------- +echo + + +case "$OS" in + CYGWIN* ) + TEST_CODEBASE=$(cygpath -m ${PWD}) + TEST_PLUGIN_JAR=$(cygpath -m ${PLUGINDST_DIR}${FILESEP}${TEST_PLUGIN}) + ;; + + # catch all other OSs + * ) + TEST_CODEBASE=${PWD} + TEST_PLUGIN_JAR=${PLUGINDST_DIR}${FILESEP}${TEST_PLUGIN} + ;; +esac + + +# Update policy file to grant read permission +echo "grant codeBase \"file:${TEST_CODEBASE}\" {" > classpath.policy +echo " permission java.io.FilePermission \"${TEST_PLUGIN_JAR}\", \"read\";" >> classpath.policy +echo " permission java.util.PropertyPermission \"test.5076692.property\", \"read\";" >> classpath.policy +echo "};" >> classpath.policy +echo "grant codeBase \"file:${TEST_PLUGIN_JAR}\" {" >> classpath.policy +echo " permission java.util.PropertyPermission \"test.5076692.property\", \"read\";" >> classpath.policy +echo "};" >> classpath.policy + +echo --------------------- +echo --- Applet policy --- +echo --------------------- +cat classpath.policy +echo --------------------- +echo + +echo ------------------------------- +echo --- Applet Classpath Test --- +echo ------------------------------- +# +# please note that we need to use "==" in setup of the java.security.policy +# property in order to overwrite policies defined in the user policy file +# For more details see: +# http://java.sun.com/j2se/1.5.0/docs/guide/security/PolicyFiles.html) +# + +${TESTJAVA}/bin/java ${TESTVMOPTS} -cp ".${PATHSEP}${TEST_PLUGIN_JAR}" \ + -Djava.security.policy==classpath.policy \ + -Djava.security.manager IIOPluginTest + +status=$? + +if [ $status -eq "0" ] ; then + pass "" +else + fail "Test failed due to test plugin was not found." +fi + diff --git a/test/javax/imageio/spi/AppletContextTest/DummyReaderPluginSpi.java b/test/javax/imageio/spi/AppletContextTest/DummyReaderPluginSpi.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/AppletContextTest/DummyReaderPluginSpi.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005, 2017, 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. + */ + +import java.io.IOException; +import java.util.Locale; + +import javax.imageio.IIOException; +import javax.imageio.ImageReader; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.spi.ServiceRegistry; + +public class DummyReaderPluginSpi extends ImageReaderSpi { + + private static String [] writerSpiNames = + {"DummyWriterPluginSpi"}; + public static String[] formatNames = {"test_5076692", "TEST_5076692"}; + public static String[] entensions = {"test_5076692"}; + public static String[] mimeType = {"image/test_5076692"}; + + private boolean registered = false; + + public DummyReaderPluginSpi() { + super("Sun Microsystems, Inc.", + "1.0", + formatNames, + entensions, + mimeType, + "DummyPluginReader", + STANDARD_INPUT_TYPE, + writerSpiNames, + false, + null, null, null, null, + false, + "", + "", + null, null); + } + + public void onRegistration(ServiceRegistry registry, + Class category) { + if (registered) { + return; + } + + System.getProperty("test.5076692.property", "not found"); + + registered = true; + } + + public String getDescription(Locale locale) { + return "Standard Dummy Image Reader"; + } + + public boolean canDecodeInput(Object source) throws IOException { + return false; + } + + public ImageReader createReaderInstance(Object extension) + throws IIOException { + return null; + } +} diff --git a/test/javax/imageio/spi/AppletContextTest/IIOPluginTest.java b/test/javax/imageio/spi/AppletContextTest/IIOPluginTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/AppletContextTest/IIOPluginTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2005, 2017, 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. + */ + +import javax.imageio.ImageIO; + +public class IIOPluginTest { + + public static String[] dummyformatNames = {"test_5076692", "TEST_5076692"}; + public static String[] dummymimeType = {"image/test_5076692"}; + + public static void main(String[] args) { + SecurityManager sm = System.getSecurityManager(); + System.out.println("Sm is " + sm); + + String formatNames[] = ImageIO.getReaderFormatNames(); + String readerMimeTypes[] = ImageIO.getReaderMIMETypes(); + + if (!isPresent(dummyformatNames, formatNames) || + !isPresent(dummymimeType, readerMimeTypes)) { + throw new RuntimeException("No test plugin available!"); + } + } + + public static boolean isPresent(String[] t, String[] r) { + for (int i=0; i category) { + System.out.println("\nfrom OnRegistration: BMP plugin Registered\n"); + super.onRegistration(sr, category); + } + + public void onDeregistration(ServiceRegistry sr, Class category) { + System.out.println("\nfrom OnDeregistration: BMP plugin De-Registered\n"); + //super.onRegistration(sr, category); + } + } +} diff --git a/test/javax/imageio/spi/DeregisterOrderedSpiTest.java b/test/javax/imageio/spi/DeregisterOrderedSpiTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/DeregisterOrderedSpiTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003, 2017, 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 4936495 8037743 + * @summary This test verifies whether deregistering an ordered spi object does + * not throw any exception + */ + +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.spi.ServiceRegistry; + +public class DeregisterOrderedSpiTest { + + public DeregisterOrderedSpiTest() { + + try { + + ServiceRegistry reg = IIORegistry.getDefaultInstance(); + ImageReaderSpi gifSpi = (ImageReaderSpi) reg.getServiceProviderByClass(com.sun.imageio.plugins.gif.GIFImageReaderSpi.class); + ImageReaderSpi pngSpi = (ImageReaderSpi) reg.getServiceProviderByClass(com.sun.imageio.plugins.png.PNGImageReaderSpi.class); + ImageReaderSpi jpgSpi = (ImageReaderSpi) reg.getServiceProviderByClass(com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi.class); + ImageReaderSpi bmpSpi = (ImageReaderSpi) reg.getServiceProviderByClass(com.sun.imageio.plugins.bmp.BMPImageReaderSpi.class); + + boolean ordered = reg.setOrdering(ImageReaderSpi.class, pngSpi, + gifSpi); + + ordered = reg.setOrdering(ImageReaderSpi.class, gifSpi, jpgSpi); + ordered = reg.setOrdering(ImageReaderSpi.class, bmpSpi, gifSpi); + reg.deregisterServiceProvider(gifSpi); + System.out.println("PASS"); + + } catch (Exception e) { + System.out.println("FAIL"); + throw new RuntimeException("Deregistering a spi object involved in some " + + "ordering throws the following exception: " + e.toString()); + } + } + + public static void main(String args[]) { + DeregisterOrderedSpiTest test = new DeregisterOrderedSpiTest(); + } +} diff --git a/test/javax/imageio/spi/OrderingTest.java b/test/javax/imageio/spi/OrderingTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/OrderingTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003, 2017, 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 4936445 + * @summary This test verifies whether setting the order reversely between 2 spi + * objects removes the previous ordering that was set between the + * same set of spi objects. This is verified by invoking + * unsetOrdering() method twice consecutively with respect to the same + * spi objects and unsetOrdering() is supposed to return false when + * called for the second time. + */ + +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.spi.ServiceRegistry; + +public class OrderingTest { + + public OrderingTest() { + + ServiceRegistry reg = IIORegistry.getDefaultInstance(); + ImageReaderSpi gifSpi = (ImageReaderSpi) reg.getServiceProviderByClass(com.sun.imageio.plugins.gif.GIFImageReaderSpi.class); + ImageReaderSpi pngSpi = (ImageReaderSpi) reg.getServiceProviderByClass(com.sun.imageio.plugins.png.PNGImageReaderSpi.class); + + boolean ordered = reg.setOrdering(ImageReaderSpi.class, gifSpi, pngSpi); + + ordered = reg.setOrdering(ImageReaderSpi.class, pngSpi, gifSpi); + + boolean unordered = reg.unsetOrdering(ImageReaderSpi.class, gifSpi, + pngSpi); + boolean unordered1 = reg.unsetOrdering(ImageReaderSpi.class, gifSpi, + pngSpi); + + if (unordered1) { + throw new RuntimeException("FAIL: Ordering 2 spi objects in the " + + "reverse direction does not remove the previous ordering " + + "set between the spi objects and hence unsetOrdering() " + + "returns true for the same spi objects when called consecutively"); + } else { + System.out.println("PASS"); + } + + } + + public static void main(String args[]) { + OrderingTest test = new OrderingTest(); + } +} diff --git a/test/javax/imageio/spi/PluginSpiTest.java b/test/javax/imageio/spi/PluginSpiTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/PluginSpiTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2005, 2017, 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 6275112 + * @summary Test verifies that imageReaders for base image formats return + * meaningful name of service provider interface (SPI) for base image + * formats + */ + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriter; +import javax.imageio.spi.ImageReaderSpi; + +public class PluginSpiTest { + + public static void main(String[] args) { + String format[] = { "GIF", "PNG", "JPEG", "BMP", "WBMP" }; + for (int i = 0; i < format.length; i++) { + System.out.println("\nFormat " + format[i]); + testFormat(format[i]); + } + } + + public static void testFormat(String format) { + ImageReader reader = + ImageIO.getImageReadersByFormatName(format).next(); + if (reader == null) { + throw new RuntimeException("Failed to get reader for " + format); + } + + ImageReaderSpi readerSpi = reader.getOriginatingProvider(); + System.out.println(format + " Reader SPI: " + readerSpi); + + String writerSpiNames[] = readerSpi.getImageWriterSpiNames(); + if (writerSpiNames == null || writerSpiNames.length == 0) { + throw new RuntimeException("Failed to get writer spi names for " + + format); + } + + System.out.println("Available writer spi names:"); + for (int i = 0; i < writerSpiNames.length; i++) { + System.out.println(writerSpiNames[i]); + try { + Class spiClass = Class.forName(writerSpiNames[i]); + if (spiClass == null) { + throw new RuntimeException("Failed to get spi class " + + writerSpiNames[i]); + } + System.out.println("Got class " + spiClass.getName()); + + Object spiObject = spiClass.newInstance(); + if (spiObject == null) { + throw new RuntimeException("Failed to instantiate spi " + + writerSpiNames[i]); + } + System.out.println("Got instance " + spiObject); + } catch (Throwable e) { + throw new RuntimeException("Failed to test spi " + + writerSpiNames[i]); + } + } + + ImageWriter writer = ImageIO.getImageWriter(reader); + if (writer == null) { + throw new RuntimeException("Failed to get writer for " + format); + } + } +} diff --git a/test/javax/imageio/spi/RegisterPluginTwiceTest.java b/test/javax/imageio/spi/RegisterPluginTwiceTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/RegisterPluginTwiceTest.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2003, 2017, 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 4836432 8037743 + * @summary This test attempts to register two instances of one ImageReaderSPI. + * Expected behavior is that only one instance of ImageReaderSPI will + * be registered. + */ + +import java.io.IOException; +import java.util.Iterator; +import java.util.Locale; + +import javax.imageio.ImageReader; +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ServiceRegistry; +import javax.imageio.stream.ImageInputStream; + +public class RegisterPluginTwiceTest { + + public RegisterPluginTwiceTest() throws Exception { + BMPImageReaderSPI BMPSpi = new BMPImageReaderSPI(); + BMPImageReaderSPI BMPSpi1 = new BMPImageReaderSPI(); + + IIORegistry regis = IIORegistry.getDefaultInstance(); + boolean res1 + = regis.registerServiceProvider(BMPSpi, + javax.imageio.spi.ImageReaderSpi.class); + boolean res2 + = regis.registerServiceProvider(BMPSpi1, + javax.imageio.spi.ImageReaderSpi.class); + + if(!res1 || res2) { + throw new RuntimeException("Bad returned values for registerServiceProvider"); + } + Iterator it = regis.getServiceProviders(Class.forName("javax.imageio.spi.ImageReaderSpi"), true); + int count = 0; + while (it.hasNext()) { + Object o = it.next(); + if(o instanceof BMPImageReaderSPI) { + count++; + System.out.println("Found next BMPImageReaderSPI, count = " +count); + } + } + if(count > 1) { + throw new RuntimeException("Too many instances of the BMPImageReaderSPI was registered!"); + } + } + + public static void main(String args[]) throws Exception{ + RegisterPluginTwiceTest fnio = new RegisterPluginTwiceTest(); + } + + + /** + Not a perfect implementation of SPI. This is just a dummy implementation + which denotes some arbitrary reader class. The intention is to check how this + is getting registered in the registry. Hence some of the values in this class + may be inappropriate.. + */ + public static class BMPImageReaderSPI extends javax.imageio.spi.ImageReaderSpi{ + + private static final String vendorName = "Javasoft"; + + private static final String version = "2.0"; + + private static final String[] names = { "bmp" }; + + private static final String[] suffixes = { "bmp" }; + + private static final String[] MIMETypes = { "image/x-bmp"}; + + private static final String readerClassName = + "com.sun.imageio.plugins.png.PNGImageReader"; + + private static final String[] writerSpiNames = { + "com.sun.imageio.plugins.png.PNGImageWriterSpi" + }; + + public BMPImageReaderSPI() { + super(vendorName, + version, + names, + suffixes, + MIMETypes, + readerClassName, + STANDARD_INPUT_TYPE, + writerSpiNames, + false, + null, null, + null, null, + true, + "BMP Native Metadata", + "com.sun.imageio.plugins.png.PNGMetadataFormat", + null, null + ); + } + + public String getDescription(Locale locale) { + return "Standard BMP image reader"; + } + + public boolean canDecodeInput(Object input) throws IOException { + if (!(input instanceof ImageInputStream)) { + return false; + } + + ImageInputStream stream = (ImageInputStream)input; + byte[] b = new byte[8]; + stream.mark(); + stream.readFully(b); + stream.reset(); + + return (b[0] == (byte)137 && + b[1] == (byte)80 && + b[2] == (byte)78 && + b[3] == (byte)71 && + b[4] == (byte)13 && + b[5] == (byte)10 && + b[6] == (byte)26 && + b[7] == (byte)10); + } + + public ImageReader createReaderInstance(Object extension) { + //return new PNGImageReader(this); + return null; + } + public void onRegistration(ServiceRegistry sr, Class category) { + //System.out.println("Registered "+category); + super.onRegistration(sr, category); + } + + public void onDeregistration(ServiceRegistry sr, Class category) { + //System.out.println("De-Registered "+category); + //super.onRegistration(sr, category); + } + } +} diff --git a/test/javax/imageio/spi/SpiTest.java b/test/javax/imageio/spi/SpiTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/SpiTest.java @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2001, 2017, 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 4395376 + * @summary Performs various sanity checks on Spi class constructors and get + * methods + */ + +import java.util.Iterator; +import java.util.Locale; + +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriter; +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.IIOServiceProvider; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.spi.ImageReaderWriterSpi; +import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.spi.ServiceRegistry; + +public class SpiTest { + + String vendorName = null; + String version = null; + String[] names = null; + String[] suffixes = null; + String[] MIMETypes = null; + String readerClassName = null; + String writerClassName = null; + Class[] inputTypes = null; + Class[] outputTypes = null; + String[] writerSpiNames = null; + String[] readerSpiNames = null; + String nativeStreamMetadataFormatName = null; + String nativeStreamMetadataFormatClassName = null; + String[] extraStreamMetadataFormatNames = null; + String[] extraStreamMetadataFormatClassNames = null; + String nativeImageMetadataFormatName = null; + String nativeImageMetadataFormatClassName = null; + String[] extraImageMetadataFormatNames = null; + String[] extraImageMetadataFormatClassNames = null; + + private void error(String message) { + // System.out.println("Error: " + message); + throw new RuntimeException(message); + } + + private void testSpi(IIOServiceProvider spi) { + if (spi.getVendorName() == null) { + error(spi + " getVendorName == null!"); + } + if (spi.getVersion() == null) { + error(spi + " getVersion == null!"); + } + } + + private void testSpi(ImageReaderWriterSpi spi) { + testSpi((IIOServiceProvider)spi); + if (spi.getFormatNames() == null) { + error("spi.getFormatNames == null!"); + } + String[] suffixes = spi.getFileSuffixes(); + if (suffixes != null && suffixes.length == 0) { + error("suffixes.length == 0!"); + } + String[] MIMETypes = spi.getMIMETypes(); + if (MIMETypes != null && MIMETypes.length == 0) { + error("MIMETypes.length == 0!"); + } + if (spi.getPluginClassName() == null) { + error("spi.getPluginClassName == null!"); + } + String[] extraStreamMetadataFormatNames = + spi.getExtraStreamMetadataFormatNames(); + if (extraStreamMetadataFormatNames != null && + extraStreamMetadataFormatNames.length == 0) { + error("extraStreamMetadataFormatNames.length == 0!"); + } + String[] extraImageMetadataFormatNames = + spi.getExtraImageMetadataFormatNames(); + if (extraImageMetadataFormatNames != null && + extraImageMetadataFormatNames.length == 0) { + error("extraImageMetadataFormatNames.length == 0!"); + } + } + + public void testSpi(ImageReaderSpi spi) { + testSpi((ImageReaderWriterSpi)spi); + Class[] inputTypes = spi.getInputTypes(); + if (inputTypes == null) { + error("inputTypes == null!"); + } + if (inputTypes.length == 0) { + error("inputTypes.length == 0!"); + } + String[] writerSpiNames = spi.getImageWriterSpiNames(); + if (writerSpiNames != null && writerSpiNames.length == 0) { + error("writerSpiNames.length == 0!"); + } + } + + public void testSpi(ImageWriterSpi spi) { + testSpi((ImageReaderWriterSpi)spi); + Class[] outputTypes = spi.getOutputTypes(); + if (outputTypes == null) { + error("outputTypes == null!"); + } + if (outputTypes.length == 0) { + error("outputTypes.length == 0!"); + } + String[] readerSpiNames = spi.getImageReaderSpiNames(); + if (readerSpiNames != null && readerSpiNames.length == 0) { + error("readerSpiNames.length == 0!"); + } + } + + private void resetConstructorArguments() { + vendorName = null; + version = null; + names = null; + suffixes = null; + MIMETypes = null; + readerClassName = null; + inputTypes = null; + outputTypes = null; + writerSpiNames = null; + readerSpiNames = null; + nativeStreamMetadataFormatName = null; + nativeStreamMetadataFormatClassName = null; + extraStreamMetadataFormatNames = null; + extraStreamMetadataFormatClassNames = null; + nativeImageMetadataFormatName = null; + nativeImageMetadataFormatClassName = null; + extraImageMetadataFormatNames = null; + extraImageMetadataFormatClassNames = null; + } + + private ImageReaderSpi constructImageReaderSpi() { + return new ImageReaderSpi(vendorName, + version, + names, + suffixes, + MIMETypes, + readerClassName, + inputTypes, + writerSpiNames, + false, + nativeStreamMetadataFormatName, + nativeStreamMetadataFormatClassName, + extraStreamMetadataFormatNames, + extraStreamMetadataFormatClassNames, + false, + nativeImageMetadataFormatName, + nativeImageMetadataFormatClassName, + extraImageMetadataFormatNames, + extraImageMetadataFormatClassNames) { + + public String getDescription(Locale locale) { + return null; + } + + public boolean canDecodeInput(Object source) { + return false; + } + + public ImageReader createReaderInstance(Object extension) { + return null; + } + }; + } + + private ImageWriterSpi constructImageWriterSpi() { + return new ImageWriterSpi(vendorName, + version, + names, + suffixes, + MIMETypes, + writerClassName, + outputTypes, + readerSpiNames, + false, + nativeStreamMetadataFormatName, + nativeStreamMetadataFormatClassName, + extraStreamMetadataFormatNames, + extraStreamMetadataFormatClassNames, + false, + nativeImageMetadataFormatName, + nativeImageMetadataFormatClassName, + extraImageMetadataFormatNames, + extraImageMetadataFormatClassNames) { + + public String getDescription(Locale locale) { + return null; + } + + public boolean canEncodeImage(ImageTypeSpecifier type) { + return false; + } + + public ImageWriter createWriterInstance(Object extension) { + return null; + } + }; + } + + private void checkImageReaderSpiConstructor(boolean shouldFail) { + boolean gotIAE = false; + try { + constructImageReaderSpi(); + } catch (Exception e) { + if (!(e instanceof IllegalArgumentException)) { + error("Got exception " + e); + } else { + gotIAE = true; + } + } + if (gotIAE != shouldFail) { + if (gotIAE) { + error("ImageReaderSpi constructor threw an IAE!"); + } else { + error("ImageReaderSpi constructor didn't throw an IAE!"); + } + } + } + + private void checkImageWriterSpiConstructor(boolean shouldFail) { + boolean gotIAE = false; + try { + constructImageWriterSpi(); + } catch (Exception e) { + if (!(e instanceof IllegalArgumentException)) { + error("Got exception " + e); + } else { + gotIAE = true; + } + } + if (gotIAE != shouldFail) { + if (gotIAE) { + error("ImageWriterSpi constructor threw an IAE!"); + } else { + error("ImageWriterSpi constructor didn't throw an IAE!"); + } + } + } + + public void testImageReaderSpiConstructor() { + resetConstructorArguments(); + + checkImageReaderSpiConstructor(true); + vendorName = "My Vendor"; + checkImageReaderSpiConstructor(true); + version = "My Version"; + checkImageReaderSpiConstructor(true); + names = new String[0]; + checkImageReaderSpiConstructor(true); + names = new String[1]; + names[0] = "My Format Name"; + checkImageReaderSpiConstructor(true); + readerClassName = "com.mycompany.Reader"; + checkImageReaderSpiConstructor(true); + inputTypes = new Class[0]; + checkImageReaderSpiConstructor(true); + inputTypes = new Class[1]; + inputTypes[0] = Object.class; + // Now it should work + checkImageReaderSpiConstructor(false); + + // Test normalization of zero-length arrays + suffixes = new String[0]; + MIMETypes = new String[0]; + writerSpiNames = new String[0]; + extraStreamMetadataFormatNames = new String[0]; + extraImageMetadataFormatNames = new String[0]; + + ImageReaderSpi spi = constructImageReaderSpi(); + if (spi.getFileSuffixes() != null) { + error("Failed to normalize suffixes!"); + } + if (spi.getMIMETypes() != null) { + error("Failed to normalize MIMETypes!"); + } + if (spi.getImageWriterSpiNames() != null) { + error("Failed to normalize writerSpiNames!"); + } + if (spi.getExtraStreamMetadataFormatNames() != null) { + error("Failed to normalize extraStreamMetadataFormatNames!"); + } + if (spi.getExtraImageMetadataFormatNames() != null) { + error("Failed to normalize extraImageMetadataFormatNames!"); + } + } + + public void testImageWriterSpiConstructor() { + resetConstructorArguments(); + + checkImageWriterSpiConstructor(true); + vendorName = "My Vendor"; + checkImageWriterSpiConstructor(true); + version = "My Version"; + checkImageWriterSpiConstructor(true); + names = new String[0]; + checkImageWriterSpiConstructor(true); + names = new String[1]; + names[0] = "My Format Name"; + checkImageWriterSpiConstructor(true); + writerClassName = "com.mycompany.Writer"; + checkImageWriterSpiConstructor(true); + outputTypes = new Class[0]; + checkImageWriterSpiConstructor(true); + outputTypes = new Class[1]; + outputTypes[0] = Object.class; + // Now it should work + checkImageWriterSpiConstructor(false); + + // Test normalization of zero-length arrays + suffixes = new String[0]; + MIMETypes = new String[0]; + readerSpiNames = new String[0]; + extraStreamMetadataFormatNames = new String[0]; + extraStreamMetadataFormatClassNames = new String[0]; + extraImageMetadataFormatNames = new String[0]; + extraImageMetadataFormatClassNames = new String[0]; + + ImageWriterSpi spi = constructImageWriterSpi(); + if (spi.getFileSuffixes() != null) { + error("Failed to normalize suffixes!"); + } + if (spi.getMIMETypes() != null) { + error("Failed to normalize MIMETypes!"); + } + if (spi.getImageReaderSpiNames() != null) { + error("Failed to normalize readerSpiNames!"); + } + if (spi.getExtraStreamMetadataFormatNames() != null) { + error("Failed to normalize extraStreamMetadataFormatNames!"); + } + if (spi.getExtraImageMetadataFormatNames() != null) { + error("Failed to normalize extraImageMetadataFormatNames!"); + } + } + + public SpiTest() { + testImageReaderSpiConstructor(); + testImageWriterSpiConstructor(); + + ServiceRegistry registry = IIORegistry.getDefaultInstance(); + Iterator readers = registry.getServiceProviders(ImageReaderSpi.class, + false); + while (readers.hasNext()) { + ImageReaderSpi rspi = (ImageReaderSpi)readers.next(); + System.out.println("*** Testing " + rspi.getClass().getName()); + testSpi(rspi); + } + + Iterator writers = registry.getServiceProviders(ImageWriterSpi.class, + false); + while (writers.hasNext()) { + ImageWriterSpi wspi = (ImageWriterSpi)writers.next(); + System.out.println("*** Testing " + wspi.getClass().getName()); + testSpi(wspi); + } + } + + public static void main(String[] args) { + new SpiTest(); + } +} diff --git a/test/javax/imageio/spi/SpiVersionNumbers.java b/test/javax/imageio/spi/SpiVersionNumbers.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/spi/SpiVersionNumbers.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2001, 2017, 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 4415450 + * @summary Checks the version number for the standard stream Spis + */ + +import javax.imageio.spi.IIOServiceProvider; + +import com.sun.imageio.spi.FileImageInputStreamSpi; +import com.sun.imageio.spi.FileImageOutputStreamSpi; +import com.sun.imageio.spi.InputStreamImageInputStreamSpi; +import com.sun.imageio.spi.OutputStreamImageOutputStreamSpi; +import com.sun.imageio.spi.RAFImageInputStreamSpi; +import com.sun.imageio.spi.RAFImageOutputStreamSpi; + +public class SpiVersionNumbers { + + private static void check(IIOServiceProvider spi) { + String version = spi.getVersion(); + if (!version.equals("1.0")) { + throw new RuntimeException("Provider " + + spi.getClass().getName() + + " has version " + version + "!"); + } + } + + public static void main(String[] args) { + check(new FileImageInputStreamSpi()); + check(new InputStreamImageInputStreamSpi()); + check(new RAFImageInputStreamSpi()); + + check(new FileImageOutputStreamSpi()); + check(new OutputStreamImageOutputStreamSpi()); + check(new RAFImageOutputStreamSpi()); + } + +} diff --git a/test/javax/imageio/stream/BitPadding.java b/test/javax/imageio/stream/BitPadding.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/BitPadding.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2017, 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 4430395 + * @summary Checks if write(int) properly pads unwritten bits with zeros + */ + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +import javax.imageio.stream.FileCacheImageOutputStream; + +public class BitPadding { + + public static void main(String[] args) throws IOException { + OutputStream ostream = new ByteArrayOutputStream(); + File f = null; + FileCacheImageOutputStream fcios = + new FileCacheImageOutputStream(ostream, f); + fcios.writeBit(1); + fcios.write(96); + + fcios.seek(0); + int r1 = fcios.read(); + if (r1 != 128 ) { + throw new RuntimeException("Failed, first byte is " + r1); + } + + int r2 = fcios.read(); + if (r2 != 96) { + throw new RuntimeException("Failed, second byte is " + r2); + } + } +} diff --git a/test/javax/imageio/stream/DeleteOnExitTest.java b/test/javax/imageio/stream/DeleteOnExitTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/DeleteOnExitTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005, 2017, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class DeleteOnExitTest { + public static void main(String[] args) throws IOException { + ByteArrayInputStream is = + new ByteArrayInputStream(new byte[100]); + ByteArrayOutputStream os = + new ByteArrayOutputStream(); + + String tmp = System.getProperty("java.io.tmpdir", "."); + System.out.println("tmp: " + tmp); + + // count number of files before test + ImageIO.setUseCache(true); + ImageIO.setCacheDirectory(new File(tmp)); + + File tmpDir = ImageIO.getCacheDirectory(); + System.out.println("tmpDir is " + tmpDir); + int fnum_before = tmpDir.list().length; + System.out.println("Files before test: " + fnum_before); + + ImageInputStream iis = + ImageIO.createImageInputStream(is); + System.out.println("iis = " + iis); + + ImageInputStream iis2 = + ImageIO.createImageInputStream(is); + + ImageOutputStream ios = + ImageIO.createImageOutputStream(os); + System.out.println("ios = " + ios); + + ImageOutputStream ios2 = + ImageIO.createImageOutputStream(os); + + iis2.close(); + ios2.close(); + int fnum_after = tmpDir.list().length; + System.out.println("Files after test: " + fnum_after); + + if (fnum_before == fnum_after) { + throw new RuntimeException("Test failed: cache was not used."); + } + } +} diff --git a/test/javax/imageio/stream/DeleteOnExitTest.sh b/test/javax/imageio/stream/DeleteOnExitTest.sh new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/DeleteOnExitTest.sh @@ -0,0 +1,69 @@ +# Copyright (c) 2005, 2017, 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 6291034 +# @run shell DeleteOnExitTest.sh +# @summary Verify that temporary imageio files files are deleted on VM exit. + +if [ -z "${TESTSRC}" ]; then + echo "TESTSRC undefined: defaulting to ." + TESTSRC=. +fi + +if [ -z "${TESTCLASSES}" ]; then + echo "TESTCLASSES undefined: defaulting to ." + TESTCLASSES=. +fi + +if [ -z "${TESTJAVA}" ]; then + echo "TESTJAVA undefined: can't continue." + exit 1 +fi + +echo "TESTJAVA=${TESTJAVA}" +echo "TESTSRC=${TESTSRC}" +echo "TESTCLASSES=${TESTCLASSES}" +cd ${TESTSRC} +${COMPILEJAVA}/bin/javac -d ${TESTCLASSES} DeleteOnExitTest.java + +cd ${TESTCLASSES} + +numfiles0=`ls ${TESTCLASSES} | grep "imageio*.tmp" | wc -l` + +${TESTJAVA}/bin/java ${TESTVMOPTS} \ + -Djava.io.tmpdir=${TESTCLASSES} DeleteOnExitTest + +if [ $? -ne 0 ] + then + echo "Test fails: exception thrown!" + exit 1 +fi + +numfiles1=`ls ${TESTCLASSES} | grep "imageio*.tmp" | wc -l` + +if [ $numfiles0 -ne $numfiles1 ] + then + echo "Test fails: tmp file exists!" + exit 1 +fi +echo "Test passed." +exit 0 diff --git a/test/javax/imageio/stream/FileCacheImageInputStreamNullTest.java b/test/javax/imageio/stream/FileCacheImageInputStreamNullTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/FileCacheImageInputStreamNullTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2001, 2017, 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 4428802 + * @summary Checks for IAE from FileCacheImageInputStream constructor with a + * null value for 'stream' + */ + +import javax.imageio.stream.FileCacheImageInputStream; + +public class FileCacheImageInputStreamNullTest { + + public static void main (String[] args) throws Exception { + boolean gotIAE = false; + try { + FileCacheImageInputStream fciis = + new FileCacheImageInputStream(null, null); + } catch (IllegalArgumentException e) { + gotIAE = true; + } + + if (!gotIAE) { + throw new RuntimeException + ("Failed to get IllegalArgumentException!"); + } + } +} diff --git a/test/javax/imageio/stream/FlushBefore.java b/test/javax/imageio/stream/FlushBefore.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/FlushBefore.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2001, 2017, 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 4431503 + * @summary Checks if flushBefore(pos) throws an IndexOutOfBoundsException if + * pos lies in the flushed portion of the stream + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import javax.imageio.stream.FileCacheImageOutputStream; +import javax.imageio.stream.ImageOutputStream; +import javax.imageio.stream.MemoryCacheImageOutputStream; + +public class FlushBefore { + + public static void main(String[] args) throws IOException { + OutputStream ostream = new ByteArrayOutputStream(); + + FileCacheImageOutputStream fcios = + new FileCacheImageOutputStream(ostream, null); + test(fcios); + + MemoryCacheImageOutputStream mcios = + new MemoryCacheImageOutputStream(ostream); + test(mcios); + } + + private static void test(ImageOutputStream ios) throws IOException { + try { + ios.write(new byte[10], 0, 10); + ios.flushBefore(5); + ios.flushBefore(4); + + throw new RuntimeException + ("Failed to get IndexOutOfBoundsException!"); + } catch (IndexOutOfBoundsException e) { + } + } +} diff --git a/test/javax/imageio/stream/MemoryCacheImageOutputStreamTest.java b/test/javax/imageio/stream/MemoryCacheImageOutputStreamTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/MemoryCacheImageOutputStreamTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001, 2017, 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 4417672 4422328 + * @summary Checks the functionality of MemoryCacheImageOutputStream + * particularly with regard to seeking and flushing + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.stream.ImageOutputStream; +import javax.imageio.stream.MemoryCacheImageOutputStream; + +public class MemoryCacheImageOutputStreamTest { + + public static void main(String[] args) throws IOException { + try { + MemoryCacheImageOutputStream stream = + new MemoryCacheImageOutputStream(new ByteArrayOutputStream()); + stream.write(0); // or write anything, for that matter + stream.flush(); + } catch (Exception e) { + throw new RuntimeException("Error flushing stream: " + e); + } + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ImageOutputStream ios = new MemoryCacheImageOutputStream(os); + + byte[] b = new byte[30*256]; + byte byteVal = (byte)0; + for (int i = 0; i < b.length; i++) { + b[i] = byteVal++; + } + + // Write 261,120 bytes + for (int i = 0; i < 34; i++) { + ios.write(b); + } + // Scatter 256 values at positions 1000, 2000, ... + // Using both write(int) and write(byte[]) + byte[] buf = new byte[1]; + for (int i = 0; i < 256; i += 2) { + ios.seek(1000*i); + ios.write(i); + + ios.seek(1000*(i + 1)); + buf[0] = (byte)(i + 1); + ios.write(buf); + } + + // Re-read scattered values + for (int i = 0; i < 256; i++) { + ios.seek(1000*i); + int val = ios.read(); + if (val != i) { + System.out.println("Got bad value (1) at pos = " + (1000*i)); + } + } + + // Discard two buffers and re-read scattered values + ios.flushBefore(2*8192); + + for (int i = 0; i < 256; i++) { + long pos = 1000*i; + if (pos >= 2*8192) { + ios.seek(pos); + int val = ios.read(); + if (val != i) { + System.out.println("Got bad value (2) at pos = " + (1000*i)); + } + } + } + ios.close(); + + byte[] data = os.toByteArray(); + for (int i = 0; i < data.length; i++) { + byte val = data[i]; + if ((i < 256000) && (i % 1000) == 0) { + if (val != (byte)(i/1000)) { + System.out.println("Got bad value (3) at pos = " + i); + } + } else { + byte gval = (byte)((i % (30*256)) % 256); + if (val != gval) { + System.out.println("Got bad value (4) at pos = " + i + + "(got " + (val & 0xff) + + " wanted " + (gval & 0xff) +")"); + } + } + } + } +} diff --git a/test/javax/imageio/stream/ReadBytesIIOByteBuffer.java b/test/javax/imageio/stream/ReadBytesIIOByteBuffer.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/ReadBytesIIOByteBuffer.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2004, 2017, 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 4446906 + * @summary Checks if ImageInputStreamImpl.readBytes(IIOByteBuffer) tests for + * len < 0 + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.imageio.stream.IIOByteBuffer; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.MemoryCacheImageInputStream; + +public class ReadBytesIIOByteBuffer { + + public static void main(String[] argv) { + byte[] bar = {1, 1, 1}; + InputStream is = new ByteArrayInputStream(bar); + + ImageInputStream iis = new MemoryCacheImageInputStream(is); + byte[] b = new byte[10]; + IIOByteBuffer iiob = new IIOByteBuffer(b, 0, b.length); + try { + iis.readBytes(iiob, -1); + } catch (IndexOutOfBoundsException e) { + return; + } catch (Exception e) { + throw new RuntimeException("Unexpected exception: " + e); + } + throw new RuntimeException("No exception thrown for len < 0!"); + } +} diff --git a/test/javax/imageio/stream/ReadFullyTest.java b/test/javax/imageio/stream/ReadFullyTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/ReadFullyTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2017, 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 4422263 + * @summary Checks that ImageInputStream.readFully(type[], int int) handles sign + * extension and byte ordering correctly + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.ByteOrder; + +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.MemoryCacheImageInputStream; + +public class ReadFullyTest { + + static final ByteOrder bigEndian = ByteOrder.BIG_ENDIAN; + static final ByteOrder littleEndian = ByteOrder.LITTLE_ENDIAN; + + private static void expect(long e, long g) { + if (e != g) { + throw new RuntimeException("Expected " + e + ", got " + g); + } + } + + public static void main (String args[]) { + try { + byte[] b = { + (byte)0x11, (byte)0x22, // low low + (byte)0x44, (byte)0x99, // low high + (byte)0xAA, (byte)0x33, // high low + (byte)0xBB, (byte)0xCC // high high + }; + InputStream in = new ByteArrayInputStream(b); + ImageInputStream iin = new MemoryCacheImageInputStream(in); + + short[] s = new short[b.length/2]; + char[] c = new char[b.length/2]; + int[] i = new int[b.length/4]; + long[] l = new long[b.length/8]; + float[] f = new float[b.length/4]; + double[] d = new double[b.length/8]; + + iin.seek(0L); + iin.setByteOrder(bigEndian); + iin.readFully(s, 0, s.length); + expect(s[0] & 0xffff, 0x1122); + expect(s[1] & 0xffff, 0x4499); + expect(s[2] & 0xffff, 0xAA33); + expect(s[3] & 0xffff, 0xBBCC); + + iin.seek(0L); + iin.setByteOrder(littleEndian); + iin.readFully(s, 0, s.length); + expect(s[0] & 0xffff, 0x2211); + expect(s[1] & 0xffff, 0x9944); + expect(s[2] & 0xffff, 0x33AA); + expect(s[3] & 0xffff, 0xCCBB); + + iin.seek(0L); + iin.setByteOrder(bigEndian); + iin.readFully(c, 0, c.length); + expect(c[0], 0x1122); + expect(c[1], 0x4499); + expect(c[2], 0xAA33); + expect(c[3], 0xBBCC); + + iin.seek(0L); + iin.setByteOrder(littleEndian); + iin.readFully(c, 0, c.length); + expect(c[0], 0x2211); + expect(c[1], 0x9944); + expect(c[2], 0x33AA); + expect(c[3], 0xCCBB); + + iin.seek(0L); + iin.setByteOrder(bigEndian); + iin.readFully(i, 0, i.length); + expect(i[0] & 0xffffffff, 0x11224499); + expect(i[1] & 0xffffffff, 0xAA33BBCC); + + iin.seek(0L); + iin.setByteOrder(littleEndian); + iin.readFully(i, 0, i.length); + expect(i[0] & 0xffffffff, 0x99442211); + expect(i[1] & 0xffffffff, 0xCCBB33AA); + + iin.seek(0L); + iin.setByteOrder(bigEndian); + iin.readFully(f, 0, f.length); + expect(Float.floatToIntBits(f[0]) & 0xffffffff, 0x11224499); + expect(Float.floatToIntBits(f[1]) & 0xffffffff, 0xAA33BBCC); + + iin.seek(0L); + iin.setByteOrder(littleEndian); + iin.readFully(f, 0, f.length); + expect(Float.floatToIntBits(f[0]) & 0xffffffff, 0x99442211); + expect(Float.floatToIntBits(f[1]) & 0xffffffff, 0xCCBB33AA); + + iin.seek(0L); + iin.setByteOrder(bigEndian); + iin.readFully(l, 0, l.length); + expect(l[0], 0x11224499AA33BBCCL); + + iin.seek(0L); + iin.setByteOrder(littleEndian); + iin.readFully(l, 0, l.length); + expect(l[0], 0xCCBB33AA99442211L); + + iin.seek(0L); + iin.setByteOrder(bigEndian); + iin.readFully(d, 0, d.length); + expect(Double.doubleToLongBits(d[0]), 0x11224499AA33BBCCL); + + iin.seek(0L); + iin.setByteOrder(littleEndian); + iin.readFully(d, 0, d.length); + expect(Double.doubleToLongBits(d[0]), 0xCCBB33AA99442211L); + } catch (Exception ex) { + throw new RuntimeException("Got exception " + ex); + } + } +} diff --git a/test/javax/imageio/stream/ReadUnsignedIntTest.java b/test/javax/imageio/stream/ReadUnsignedIntTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/ReadUnsignedIntTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003, 2017, 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 4949609 + * @summary Tests that the readUnsignedInt returns the positive value + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.stream.ImageInputStream; + +public class ReadUnsignedIntTest { + + public static void main(String[] args) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + dos.writeInt(1); + dos.writeInt(0x7fffffff); + dos.writeInt(0x8fffffff); + dos.writeInt(0xffffffff); + + dos.close(); + + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ImageInputStream iis = ImageIO.createImageInputStream(bais); + for (int i=0; i<4; i++) { + long res = iis.readUnsignedInt(); + if (res <= 0) { + throw new RuntimeException("Negative number was read: "+ + Long.toString(res, 16)); + } + } + } +} diff --git a/test/javax/imageio/stream/StreamFlush.java b/test/javax/imageio/stream/StreamFlush.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/StreamFlush.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2001, 2017, 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 4414990 4415041 + * @summary Checks that the output is flushed properly when using various + * ImageOutputStreams and writers + */ + +import java.awt.image.BufferedImage; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.imageio.stream.ImageOutputStream; + +public class StreamFlush { + + public static void main(String[] args) throws IOException { + ImageIO.setUseCache(true); + + // Create a FileImageOutputStream from a FileOutputStream + File temp1 = File.createTempFile("imageio", ".tmp"); + temp1.deleteOnExit(); + ImageOutputStream fios = ImageIO.createImageOutputStream(temp1); + + // Create a FileCacheImageOutputStream from a BufferedOutputStream + File temp2 = File.createTempFile("imageio", ".tmp"); + temp2.deleteOnExit(); + FileOutputStream fos2 = new FileOutputStream(temp2); + BufferedOutputStream bos = new BufferedOutputStream(fos2); + ImageOutputStream fcios1 = ImageIO.createImageOutputStream(bos); + + // Create a FileCacheImageOutputStream from a ByteArrayOutputStream + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream fcios2 = ImageIO.createImageOutputStream(baos); + + BufferedImage bi = + new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR); + + ImageIO.write(bi, "jpg", fios); // No bug, check it anyway + ImageIO.write(bi, "png", fcios1); // Bug 4414990 + ImageIO.write(bi, "jpg", fcios2); // Bug 4415041 + + // It should not be necessary to flush any of the streams + // If flushing does make a difference, it indicates a bug + // in the writer or the stream implementation + + // Get length of temp1 before and after flushing + long file1NoFlushLength = temp1.length(); + fios.flush(); + long file1FlushLength = temp1.length(); + + // Get length of temp2 before and after flushing + long file2NoFlushLength = temp2.length(); + fcios1.flush(); + bos.flush(); + long file2FlushLength = temp2.length(); + + byte[] b0 = baos.toByteArray(); + int cacheNoFlushLength = b0.length; + fcios2.flush(); + byte[] b1 = baos.toByteArray(); + int cacheFlushLength = b1.length; + + if (file1NoFlushLength != file1FlushLength) { + // throw new RuntimeException + System.out.println + ("FileImageOutputStream not flushed!"); + } + + if (file2NoFlushLength != file2FlushLength) { + // throw new RuntimeException + System.out.println + ("FileCacheImageOutputStream/BufferedOutputStream not flushed!"); + } + + if (cacheNoFlushLength != cacheFlushLength) { + // throw new RuntimeException + System.out.println + ("FileCacheImageOutputStream/ByteArrayOutputStream not flushed!"); + } + } +} diff --git a/test/javax/imageio/stream/WriteBitsTest.java b/test/javax/imageio/stream/WriteBitsTest.java new file mode 100644 --- /dev/null +++ b/test/javax/imageio/stream/WriteBitsTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2002, 2017, 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 4507868 + * @summary Checks that ImageOutputStreamImpl.writeBits() advances the stream + * position and bit offset correctly. Also verifies that the + * MemoryCacheImageOutputStream.read() variants reset the bitOffset + * before the read actually occurs. + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.stream.ImageOutputStream; +import javax.imageio.stream.MemoryCacheImageOutputStream; + +public class WriteBitsTest { + + private static void verify(ImageOutputStream ios, + long expstreampos, int expbitoffset) + throws IOException, RuntimeException + { + long actstreampos = ios.getStreamPosition(); + int actbitoffset = ios.getBitOffset(); + + if ((actstreampos != expstreampos) || + (actbitoffset != expbitoffset)) + { + System.err.println("Expected stream position: " + expstreampos + + " Actual: " + actstreampos); + System.err.println("Expected bit offset: " + expbitoffset + + " Actual: " + actbitoffset); + throw new RuntimeException("Test failed."); + } + } + + public static void main(String argv[]) throws RuntimeException { + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + MemoryCacheImageOutputStream mcios = new + MemoryCacheImageOutputStream(ostream); + + try { + // verify correct writeBits() functionality + long streampos = 0; + int bitoffset = 0; + + mcios.setBitOffset(bitoffset); + verify(mcios, streampos, bitoffset); + + bitoffset = 3; + mcios.setBitOffset(bitoffset); + verify(mcios, streampos, bitoffset); + + for (int incr = 3; incr <= 15; incr += 12) { + for (int i = 0; i < 64; i += incr) { + mcios.writeBits(10, incr); + + bitoffset += incr; + + if (bitoffset > 7) { + int stroffset = bitoffset / 8; + bitoffset = bitoffset % 8; + streampos += stroffset; + } + + verify(mcios, streampos, bitoffset); + } + } + + // verify correct read(byte[], int, int) functionality + byte[] bytearr = new byte[2]; + mcios.seek(2); + mcios.setBitOffset(3); + int numread = mcios.read(bytearr, 0, 2); + if (numread != 2) { + throw new RuntimeException("Error in mcios.read([BII)I"); + } + verify(mcios, 4, 0); + + // verify correct read() functionality + mcios.setBitOffset(3); + mcios.read(); + verify(mcios, 5, 0); + } catch (IOException e) { + throw new RuntimeException("Unexpected IOException: " + e); + } + } +} diff --git a/test/javax/management/loading/ParserInfiniteLoopTest.java b/test/javax/management/loading/ParserInfiniteLoopTest.java --- a/test/javax/management/loading/ParserInfiniteLoopTest.java +++ b/test/javax/management/loading/ParserInfiniteLoopTest.java @@ -31,9 +31,9 @@ * @author Luis-Miguel Alventosa * @run clean ParserInfiniteLoopTest * @run build ParserInfiniteLoopTest - * @run main/othervm/timeout=5 ParserInfiniteLoopTest mlet1.html - * @run main/othervm/timeout=5 ParserInfiniteLoopTest mlet2.html - * @run main/othervm/timeout=5 ParserInfiniteLoopTest mlet3.html + * @run main/othervm ParserInfiniteLoopTest mlet1.html + * @run main/othervm ParserInfiniteLoopTest mlet2.html + * @run main/othervm ParserInfiniteLoopTest mlet3.html */ import java.io.File; diff --git a/test/javax/sound/midi/Devices/ClosedReceiver.java b/test/javax/sound/midi/Devices/ClosedReceiver.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Devices/ClosedReceiver.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Synthesizer; + +/** + * @test + * @bug 4616517 + * @summary Receiver.send() does not work properly + */ +public class ClosedReceiver { + + public static void main(String[] args) throws Exception { + out("#4616517: Receiver.send() does not work properly"); + if (!isMidiInstalled()) { + out("Soundcard does not exist or sound drivers not installed!"); + out("This test requires sound drivers for execution."); + return; + } + + boolean passed = true; + + passed &= testReceiverSend(); + passed &= testClosedReceivers(); + if (passed) { + out("Test PASSED."); + } else { + throw new Exception("Test FAILED."); + } + } + + /** + * Execute Receiver.send() and expect that there is no exception. + */ + private static boolean testReceiverSend() { + boolean result = true; + + Receiver receiver; + ShortMessage shMsg = new ShortMessage(); + + try { + receiver = MidiSystem.getReceiver(); + shMsg.setMessage(ShortMessage.NOTE_ON, 0,60, 93); + try { + receiver.send( shMsg, -1 ); + } catch(IllegalStateException ilEx) { + ilEx.printStackTrace(System.out); + out("IllegalStateException was thrown incorrectly!"); + result = false; + } + receiver.close(); + } catch(MidiUnavailableException e) { + out("Midi unavailable, cannot test."); + } catch(InvalidMidiDataException ine) { + out("InvalidMidiDataException, cannot test."); + } + return result; + } + + private static boolean testClosedReceivers() { + boolean result = true; + Receiver receiver; + Synthesizer synt = null; + + // test Synthesizer's Receiver + try { + synt = MidiSystem.getSynthesizer(); + synt.open(); + } catch(MidiUnavailableException e) { + out("Midi unavailable, cannot test."); + return result; + } + try { + receiver = synt.getReceiver(); + } catch (MidiUnavailableException e) { + out("unable to get Receiver from synthesizer, cannot test."); + return result; + } + result &= testClosedReceiver(receiver); + synt.close(); + + // test all MidiDevices' Receivers + + MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < devices.length; i++) { + try { + MidiDevice device = MidiSystem.getMidiDevice(devices[i]); + if (device.getMaxReceivers() != 0) { + receiver = device.getReceiver(); + result &= testClosedReceiver(receiver); + } + } catch (Exception e) { + out(e); + out("cannot test."); + return result; + } + } + return result; + } + + /** + * Execute send() on a closed Receivers and expect IllegalStateException. + */ + private static boolean testClosedReceiver(Receiver receiver) { + boolean result = true; + out("testing Receiver: " + receiver); + ShortMessage shMsg = new ShortMessage(); + try { + shMsg.setMessage(ShortMessage.NOTE_ON, 0,60, 93); + } catch(InvalidMidiDataException e) { + out(e); + out("unable to construct ShortMessage, cannot test."); + return result; + } + + // begin of test + receiver.close(); + try { + receiver.send( shMsg, -1 ); + out("IllegalStateException was not thrown " + + "on Receiver.send()!"); + result = false; + } catch(IllegalStateException e) { + out("IllegalStateException was thrown. Ok."); + } + return result; + } + + private static void out(Throwable t) { + t.printStackTrace(System.out); + } + + private static void out(String message) { + System.out.println(message); + } + + /** + * Returns true if at least one MIDI (port) device is correctly installed on + * the system. + */ + private static boolean isMidiInstalled() { + boolean result = false; + MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < devices.length; i++) { + try { + MidiDevice device = MidiSystem.getMidiDevice(devices[i]); + result = !(device instanceof Sequencer) + && !(device instanceof Synthesizer); + } catch (Exception e1) { + System.err.println(e1); + } + if (result) + break; + } + return result; + } +} diff --git a/test/javax/sound/midi/Devices/IOLoop.java b/test/javax/sound/midi/Devices/IOLoop.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Devices/IOLoop.java @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Receiver; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.SysexMessage; +import javax.sound.midi.Transmitter; + +/** + * @test + * @bug 4782924 + * @bug 4812168 + * @bug 4356787 + * @summary MIDI i/o. This is an interactive test! Start it and follow the + * instructions. + * @run main/manual IOLoop + */ +public class IOLoop { + private static final int LONG_SYSEX_LENGTH = 2000; + + private static Receiver receiver; + private static Transmitter transmitter; + private static MidiMessage receivedMessage; + private static ByteArrayOutputStream baos; + private static int expectedBytes; + private static int receivedBytes; + private static Object lock = new Object(); + private static long lastTimestamp; + + public static void main(String[] args) throws Exception { + ShortMessage sMsg = new ShortMessage(); + SysexMessage syMsg = new SysexMessage(); + boolean isTestPassed = true; + boolean sysExTestPassed = true; + boolean isTestExecuted = true; + + out("To run this test successfully, you need to have attached"); + out(" your MIDI out port with the MIDI in port."); + + MidiDevice inDev = null; + MidiDevice outDev = null; + + // setup + try { + MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + + int devNum = Integer.decode(args[0]).intValue(); + out("-> opening Transmitter from "+infos[devNum]); + inDev = MidiSystem.getMidiDevice(infos[devNum]); + inDev.open(); + transmitter = inDev.getTransmitter(); + Receiver testReceiver = new TestReceiver(); + transmitter.setReceiver(testReceiver); + + devNum = Integer.decode(args[1]).intValue(); + out("-> opening Receiver from "+infos[devNum]); + outDev = MidiSystem.getMidiDevice(infos[devNum]); + outDev.open(); + receiver = outDev.getReceiver(); + + } catch (Exception e) { + System.out.println(e); + System.out.println("Cannot test!"); + return; + } + + // test + sMsg.setMessage(ShortMessage.NOTE_OFF | 0, 27, 100); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.NOTE_OFF | 0, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.NOTE_OFF | 15, 127, 127); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.NOTE_ON | 4, 27, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.NOTE_ON | 0, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.NOTE_ON | 15, 127, 127); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.POLY_PRESSURE | 11, 98, 99); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.POLY_PRESSURE | 0, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.POLY_PRESSURE | 15, 127, 127); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 13, 1, 63); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 0, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 15, 127, 127); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 2, 120, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 0, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 15, 127, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 6, 30, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 0, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 15, 127, 0); + isTestPassed &= testMessage(sMsg); + + sMsg.setMessage(ShortMessage.PITCH_BEND | 6, 56, 4); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.PITCH_BEND | 0, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.PITCH_BEND | 15, 127, 127); + isTestPassed &= testMessage(sMsg); + + sMsg.setMessage(ShortMessage.MIDI_TIME_CODE, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.MIDI_TIME_CODE, 127, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 1, 77); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 127, 127); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.SONG_SELECT, 51, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.SONG_SELECT, 0, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.SONG_SELECT, 127, 0); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.TUNE_REQUEST); + isTestPassed &= testMessage(sMsg); + + sMsg.setMessage(ShortMessage.TIMING_CLOCK); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.START); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.CONTINUE); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.STOP); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.ACTIVE_SENSING); + isTestPassed &= testMessage(sMsg); + sMsg.setMessage(ShortMessage.SYSTEM_RESET); + isTestPassed &= testMessage(sMsg); + + syMsg.setMessage(new byte[]{(byte) 0xF0, (byte) 0xF7}, 2); + isTestPassed &= testMessage(syMsg); + syMsg.setMessage(new byte[]{(byte) 0xF0, 0x01, (byte) 0xF7}, 3); + isTestPassed &= testMessage(syMsg); + syMsg.setMessage(new byte[]{(byte) 0xF0, 0x02, 0x03, (byte) 0xF7}, 4); + isTestPassed &= testMessage(syMsg); + syMsg.setMessage(new byte[]{(byte) 0xF0, 0x04, 0x05, 0x06, (byte) 0xF7}, 5); + isTestPassed &= testMessage(syMsg); + + if (isTestPassed) { + byte[] sysexArray = new byte[LONG_SYSEX_LENGTH]; + sysexArray[0] = (byte) 0xF0; + for (int i = 1; i < sysexArray.length; i++) { + sysexArray[i] = (byte) (i % 0x80); + } +// syMsg.setMessage(new byte[]{(byte) 0xF7, (byte) ShortMessage.START}, 2); +// sMsg.setMessage(ShortMessage.START); +// isTestPassed &= testMessage(syMsg, sMsg, DEFAULT_SLEEP_INTERVALL); + for (int trial = sysexArray.length; trial > 4; trial -= 1234) { + sleep(500); + sysexArray[trial - 1] = (byte) 0xF7; + syMsg.setMessage(sysexArray, trial); + sysExTestPassed &= testMessage(syMsg); + break; + } + } + + // cleanup + receiver.close(); + transmitter.close(); + inDev.close(); + outDev.close(); + + if (isTestExecuted) { + if (isTestPassed && sysExTestPassed) { + + out("Test PASSED."); + } else { + if (isTestPassed + && !sysExTestPassed + && (System.getProperty("os.name").startsWith("Windows"))) { + out("Some Windows MIDI i/o drivers have a problem with larger "); + out("sys ex messages. The failing sys ex cases are OK, therefore."); + out("Test PASSED."); + } else { + throw new Exception("Test FAILED."); + } + } + } else { + out("Test NOT FAILED"); + } + } + + private static boolean testMessage(MidiMessage message) { + receivedMessage = null; + baos = new ByteArrayOutputStream(); + expectedBytes = message.getLength(); + receivedBytes = 0; + System.out.print("Sending message " + getMessageString(message.getMessage())+"..."); + receiver.send(message, -1); + /* sending 3 bytes can roughly be done in 1 millisecond, + * so this estimate waits at max 3 times longer than the message takes, + * plus a little offset to allow the MIDI subsystem some processing time + */ + int offset = 300; // standard offset 100 millis + if (message instanceof SysexMessage) { + // add a little processing time to sysex messages + offset += 1000; + } + if (receivedBytes < expectedBytes) { + sleep(expectedBytes + offset); + } + boolean equal; + byte[] data = baos.toByteArray(); + if (data.length > 0) { + equal = messagesEqual(message.getMessage(), data); + } else { + equal = messagesEqual(message, receivedMessage); + if (receivedMessage != null) { + data = receivedMessage.getMessage(); + } else { + data = null; + } + } + if (!equal) { + if ((message.getStatus() & 0xF0) == ShortMessage.PITCH_BEND) { + out("NOT failed (may expose a bug in ALSA)"); + equal = true; + sleep(100); + } + if ((message.getStatus() == 0xF6) && (message.getLength() == 1)) { + out("NOT failed (may expose an issue on Solaris)"); + equal = true; + sleep(100); + } + else if ((message.getStatus()) == 0xF0 && message.getLength() < 4) { + out("NOT failed (not a correct sys ex message)"); + equal = true; + sleep(200); + } else { + out("FAILED:"); + out(" received as " + getMessageString(data)); + } + } else { + System.out.println("OK"); + } + return equal; + } + + private static void sleep(int milliseconds) { + synchronized(lock) { + try { + lock.wait(milliseconds); + } catch (InterruptedException e) { + } + } + } + + private static String getMessageString(byte[] data) { + String s; + if (data == null) { + s = ""; + } else if (data.length == 0) { + s = "0-sized array"; + } else { + int status = data[0] & 0xFF; + if (data.length <= 3) { + if (status < 240) { + s = "command 0x" + Integer.toHexString(status & 0xF0) + " channel " + (status & 0x0F); + } else { + s = "status 0x" + Integer.toHexString(status); + } + if (data.length > 1) { + s += " data 0x" + Integer.toHexString(data[1] & 0xFF); + if (data.length > 2) { + s += " 0x" + Integer.toHexString(data[2] & 0xFF); + } + } + } else { + s = "status " + Integer.toHexString(status)+" and length "+data.length+" bytes"; + } + } + return s; + } + + private static boolean messagesEqual(MidiMessage m1, MidiMessage m2) { + if (m1 == null || m2 == null) { + return false; + } + if (m1.getLength() != m2.getLength()) { + return false; + } + byte[] array1 = m1.getMessage(); + byte[] array2 = m2.getMessage(); + return messagesEqual(array1, array2); + } + + private static boolean messagesEqual(byte[] a1, byte[] a2) { + if (a1.length != a2.length) return false; + for (int i = 0; i < a1.length; i++) { + if (a1[i] != a2[i]) { + return false; + } + } + return true; + } + + private static void out(String s) { + System.out.println(s); + System.out.flush(); + } + + private static String canIn(MidiDevice dev) { + if (dev.getMaxTransmitters() != 0) { + return "IN "; + } + return " "; + } + + private static String canOut(MidiDevice dev) { + if (dev.getMaxReceivers() != 0) { + return "OUT "; + } + return " "; + } + + + private static void checkTimestamp(long timestamp) { + // out("checking timestamp..."); + if (timestamp < 1) { + out("timestamp 0 or negative!"); + } + if (timestamp < lastTimestamp) { + out("timestamp not progressive!"); + } + lastTimestamp = timestamp; + } + + private static class TestReceiver implements Receiver { + public void send(MidiMessage message, long timestamp) { + //System.out.print(""+message.getLength()+".."); + checkTimestamp(timestamp); + try { + receivedMessage = message; + if (message.getStatus() == 0xF0 + || (message.getLength() > 3 && message.getStatus() != 0xF7)) { + // sys ex message + byte[] data = message.getMessage(); + baos.write(data); + receivedBytes += data.length; + } + else if (message.getStatus() == 0xF7) { + // sys ex cont'd message + byte[] data = message.getMessage(); + // ignore the prepended 0xF7 + baos.write(data, 1, data.length-1); + receivedBytes += (data.length - 1); + } else { + receivedBytes += message.getLength(); + } + if (receivedBytes >= expectedBytes) { + synchronized(lock) { + lock.notify(); + } + } + System.out.print(""+receivedBytes+".."); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void close() { + } + } +} diff --git a/test/javax/sound/midi/Devices/MidiDeviceGetReceivers.java b/test/javax/sound/midi/Devices/MidiDeviceGetReceivers.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Devices/MidiDeviceGetReceivers.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.util.List; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Transmitter; + +/** + * @test + * @bug 4931387 + * @summary Add methods to MidiDevice to get list of Transmitters and Receivers + */ +public class MidiDeviceGetReceivers { + + private static boolean executed = false; + private static boolean failed = false; + + public static void main(String[] args) throws Exception { + out("unit test 4931387: Add methods to MidiDevice to get list of Transmitters and Receivers"); + doAllTests(); + if (executed) { + if (failed) throw new Exception("Test FAILED!"); + out("Test PASSED."); + } else { + out("Test NOT failed."); + } + } + + private static void doAllTests() { + MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < infos.length; i++) { + MidiDevice device = null; + try { + device = MidiSystem.getMidiDevice(infos[i]); + doTest(device); + } catch (MidiUnavailableException e) { + out("Exception occured when retrieving device "+infos[i]+": "+e); + } + } + if (infos.length == 0) { + out("No MIDI devices exist or sound drivers not installed!"); + } + } + + private static boolean containsReceiver(MidiDevice dev, Receiver rec) { + List recvs = dev.getReceivers(); + return recvs.contains(rec); + } + + private static boolean containsTransmitter(MidiDevice dev, Transmitter tra) { + List tras = dev.getTransmitters(); + return tras.contains(tra); + } + + private static void doTest(MidiDevice device) { + boolean thisFailed = false; + out1("Testing: " + device+"..."); + try { + device.open(); + } catch (Exception e) { + out2("device.open threw exception: "+e); + out2("cannot test this device."); + return; + } + if (device.getMaxReceivers() != 0) { + // device offers receivers + try { + List origList = device.getReceivers(); + Receiver rec = device.getReceiver(); + if (!containsReceiver(device, rec)) { + out2("Getting a receiver did not add it to device list!"); + thisFailed = true; + } + if (origList.contains(rec)) { + out2("Original unmodifiable list was modified by adding a receiver!"); + thisFailed = true; + } + rec.close(); + if (containsReceiver(device, rec)) { + out2("Closing a receiver did not remove it from device list!"); + thisFailed = true; + } + // add a new receiver so that the device.close will really test + // that the receiver is removed + rec = device.getReceiver(); + if (!containsReceiver(device, rec)) { + out2("Getting a receiver again did not add it to device list!"); + thisFailed = true; + } + } catch (MidiUnavailableException e) { + out2("Exception on getting Receiver: " + e); + } + } + if (device.getMaxTransmitters() != 0) { + // device offers transmitters + try { + List origList = device.getTransmitters(); + Transmitter tra = device.getTransmitter(); + if (!containsTransmitter(device, tra)) { + out2("Getting a transmitter did not add it to device list!"); + thisFailed = true; + } + if (origList.contains(tra)) { + out2("Original unmodifiable list was modified by adding a transmitter!"); + thisFailed = true; + } + tra.close(); + if (containsTransmitter(device, tra)) { + out2("Closing a transmitter did not remove it from device list!"); + thisFailed = true; + } + tra = device.getTransmitter(); + if (!containsTransmitter(device, tra)) { + out2("Getting a transmitter again did not add it to device list!"); + thisFailed = true; + } + } catch (MidiUnavailableException e) { + out("Exception on getting Transmitter: " + e); + } + } + try { + device.close(); + if (device.getTransmitters().size() > 0) { + out2(" Device still has transmitters after close() was called!"); + thisFailed = true; + } + if (device.getReceivers().size() > 0) { + out2(" Device still has receivers after close() was called!"); + thisFailed = true; + } + } catch (Exception e) { + out2("device.close threw exception: "+e); + } + if (!thisFailed) { + out("OK"); + } else { + failed = true; + } + executed = true; + } + + static boolean lfMissing = false; + + private static void out(String message) { + lfMissing = true; + System.out.println(message); + } + + /* don't print LF at end */ + private static void out1(String message) { + System.out.print(message); + lfMissing = true; + } + + /* print at a new line, indented */ + private static void out2(String message) { + if (lfMissing) { + System.out.println(); + lfMissing = false; + } + System.out.println(" "+message); + } +} diff --git a/test/javax/sound/midi/Devices/MidiIO.java b/test/javax/sound/midi/Devices/MidiIO.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Devices/MidiIO.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; + +/** + * @test + * @bug 4356787 + * @summary MIDI device I/O is not working + */ +public class MidiIO { + + public static void main(String[] args) throws Exception { + out("4356787: MIDI device I/O is not working (windows)"); + + if (System.getProperty("os.name").startsWith("Windows")) { + boolean forInput=true; + boolean forOutput=true; + int outOnlyCount=0; + int inOnlyCount=0; + out(" available MIDI devices:"); + MidiDevice.Info[] aInfos = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < aInfos.length; i++) { + try { + MidiDevice device = MidiSystem.getMidiDevice(aInfos[i]); + boolean bAllowsInput = (device.getMaxTransmitters() != 0); + boolean bAllowsOutput = (device.getMaxReceivers() != 0); + if (bAllowsInput && !bAllowsOutput) { + inOnlyCount++; + } + if (!bAllowsInput && bAllowsOutput) { + outOnlyCount++; + } + if ((bAllowsInput && forInput) || (bAllowsOutput && forOutput)) { + out(""+i+" " + +(bAllowsInput?"IN ":" ") + +(bAllowsOutput?"OUT ":" ") + +aInfos[i].getName()+", " + +aInfos[i].getVendor()+", " + +aInfos[i].getVersion()+", " + +aInfos[i].getDescription()); + } + } + catch (MidiUnavailableException e) { + // device is obviously not available... + } + } + if (aInfos.length == 0) { + out("No devices available. Test should be run on systems with MIDI drivers installed."); + } else { + if (outOnlyCount>1) { + if (inOnlyCount==0) { + //throw new Exception("No input devices! test fails."); + out("System provides out devices, but no input devices. This means either"); + out("a bug in Java Sound, or the drivers are not set up correctly."); + } + out("Test passed."); + } else { + out("no MIDI I/O installed. Test should be run on systems with MIDI drivers installed."); + } + } + } else { + out(" -- not on Windows. Test doesn't apply."); + } + } + + static void out(String s) { + System.out.println(s); System.out.flush(); + } +} diff --git a/test/javax/sound/midi/Devices/MidiOutGetMicrosecondPositionBug.java b/test/javax/sound/midi/Devices/MidiOutGetMicrosecondPositionBug.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Devices/MidiOutGetMicrosecondPositionBug.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequencer; +import javax.sound.midi.Synthesizer; + +/** + * @test + * @bug 4903786 + * @summary MIDI OUT does not implement getMicrosecondPosition() consistently + */ +public class MidiOutGetMicrosecondPositionBug { + static int successfulTests = 0; + + private static void testDevice(MidiDevice device) throws Exception { + boolean timestampsAvailable = false; + boolean timestampPrecisionOk = false; + try { + // expected behaviour if not opened? + device.open(); + /* First, we're testing if timestamps are provided at all. + Returning -1 (unsupported), while allowed by the API + specification, is not sufficient to pass this test. */ + long timestamp = device.getMicrosecondPosition(); + timestampsAvailable = (timestamp != -1); + + /* Then, we're testing the precision. Note that the system time + is measured in milliseconds, while the device time is measured + in microseconds. */ + + long systemTime1 = System.currentTimeMillis(); + long deviceTime1 = device.getMicrosecondPosition(); + // rest for 5 seconds + Thread.sleep(5000); + long systemTime2 = System.currentTimeMillis(); + long deviceTime2 = device.getMicrosecondPosition(); + + // now both period measurements are calculated in milliseconds. + long systemDuration = systemTime2 - systemTime1; + long deviceDuration = (deviceTime2 - deviceTime1) / 1000; + long delta = Math.abs(systemDuration - deviceDuration); + // a deviation of 0.5 seconds (= 500 ms) is allowed. + timestampPrecisionOk = (delta <= 500); + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - " + t.toString()); + return; + } finally { + device.close(); + } + if (! timestampsAvailable) { + throw new Exception("timestamps are not supported"); + } + if (! timestampPrecisionOk) { + throw new Exception("device timer not precise enough"); + } + successfulTests++; + } + + private static void doAll() throws Exception { + MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + for (int i=0; i < infos.length; i++) { + MidiDevice device = MidiSystem.getMidiDevice(infos[i]); + if ((! (device instanceof Sequencer)) && + (! (device instanceof Synthesizer)) && + (device.getMaxReceivers() > 0 || device.getMaxReceivers() == -1)) { + + System.out.println("--------------"); + System.out.println("Testing MIDI device: " + infos[i]); + testDevice(device); + } + if (infos.length==0) { + System.out.println("No MIDI devices available!"); + } + } + } + + public static void main(String[] args) throws Exception { + if (!isMidiInstalled()) { + return; + } + doAll(); + if (successfulTests==0) { + System.out.println("Could not execute any of the tests. Test NOT failed."); + } else { + System.out.println("Test PASSED."); + } + } + + /** + * Returns true if at least one MIDI (port) device is correctly installed on + * the system. + */ + public static boolean isMidiInstalled() { + boolean result = false; + MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < devices.length; i++) { + try { + MidiDevice device = MidiSystem.getMidiDevice(devices[i]); + result = ! (device instanceof Sequencer) && ! (device instanceof Synthesizer); + } catch (Exception e1) { + System.err.println(e1); + } + if (result) + break; + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } +} diff --git a/test/javax/sound/midi/Devices/OpenClose.java b/test/javax/sound/midi/Devices/OpenClose.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Devices/OpenClose.java @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequencer; +import javax.sound.midi.Synthesizer; +import javax.sound.midi.Transmitter; + +/** + * @test + * @bug 4616517 + * @summary Receiver.send() does not work properly. Tests open/close behaviour + * of MidiDevices. For this test, it is essential that the MidiDevice + * picked from the list of devices (MidiSystem.getMidiDeviceInfo()) is + * the same as the one used by + * MidiSystem.getReceiver()/getTransmitter(). To achieve this, default + * provider properties for Receivers/Transmitters are used. + */ +public class OpenClose { + + private static boolean isTestExecuted; + private static boolean isTestPassed; + + public static void main(String[] args) throws Exception { + boolean failed = false; + out("#4616517: Receiver.send() does not work properly"); + if (!isMidiInstalled()) { + out("Soundcard does not exist or sound drivers not installed!"); + out("This test requires sound drivers for execution."); + return; + } + MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + MidiDevice outDevice = null; + MidiDevice inDevice = null; + for (int i = 0; i < infos.length; i++) { + MidiDevice device = MidiSystem.getMidiDevice(infos[i]); + if (! (device instanceof Synthesizer) && + ! (device instanceof Sequencer)) { + if (device.getMaxReceivers() != 0) { + outDevice = device; + } + if (device.getMaxTransmitters() != 0) { + inDevice = device; + } + } + } + if (outDevice != null) { + // set the default provider properties + System.setProperty(Receiver.class.getName(), + "#" + outDevice.getDeviceInfo().getName()); + } + if (inDevice != null) { + System.setProperty(Transmitter.class.getName(), + "#" + inDevice.getDeviceInfo().getName()); + } + out("Using MIDI OUT Device: " + outDevice); + out("Using MIDI IN Device: " + inDevice); + + isTestExecuted = false; + if (outDevice != null) { + isTestExecuted = true; + TestHelper testHelper = new ReceiverTestHelper(outDevice); + try { + doTest("Receiver", testHelper); + failed |= testHelper.hasFailed(); + } catch (Exception e) { + out("Exception occured, cannot test!"); + isTestExecuted = false; + } + } + + if (inDevice != null) { + isTestExecuted = true; + TestHelper testHelper = new TransmitterTestHelper(inDevice); + try { + doTest("Transmitter", testHelper); + failed |= testHelper.hasFailed(); + } catch (Exception e) { + out("Exception occured, cannot test!"); + isTestExecuted = false; + } + } + + isTestPassed = ! failed; + + if (isTestExecuted) { + if (isTestPassed) { + out("Test PASSED."); + } else { + throw new Exception("Test FAILED."); + } + } else { + out("Test NOT FAILED"); + } + } + + private static void doTest(String type, + TestHelper testHelper) throws Exception { + /* Case 1: + - MidiDevice.open() + - MidiDevice.close() + */ + out("checking " + type + " case 1..."); + testHelper.checkClosed(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 2a: + - MidiSystem.get[Receiver|Transmitter]() + - [Receiver|Transmitter].close() + */ + out("checking " + type + " case 2a..."); + testHelper.checkClosed(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 2b: + - MidiDevice.get[Receiver|Transmitter]() + - [Receiver|Transmitter].close() + */ + out("checking " + type + " case 2b..."); + testHelper.checkClosed(); + + testHelper.fetchObjectDevice(); + testHelper.checkClosed(); + + testHelper.closeObjectDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 3a: + - MidiSystem.get[Receiver|Transmitter]() + - MidiDevice.open() + - MidiDevice.close() + - [Receiver|Transmitter].close() + */ + out("checking " + type + " case 3a..."); + testHelper.checkClosed(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 3b: + - MidiDevice.get[Receiver|Transmitter]() + - MidiDevice.open() + - MidiDevice.close() + - [Receiver|Transmitter].close() + */ + out("checking " + type + " case 3b..."); + testHelper.checkClosed(); + + testHelper.fetchObjectDevice(); + testHelper.checkClosed(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + testHelper.closeObjectDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 4a: + - MidiSystem.get[Receiver|Transmitter]() + - MidiDevice.open() + - [Receiver|Transmitter].close() + - MidiDevice.close() + */ + out("checking " + type + " case 4a..."); + testHelper.checkClosed(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 4b: + - MidiDevice.get[Receiver|Transmitter]() + - MidiDevice.open() + - [Receiver|Transmitter].close() + - MidiDevice.close() + */ + out("checking " + type + " case 4b..."); + testHelper.checkClosed(); + + testHelper.fetchObjectDevice(); + testHelper.checkClosed(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.closeObjectDevice(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 5a: + - MidiDevice.open() + - MidiSystem.get[Receiver|Transmitter]() + - MidiDevice.close() + - [Receiver|Transmitter].close() + */ + out("checking " + type + " case 5a..."); + testHelper.checkClosed(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 5b: + - MidiDevice.open() + - MidiDevice.get[Receiver|Transmitter]() + - MidiDevice.close() + - [Receiver|Transmitter].close() + */ + out("checking " + type + " case 5b..."); + testHelper.checkClosed(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.fetchObjectDevice(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + testHelper.closeObjectDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 6a: + - MidiDevice.open() + - MidiSystem.get[Receiver|Transmitter]() + - [Receiver|Transmitter].close() + - MidiDevice.close() + */ + out("checking " + type + " case 6a..."); + testHelper.checkClosed(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 6b: + - MidiDevice.open() + - MidiDevice.get[Receiver|Transmitter]() + - [Receiver|Transmitter].close() + - MidiDevice.close() + */ + out("checking " + type + " case 6b..."); + testHelper.checkClosed(); + + testHelper.openDevice(); + testHelper.checkOpen(); + + testHelper.fetchObjectDevice(); + testHelper.checkOpen(); + + testHelper.closeObjectDevice(); + testHelper.checkOpen(); + + testHelper.closeDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 7: + - MidiSystem.get[Receiver|Transmitter]() // 1 + - MidiDevice.get[Receiver|Transmitter]() // 2 + - [Receiver|Transmitter].close() // 2 + - [Receiver|Transmitter].close() // 1 + */ + out("checking " + type + " case 7..."); + testHelper.checkClosed(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.fetchObjectDevice(); + testHelper.checkOpen(); + + testHelper.closeObjectDevice(); + testHelper.checkOpen(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 8: + - MidiSystem.get[Receiver|Transmitter]() // 1 + - MidiDevice.get[Receiver|Transmitter]() // 2 + - [Receiver|Transmitter].close() // 1 + - [Receiver|Transmitter].close() // 2 + */ + out("checking " + type + " case 8..."); + testHelper.checkClosed(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.fetchObjectDevice(); + testHelper.checkOpen(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkClosed(); + + testHelper.closeObjectDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 9: + - MidiDevice.get[Receiver|Transmitter]() // 2 + - MidiSystem.get[Receiver|Transmitter]() // 1 + - [Receiver|Transmitter].close() // 2 + - [Receiver|Transmitter].close() // 1 + */ + out("checking " + type + " case 9..."); + testHelper.checkClosed(); + + testHelper.fetchObjectDevice(); + testHelper.checkClosed(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.closeObjectDevice(); + testHelper.checkOpen(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case 10: + - MidiDevice.get[Receiver|Transmitter]() // 2 + - MidiSystem.get[Receiver|Transmitter]() // 1 + - [Receiver|Transmitter].close() // 1 + - [Receiver|Transmitter].close() // 2 + */ + out("checking " + type + " case 10..."); + testHelper.checkClosed(); + + testHelper.fetchObjectDevice(); + testHelper.checkClosed(); + + testHelper.fetchObjectMidiSystem(); + testHelper.checkOpen(); + + testHelper.closeObjectMidiSystem(); + testHelper.checkClosed(); + + testHelper.closeObjectDevice(); + testHelper.checkClosed(); + + out("...OK"); + + /* Case N - 1: + - 10 x MidiSystem.get[Receiver|Transmitter]() + - 10 x [Receiver|Transmitter].close() + */ + out("checking " + type + " case N - 1..."); + TestHelper[] testHelpers = new TestHelper[10]; + for (int i = 0; i < 10; i++) { + testHelpers[i] = (TestHelper) testHelper.clone(); + } + testHelper.checkClosed(); + + for (int i = 0; i < 10; i++) { + testHelpers[i].fetchObjectMidiSystem(); + testHelper.checkOpen(); + } + + + for (int i = 0; i < 9; i++) { + testHelpers[i].closeObjectMidiSystem(); + testHelper.checkOpen(); + } + + testHelpers[9].closeObjectMidiSystem(); + testHelper.checkClosed(); + + out("...OK"); + } + + private static void out(String message) { + System.out.println(message); + } + + private static abstract class TestHelper implements Cloneable { + private MidiDevice device; + private boolean failed; + + protected TestHelper(MidiDevice device) { + this.device = device; + failed = false; + } + + protected MidiDevice getDevice() { + return device; + } + + public boolean hasFailed() { + return failed; + } + + public void openDevice() throws MidiUnavailableException { + getDevice().open(); + } + + public void closeDevice() { + getDevice().close(); + } + + public void checkOpen(){ + checkOpen(getDevice(), true); + } + + public void checkClosed(){ + checkOpen(getDevice(), false); + } + + private void checkOpen(MidiDevice device, boolean desiredState) { + if (device.isOpen() != desiredState) { + out("device should be " + + getStateString(desiredState) + ", but isn't!"); + failed = true; + } + } + + + private String getStateString(boolean state) { + return state ? "open" : "closed"; + } + + + public abstract void fetchObjectMidiSystem() throws MidiUnavailableException; + public abstract void fetchObjectDevice() throws MidiUnavailableException; + public abstract void closeObjectMidiSystem(); + public abstract void closeObjectDevice(); + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + } + + private static class ReceiverTestHelper extends TestHelper { + private Receiver receiverMidiSystem; + private Receiver receiverDevice; + + public ReceiverTestHelper(MidiDevice device) { + super(device); + } + + public void fetchObjectMidiSystem() throws MidiUnavailableException { + receiverMidiSystem = MidiSystem.getReceiver(); + } + + + public void fetchObjectDevice() throws MidiUnavailableException { + receiverDevice = getDevice().getReceiver(); + } + + + public void closeObjectMidiSystem() { + receiverMidiSystem.close(); + } + + + public void closeObjectDevice() { + receiverDevice.close(); + } + } + + private static class TransmitterTestHelper extends TestHelper { + private Transmitter transmitterMidiSystem; + private Transmitter transmitterDevice; + + public TransmitterTestHelper(MidiDevice device) { + super(device); + } + + public void fetchObjectMidiSystem() throws MidiUnavailableException { + transmitterMidiSystem = MidiSystem.getTransmitter(); + } + + + public void fetchObjectDevice() throws MidiUnavailableException { + transmitterDevice = getDevice().getTransmitter(); + } + + + public void closeObjectMidiSystem() { + transmitterMidiSystem.close(); + } + + + public void closeObjectDevice() { + transmitterDevice.close(); + } + } + + /** + * Returns true if at least one MIDI (port) device is correctly installed on + * the system. + */ + public static boolean isMidiInstalled() { + boolean result = false; + MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < devices.length; i++) { + try { + MidiDevice device = MidiSystem.getMidiDevice(devices[i]); + result = ! (device instanceof Sequencer) && ! (device instanceof Synthesizer); + } catch (Exception e1) { + System.err.println(e1); + } + if (result) + break; + } + return result; + } +} diff --git a/test/javax/sound/midi/Devices/ReceiverTransmitterAvailable.java b/test/javax/sound/midi/Devices/ReceiverTransmitterAvailable.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Devices/ReceiverTransmitterAvailable.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Transmitter; + +/** + * @test + * @bug 4616517 + * @summary Receiver.send() does not work properly + */ +public class ReceiverTransmitterAvailable { + + private static boolean isTestExecuted; + private static boolean isTestPassed; + + public static void main(String[] args) throws Exception { + out("#4616517: Receiver.send() does not work properly"); + doAllTests(); + if (isTestExecuted) { + if (isTestPassed) { + out("Test PASSED."); + } else { + throw new Exception("Test FAILED."); + } + } else { + out("Test NOT FAILED"); + } + } + + private static void doAllTests() { + boolean problemOccured = false; + boolean succeeded = true; + MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < infos.length; i++) { + MidiDevice device = null; + try { + device = MidiSystem.getMidiDevice(infos[i]); + succeeded &= doTest(device); + } catch (MidiUnavailableException e) { + out("exception occured; cannot test"); + problemOccured = true; + } + } + if (infos.length == 0) { + out("Soundcard does not exist or sound drivers not installed!"); + out("This test requires sound drivers for execution."); + } + isTestExecuted = !problemOccured; + isTestPassed = succeeded; + } + + private static boolean doTest(MidiDevice device) { + boolean succeeded = true; + out("Testing: " + device); + boolean expectingReceivers = (device.getMaxReceivers() != 0); + boolean expectingTransmitters = (device.getMaxTransmitters() != 0); + try { + Receiver rec = device.getReceiver(); + rec.close(); + if (! expectingReceivers) { + out("no exception on getting Receiver"); + succeeded = false; + } + } catch (MidiUnavailableException e) { + if (expectingReceivers) { + out("Exception on getting Receiver: " + e); + succeeded = false; + } + } + try { + Transmitter trans = device.getTransmitter(); + trans.close(); + if (! expectingTransmitters) { + out("no exception on getting Transmitter"); + succeeded = false; + } + } catch (MidiUnavailableException e) { + if (expectingTransmitters) { + out("Exception on getting Transmitter: " + e); + succeeded = false; + } + } + return succeeded; + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/midi/Devices/Reopen.java b/test/javax/sound/midi/Devices/Reopen.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Devices/Reopen.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequencer; +import javax.sound.midi.Synthesizer; + +/** + * @test + * @bug 4914667 + * @summary Closing and reopening MIDI IN device on Linux throws + * MidiUnavailableException + */ +public class Reopen { + + private static boolean isTestExecuted; + private static boolean isTestPassed; + + /* + * run manually: + * java Reopen 100 in for 100 iterations on the MIDI IN device + * java Reopen 16 out for 16 iterations on the MIDI OUT device + */ + public static void main(String[] args) throws Exception { + if (args.length == 0) { + doAllTests(); + } else if (args.length == 2) { + int numIterations = Integer.parseInt(args[0]); + if (args[1].equals("in")) { + doTest(numIterations, true); + } else { + doTest(numIterations, false); + } + } else { + out("usage: java Reopen in|out"); + } + } + + private static void doAllTests() throws Exception { + out("#4914667: Closing and reopening MIDI IN device on Linux throws MidiUnavailableException"); + boolean success = true; + try { + success &= doTest(20, true); // MIDI IN + success &= doTest(20, false); // MIDI OUT + isTestExecuted = true; + } catch (Exception e) { + out(e); + isTestExecuted = false; + } + isTestPassed = success; + if (isTestExecuted) { + if (isTestPassed) { + out("Test PASSED."); + } else { + throw new Exception("Test FAILED."); + } + } else { + out("Test NOT FAILED"); + } + } + + private static boolean doTest(int numIterations, boolean input) throws Exception { + MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + MidiDevice outDevice = null; + MidiDevice inDevice = null; + for (int i = 0; i < infos.length; i++) { + MidiDevice device = MidiSystem.getMidiDevice(infos[i]); + if (! (device instanceof Sequencer) && + ! (device instanceof Synthesizer)) { + if (device.getMaxReceivers() != 0) { + outDevice = device; + } + if (device.getMaxTransmitters() != 0) { + inDevice = device; + } + } + } + MidiDevice testDevice = null; + if (input) { + testDevice = inDevice; + } else { + testDevice = outDevice; + } + if (testDevice == null) { + out("Cannot test: device not available."); + return true; + } + out("Using Device: " + testDevice); + + for (int i = 0; i < numIterations; i++) { + out("@@@ ITERATION: " + i); + testDevice.open(); + // This sleep ensures that the thread of MidiInDevice is started. + sleep(50); + testDevice.close(); + } + return true; + } + + private static void sleep(int milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (InterruptedException e) { + } + } + + private static void out(Throwable t) { + t.printStackTrace(System.out); + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/midi/File/SMFCp037.java b/test/javax/sound/midi/File/SMFCp037.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/File/SMFCp037.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.midi.MidiSystem; + +/** + * @test + * @bug 4303933 + * @summary MidiSystem fails to load MIDI file on systems with EBCDIC simulation + */ +public class SMFCp037 { + + public static void main(String args[]) throws Exception { + // Test to read MIDI files with Cp037 character set - close enough + // for EBCDIC simulation + System.setProperty("file.encoding", "Cp037"); + // try to read this file with Cp037 encoding + MidiSystem.getSequence(new ByteArrayInputStream(SHORT_SMF)); + System.out.println(" test passed."); + } + +public static byte[] SHORT_SMF = { + 77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 2, 0, 120, 77, 84, 114, 107, 0, 0, + 0, 27, 0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32, + 116, 114, 97, 99, 107, 32, 48, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, -44, + 0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32, 116, 114, + 97, 99, 107, 32, 49, 0, -64, 30, 0, -112, 68, 126, 0, -32, 6, 67, 0, 14, + 71, 0, 20, 74, 0, 26, 77, 0, 32, 80, 0, 42, 85, 6, 50, 89, 6, 56, 92, 5, + 66, 97, 6, 74, 101, 6, 80, 104, 11, 84, 106, 20, 76, 102, 6, 70, 99, 5, 60, + 94, 6, 52, 90, 5, 44, 86, 4, 34, 81, 5, 26, 77, 5, 20, 74, 6, 10, 69, 5, + 2, 65, 7, 0, 64, 42, -112, 66, 123, 11, 68, 0, 72, 63, 126, 4, 66, 0, 43, + -32, 0, 63, 6, 0, 60, 7, 0, 56, 6, 0, 53, 5, 0, 49, 5, 0, 43, 4, 0, 37, 3, + 0, 30, 3, 0, 25, 3, 0, 19, 3, 0, 13, 4, 0, 8, 4, 0, 2, 4, 0, 0, 70, 0, 3, + 5, 0, 9, 3, 0, 14, 7, 0, 16, 25, 0, 21, 5, 0, 25, 7, 0, 28, 5, 0, 32, 5, + 0, 36, 5, 0, 41, 6, 0, 46, 5, 0, 50, 5, 0, 53, 4, 0, 58, 7, 0, 61, 7, 0, + 64, 117, -112, 63, 0, 0, -1, 47, 0 + }; +} diff --git a/test/javax/sound/midi/File/SMFParserBreak.java b/test/javax/sound/midi/File/SMFParserBreak.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/File/SMFParserBreak.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; + +/** + * @test + * @bug 4910986 + * @summary MIDI file parser breaks up on http connection + */ +public class SMFParserBreak { + + public static void main(String[] args) throws Exception { + + InputStream is = new ByteArrayInputStream(midifile); + // create a buffered input stream that seems + // to be on an unfortunate boundary for the + // 1.4.2 SMF parser implementation + is = new ChunkInputStream(is, 32); + Sequence sequence = MidiSystem.getSequence(is); + + long duration = sequence.getMicrosecondLength() / 10000; + System.out.println("Duration: "+duration+" deciseconds "); + + // the test is passed if no exception thrown + System.out.println("Test passed"); + } + + // A MIDI file + static byte[] midifile = { + 77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 3, -30, 120, 77, 84, 114, 107, 0, + 0, 0, 123, 0, -112, 30, 100, -113, 49, -128, 50, 100, -114, 69, -112, 31, + 100, -114, 33, -128, 51, 100, -114, 55, -112, 32, 100, -114, 120, -128, 52, + 100, -114, 40, -112, 33, 100, -114, 26, -128, 53, 100, -114, 26, -112, 34, + 100, -114, 76, -128, 54, 100, -114, 12, -112, 35, 100, -114, 91, -128, 55, + 100, -114, 69, -112, 36, 100, -114, 33, -128, 56, 100, -114, 55, -112, 37, + 100, -114, 84, -128, 57, 100, -114, 40, -112, 38, 100, -114, 26, -128, 58, + 100, -114, 26, -112, 39, 100, -113, 24, -128, 59, 100, -113, 60, -112, 40, + 100, -113, 110, -128, 60, 100, -113, 96, -112, 41, 100, -113, 39, -128, 61, + 100, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, 4, 0, -1, 47, 0, 77, 84, 114, + 107, 0, 0, 0, 4, 0, -1, 47, 0 + }; +} + +/* an input stream that always returns data in chunks */ +class ChunkInputStream extends FilterInputStream { + int chunkSize; + int p = 0; // position + + public ChunkInputStream(InputStream is, int chunkSize) { + super(is); + this.chunkSize = chunkSize; + } + + // override to increase counter + public int read() throws IOException { + int ret = super.read(); + if (ret >= 0) { + p++; + } + return ret; + } + + // override to make sure that read(byte[], int, int) is used + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + // override to split the data in chunks + public int read(byte[] b, int off, int len) throws IOException { + // if we would pass a chunk boundary, + // only return up to the chunk boundary + if ( (p / chunkSize) < ( (p+len) / chunkSize)) { + // p+len is in the next chunk + len -= ((p+len) % chunkSize); + } + int ret = super.read(b, off, len); + if (ret >= 0) { + p += ret; + } + return ret; + } +} diff --git a/test/javax/sound/midi/File/WriteRealTimeMessageNPE.java b/test/javax/sound/midi/File/WriteRealTimeMessageNPE.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/File/WriteRealTimeMessageNPE.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 5048381 + * @summary NPE when writing a sequence with a realtime MIDI message + */ +public class WriteRealTimeMessageNPE { + + public static void main(String args[]) throws Exception { + System.out.println("5048381: NullPointerException when saving a MIDI sequence"); + boolean npeThrown = false; + boolean noEx = false; + + Sequence seq = new Sequence(Sequence.PPQ, 384, 1); + Track t = seq.getTracks()[0]; + ShortMessage msg = new ShortMessage(); + msg.setMessage(0xF8, 0, 0); + t.add(new MidiEvent(msg, 0)); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + MidiSystem.write(seq, 0, out); + noEx = true; + } catch (NullPointerException npe) { + npeThrown = true; + System.out.println("## Failed: Threw unexpected NPE: "+npe); + throw new Exception("Test FAILED!"); + } catch (Exception e) { + System.out.println("Threw unexpected Exception: "+e); + System.out.println("But at least did not throw NPE..."); + } + if (noEx) { + InputStream is = new ByteArrayInputStream(out.toByteArray()); + seq = MidiSystem.getSequence(is); + System.out.println("Sequence has "+seq.getTracks().length+" tracks."); + if (seq.getTracks().length > 0) { + System.out.println("Track 0 has "+seq.getTracks()[0].size()+" events."); + } + } + System.out.println("Test passed."); + } +} diff --git a/test/javax/sound/midi/MetaMessage/MetaMessageClone.java b/test/javax/sound/midi/MetaMessage/MetaMessageClone.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/MetaMessage/MetaMessageClone.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.midi.MetaMessage; + +/** + * @test + * @bug 4511796 + * @summary Check that MetaMessage.clone() works correctly + */ +public class MetaMessageClone { + + private static void printMsg(MetaMessage msg, byte[] data) { + System.out.println(""+msg.getLength()+" total bytes, type="+msg.getType()+", dataLength="+data.length); + } + + private static void checkClone(MetaMessage msg) throws Exception { + System.out.print("Original: "); + byte[] msgData=msg.getData(); + printMsg(msg, msgData); + MetaMessage msg2=(MetaMessage) msg.clone(); + byte[] msg2Data=msg2.getData(); + System.out.print("Clone: "); + printMsg(msg2, msg2Data); + + if (msg2.getLength()!=msg.getLength() + || msg.getType()!=msg2.getType() + || msgData.length!=msg2Data.length) { + throw new Exception("cloned MetaMessage is not equal."); + } + int max=Math.min(msgData.length, 10); + for (int i=0; i 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //DialogOrient + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + Test6411624.pass(); + } + else + { + Test6411624.fail(); + } + } + + }// TestDialog class diff --git a/test/javax/sound/midi/MidiSystem/6411624/bug6411624.java b/test/javax/sound/midi/MidiSystem/6411624/bug6411624.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/MidiSystem/6411624/bug6411624.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2006, 2016, 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. + */ + +import java.io.IOException; +import java.util.Iterator; +import java.util.List; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequencer; +import javax.sound.midi.Synthesizer; +import javax.sound.midi.Transmitter; + +/** + * This test should be run on specific environment (solaris or linux w/o + * audio card installed). + */ +public class bug6411624 { + + public static void main(String args[]) throws Exception { + log("This test should only be run on solaris or linux system"); + log("without audio card installed (to test on SunRay set"); + log("incorrect $AUDIODEV value)."); + readln(); + + boolean testRecv = false; + boolean testTrans = false; + boolean testSeq = true; + + // print add info (midi device list) + try { + MidiDevice.Info[] midis = MidiSystem.getMidiDeviceInfo(); + log("MidiDevices (total " + midis.length + "):"); + for (int i=0; i transmitters = seq.getTransmitters(); + int size = transmitters.size(); + out(" transmitters.size()="+size); + if (size != 1 && connected) { + out(" should have 1 connection! Failed."); + failed = true; + } + if (size != 0 && !connected) { + out(" should have 0 connections! Failed."); + failed = true; + } + out(" closing..."); + seq.close(); + transmitters = seq.getTransmitters(); + size = transmitters.size(); + out(" transmitters.size()="+size); + if (size != 0) { + out(" should have 0 connections! Failed."); + failed = true; + } + + out(" opening again..."); + seq.open(); + transmitters = seq.getTransmitters(); + size = transmitters.size(); + out(" transmitters.size()="+size); + if (size != 1 && connected) { + out(" should have 1 connection! Failed."); + failed = true; + } + if (size != 0 && !connected) { + out(" should have 0 connections! Failed."); + failed = true; + } + } catch (Exception e) { + System.err.println(" unexpectedException was thrown: " + e); + System.err.println(" causes this test to FAIL."); + failed = true; + } + seq.close(); + } + + static void out(String s) { + System.out.println(s); + } +} diff --git a/test/javax/sound/midi/MidiSystem/MidiFileTypeUniqueness.java b/test/javax/sound/midi/MidiSystem/MidiFileTypeUniqueness.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/MidiSystem/MidiFileTypeUniqueness.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.MidiSystem; + +/** + * @test + * @bug 4883060 + * @summary AudioSystem.getAudioFileTypes returns duplicates + */ +public class MidiFileTypeUniqueness { + + public static void main(String[] args) throws Exception { + boolean foundDuplicates = false; + int[] aTypes = MidiSystem.getMidiFileTypes(); + for (int i = 0; i < aTypes.length; i++) + { + for (int j = 0; j < aTypes.length; j++) + { + if (aTypes[i] == aTypes[j] && i != j) { + foundDuplicates = true; + } + } + } + if (foundDuplicates) { + throw new Exception("Test failed"); + } else { + System.out.println("Test passed"); + } + } +} diff --git a/test/javax/sound/midi/MidiSystem/ProviderCacheing.java b/test/javax/sound/midi/MidiSystem/ProviderCacheing.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/MidiSystem/ProviderCacheing.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.util.List; + +import com.sun.media.sound.JDK13Services; + +/** + * @test + * @bug 4776511 + * @summary RFE: Setting the default MixerProvider. Test the cacheing of + * providers. This is a part of the test for 4776511. + * @modules java.desktop/com.sun.media.sound + */ +public class ProviderCacheing { + + private static final Class[] providerClasses = { + javax.sound.midi.spi.MidiDeviceProvider.class, + javax.sound.midi.spi.MidiFileReader.class, + javax.sound.midi.spi.MidiFileWriter.class, + javax.sound.midi.spi.SoundbankReader.class, + }; + + public static void main(String[] args) throws Exception { + boolean allCached = true; + for (int i = 0; i < providerClasses.length; i++) { + List list0 = JDK13Services.getProviders(providerClasses[i]); + List list1 = JDK13Services.getProviders(providerClasses[i]); + if (list0 == list1) { + out("Providers should not be cached for " + providerClasses[i]); + allCached = false; + } + } + + if (! allCached) { + throw new Exception("Test failed"); + } else { + out("Test passed"); + } + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/midi/MidiSystem/testdata/lib/conf/sound.properties b/test/javax/sound/midi/MidiSystem/testdata/lib/conf/sound.properties new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/MidiSystem/testdata/lib/conf/sound.properties @@ -0,0 +1,27 @@ +# +# Copyright (c) 2003, 2016, 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. +# + +javax.sound.midi.Receiver=xyz#123 +javax.sound.midi.Transmitter=xyz#123 +javax.sound.midi.Sequencer=xyz#123 +javax.sound.midi.Synthesizer=xyz#123 diff --git a/test/javax/sound/midi/Sequence/GetMicrosecondLength.java b/test/javax/sound/midi/Sequence/GetMicrosecondLength.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequence/GetMicrosecondLength.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.Sequence; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4929955 + * @summary Sequence.getMicrosecondLength() returns wrong value + */ +public class GetMicrosecondLength { + + public static boolean failed = false; + //private static Sequencer seq = null; + + public static void main(String[] args) throws Exception { + /* + try { + seq = MidiSystem.getSequencer(); + } catch (Exception e) { + e.printStackTrace(); + } + */ + for (int sec = 1; sec < 10; sec += 4) { + for (int tempo=0; tempo < 1000; tempo+=120) { + for (int resolution=1; resolution < 480; ) { + testSequence(sec, tempo, resolution); + if (resolution == 1) { + resolution = 120; + } else { + resolution += 120; + } + } + } + } + if (failed) throw new Exception("Test FAILED!"); + out("Test Passed."); + } + + /** + * Create a new Sequence for testing. + */ + private static void testSequence(int lengthInSeconds, int tempoInBPM, int resolution) { + Sequence sequence = null; + long lengthInMicroseconds = lengthInSeconds * 1000000; + boolean createTempoEvent = true; + if (tempoInBPM == 0) { + tempoInBPM = 120; + createTempoEvent = false; + System.out.print("Creating sequence: "+lengthInSeconds+"sec, " + +"resolution="+resolution+" ticks/beat..."); + } else { + System.out.print("Creating sequence: "+lengthInSeconds+"sec, " + +tempoInBPM+" beats/min, " + +"resolution="+resolution+" ticks/beat..."); + } + //long lengthInTicks = (lengthInMicroseconds * resolution) / tempoInBPM; + long lengthInTicks = (lengthInMicroseconds * tempoInBPM * resolution) / 60000000l; + //out("expected length in ticks: " + lengthInTicks); + try { + sequence = new Sequence(Sequence.PPQ, resolution); + Track track = sequence.createTrack(); + if (createTempoEvent) { + int tempoInMPQ = (int) (60000000l / tempoInBPM); + MetaMessage tm = new MetaMessage(); + byte[] msg = new byte[3]; + msg[0] = (byte) (tempoInMPQ >> 16); + msg[1] = (byte) ((tempoInMPQ >> 8) & 0xFF); + msg[2] = (byte) (tempoInMPQ & 0xFF); + + tm.setMessage(0x51 /* Meta Tempo */, msg, msg.length); + track.add(new MidiEvent(tm, 0)); + //out("regtest: tempoInMPQ="+tempoInMPQ); + //out("Added tempo event: new size="+track.size()); + } + ShortMessage mm = new ShortMessage(); + mm.setMessage(0xF6, 0, 0); + MidiEvent me = new MidiEvent(mm, lengthInTicks); + track.add(me); + //out("Added realtime event: new size="+track.size()); + } catch (InvalidMidiDataException e) { + out(e); + } + boolean thisFailed = false; + long actualLengthInTicks = sequence.getTickLength(); + // allow +/- 5% + if (Math.abs(actualLengthInTicks - lengthInTicks) > lengthInTicks / 20) { + out("FAILED:"); + out(" expected length in ticks: " + lengthInTicks); + out(" actual length in ticks : " + actualLengthInTicks); + thisFailed = true; + } + long actualLengthInUs = sequence.getMicrosecondLength(); + // allow +/- 5% + if (Math.abs(actualLengthInUs - lengthInMicroseconds) > lengthInMicroseconds / 20) { + if (!thisFailed) { + out("FAILED:"); + } + out(" expected length in microsecs: " + lengthInMicroseconds); + out(" actual length in microsecs : " + actualLengthInUs); + thisFailed = true; + } + if (!thisFailed) { + out("OK"); + } + /*if (seq != null) { + try { + seq.setSequence(sequence); + out("Sequencer tempo="+seq.getTempoInBPM()); + } catch (Exception e) { + e.printStackTrace(); + } + } + */ + failed |= thisFailed; + } + + + private static void out(Throwable t) { + t.printStackTrace(System.out); + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/midi/Sequence/MidiSMPTE.java b/test/javax/sound/midi/Sequence/MidiSMPTE.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequence/MidiSMPTE.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; + +/** + * @test + * @bug 4291250 + * @summary Midi files with SMPTE time do not play properly + */ +public class MidiSMPTE { + + public static void main(String[] args) throws Exception { + Sequence s = null; + //File midiFile = new File("outsmpte.mid"); + //InputStream is = new FileInputStream(midiFile); + //is = new BufferedInputStream(is); + InputStream is = new ByteArrayInputStream(smptemidifile); + s = MidiSystem.getSequence(is); + long duration = s.getMicrosecondLength() / 1000000; + System.out.println("Duration: "+duration+" seconds "); + if (duration > 14) { + throw new Exception("SMPTE time reader is broken! Test FAILED"); + } + System.out.println("Test passed"); + } + + public static void printFile(String filename) throws Exception { + File file = new File(filename); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + fis.read(data); + String s = ""; + for (int i=0; i72) { + System.out.println(s); + s=""; + } + } + System.out.println(s); + } + + // A MIDI file with SMPTE timing + static byte[] smptemidifile = { + 77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 3, -30, 120, 77, 84, 114, 107, 0, + 0, 0, 123, 0, -112, 30, 100, -113, 49, -128, 50, 100, -114, 69, -112, 31, + 100, -114, 33, -128, 51, 100, -114, 55, -112, 32, 100, -114, 120, -128, 52, + 100, -114, 40, -112, 33, 100, -114, 26, -128, 53, 100, -114, 26, -112, 34, + 100, -114, 76, -128, 54, 100, -114, 12, -112, 35, 100, -114, 91, -128, 55, + 100, -114, 69, -112, 36, 100, -114, 33, -128, 56, 100, -114, 55, -112, 37, + 100, -114, 84, -128, 57, 100, -114, 40, -112, 38, 100, -114, 26, -128, 58, + 100, -114, 26, -112, 39, 100, -113, 24, -128, 59, 100, -113, 60, -112, 40, + 100, -113, 110, -128, 60, 100, -113, 96, -112, 41, 100, -113, 39, -128, 61, + 100, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, 4, 0, -1, 47, 0, 77, 84, 114, + 107, 0, 0, 0, 4, 0, -1, 47, 0 + }; + +} diff --git a/test/javax/sound/midi/Sequence/SMPTEDuration.java b/test/javax/sound/midi/Sequence/SMPTEDuration.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequence/SMPTEDuration.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.Sequence; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4702328 + * @summary Wrong time in sequence for SMPTE based types + */ +public class SMPTEDuration { + + public static void main(String args[]) throws Exception { + int[][] dataMes = { {ShortMessage.NOTE_ON, 10, 0x24, 0x50} , + { ShortMessage.NOTE_OFF, 10, 0x24, 0x44 }, + { ShortMessage.NOTE_ON, 10, 0x24, 0x50 }, + { ShortMessage.NOTE_ON, 10, 0x26, 0x50 }, + { ShortMessage.NOTE_OFF, 10, 0x26, 0x53 } }; + long[] ticks = { 0, 68, 240, 240, 286}; + int res = 240; + ShortMessage msg; + Sequence midiData = null; + Track track; + boolean failed = false; + + + try { + midiData = new Sequence(Sequence.SMPTE_24 , res); + } catch (InvalidMidiDataException invMidiEx) { + invMidiEx.printStackTrace(System.out); + System.out.println("Unexpected InvalidMidiDataException: " + + invMidiEx.getMessage()); + failed = true; + } + track = midiData.createTrack(); + for (int i = 0; i < dataMes.length; i++) { + msg = new ShortMessage(); + try { + msg.setMessage(dataMes[i][0], dataMes[i][1], dataMes[i][2], + dataMes[i][3]); + } catch (InvalidMidiDataException invMidiEx) { + invMidiEx.printStackTrace(System.out); + System.out.println("Unexpected InvalidMidiDataException: " + + invMidiEx.getMessage()); + failed = true; + } + track.add(new MidiEvent(msg, ticks[i])); + } + // lengthInMs = (tickLength*1000000)/(divType*Res) + long micros = (long) ((midiData.getTickLength() * 1000000) / (res * Sequence.SMPTE_24)); + if (midiData.getMicrosecondLength() != micros) { + failed = true; + System.out.println("getMicrosecondLength() returns wrong length: " + + midiData.getMicrosecondLength()); + System.out.println("getMicrosecondLength() must return length: " + + micros); + } + if (midiData.getTickLength() != 286) { + failed = true; + System.out.println("getTickLength() returns wrong length: " + + midiData.getTickLength()); + } + + if( failed == true ) { + throw new Exception("test failed"); + } else { + System.out.println("Passed."); + } + } +} diff --git a/test/javax/sound/midi/Sequencer/LoopIAE.java b/test/javax/sound/midi/Sequencer/LoopIAE.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/LoopIAE.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 5025549 + * @summary Verify that setLoopEndPoint throws IAE + */ +public class LoopIAE { + + static ShortMessage MidiMsg3(int a, int b, int c) { + try { + ShortMessage msg = new ShortMessage(); + msg.setMessage((byte)a,(byte)b,(byte)c); + return msg; + } catch(InvalidMidiDataException ex) { + throw new RuntimeException(); + } + } + + static boolean failed = false; + + public static void main(String[] argv) throws Exception { + if (!hasSequencer()) { + return; + } + Sequencer sequencer = MidiSystem.getSequencer(); + Sequence sequence = new Sequence(Sequence.PPQ, 240); + Track track = sequence.createTrack(); + + track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,100),0)); + track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,0),0 + 240)); + track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,100),10*20)); + track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,0),10*20 + 10)); + + try { + sequencer.open(); + sequencer.setSequence(sequence); + sequencer.setTempoInBPM(100); + + System.out.println("Setting loop end point to 1"); + sequencer.setLoopEndPoint(1); + System.out.println(" -> effectively: "+sequencer.getLoopEndPoint()); + System.out.println("Setting loop start point to 2 -- should throw IAE"); + sequencer.setLoopStartPoint(2); + System.out.println(" -> effectively: "+sequencer.getLoopStartPoint()); + System.out.println("No IllegalArgumentException was thrown!"); + failed = true; + } catch (IllegalArgumentException iae) { + System.out.println("IAE was thrown correctly."); + } catch (MidiUnavailableException mue) { + System.out.println("MidiUnavailableException was thrown: " + mue); + System.out.println("Cannot execute test."); + } catch (InvalidMidiDataException imEx) { + System.out.println("InvalidMidiDataException was thrown."); + imEx.printStackTrace(); + System.out.println("Cannot execute test."); + } finally { + if (sequencer != null && sequencer.isOpen()) { + sequencer.close(); + } + } + if (failed) { + throw new Exception("Test FAILED!"); + } + System.out.println("test passed."); + } + + static boolean hasSequencer() { + try { + Sequencer seq = MidiSystem.getSequencer(); + if (seq != null) { + if (seq.isOpen()) { + seq.close(); + } + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("No sequencer available! Cannot execute test."); + return false; + } +} diff --git a/test/javax/sound/midi/Sequencer/Looping.java b/test/javax/sound/midi/Sequencer/Looping.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/Looping.java @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaEventListener; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4204105 + * @summary RFE: add loop() method(s) to Sequencer + * @key intermittent + */ +public class Looping { + + public static void main(String[] args) throws Exception { + out("4204105: RFE: add loop() method(s) to Sequencer"); + boolean passed = testAll(); + if (passed) { + out("Test PASSED."); + } else { + throw new Exception("Test FAILED."); + } + } + + /** + * Execute the test on all available Sequencers. + * + * @return true if the test passed for all Sequencers, false otherwise + */ + private static boolean testAll() throws Exception { + boolean result = true; + MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < devices.length; i++) { + MidiDevice device = MidiSystem.getMidiDevice(devices[i]); + if (device instanceof Sequencer) { + result &= testSequencer((Sequencer) device); + } + } + return result; + } + + /** + * Execute the test on the passed Sequencer. + * + * @return true if the test is passed this Sequencer, false otherwise + */ + private static boolean testSequencer(Sequencer seq) throws Exception{ + boolean result = true; + out("testing: " + seq); + + result &= testGetSet(seq); + + seq.setSequence(createSequence()); + + result &= testGetSet(seq); + + result &= testPlay(seq); + + return result; + } + + private static boolean testGetSet(Sequencer seq) { + boolean result = true; + Sequence sequence = seq.getSequence(); + boolean isSequenceLoaded = (sequence != null); + + out("TestGetSet"); + + try { + if (seq.getLoopStartPoint() != 0) { + out("start point", isSequenceLoaded, + "isn't 0!"); + result = false; + } + } catch (IllegalArgumentException iae) { + if (!isSequenceLoaded) { + out("Caught permissable IllegalArgumentException:"); + } else { + out("Threw unacceptable IllegalArgumentException! FAILED"); + result = false; + } + out(iae.toString()); + } + + if (seq.getLoopEndPoint() != -1) { + out("end point", isSequenceLoaded, + "isn't -1!"); + result = false; + } + + try { + seq.setLoopStartPoint(25); + if (seq.getLoopStartPoint() != 25) { + out("setLoopStartPoint()", isSequenceLoaded, + "doesn't set the start point correctly!"); + result = false; + } + } catch (IllegalArgumentException iae) { + if (!isSequenceLoaded) { + out("Caught permissable IllegalArgumentException:"); + } else { + out("Threw unacceptable IllegalArgumentException! FAILED"); + result = false; + } + out(iae.toString()); + } + + try { + seq.setLoopEndPoint(26); + if (seq.getLoopEndPoint() != 26) { + out("setLoopEndPoint()", isSequenceLoaded, + "doesn't set the end point correctly!"); + result = false; + } + } catch (IllegalArgumentException iae) { + if (!isSequenceLoaded) { + out("Caught permissable IllegalArgumentException:"); + } else { + out("Threw unacceptable IllegalArgumentException! FAILED"); + result = false; + } + out(iae.toString()); + } + + try { + seq.setLoopStartPoint(0); + if (seq.getLoopStartPoint() != 0) { + out("setLoopStartPoint()", isSequenceLoaded, + "doesn't set the start point correctly!"); + result = false; + } + } catch (IllegalArgumentException iae) { + if (!isSequenceLoaded) { + out("Caught permissable IllegalArgumentException:"); + } else { + out("Threw unacceptable IllegalArgumentException! FAILED"); + result = false; + } + out(iae.toString()); + } + + if (isSequenceLoaded) { + seq.setLoopEndPoint(sequence.getTickLength()); + if (seq.getLoopEndPoint() != sequence.getTickLength()) { + out("setLoopEndPoint()", isSequenceLoaded, + "doesn't set the end point correctly!"); + result = false; + } + } else { + // fails + seq.setLoopEndPoint(-1); + if (seq.getLoopEndPoint() != -1) { + out("setLoopEndPoint()", isSequenceLoaded, + "doesn't set the end point correctly!"); + result = false; + } + } + + if (seq.getLoopCount() != 0) { + out("loop count", isSequenceLoaded, + "isn't 0!"); + result = false; + } + + seq.setLoopCount(1001); + if (seq.getLoopCount() != 1001) { + out("setLoopCount()", isSequenceLoaded, + "doesn't set the loop count correctly!"); + result = false; + } + + seq.setLoopCount(Sequencer.LOOP_CONTINUOUSLY); + if (seq.getLoopCount() != Sequencer.LOOP_CONTINUOUSLY) { + out("setLoopCount(Sequencer.LOOP_CONTINUOUSLY)", isSequenceLoaded, + "doesn't set the loop count correctly!"); + result = false; + } + + try { + seq.setLoopCount(-55); + out("setLoopCount()", isSequenceLoaded, + "doesn't throw IllegalArgumentException on illegal value!"); + result = false; + } catch (IllegalArgumentException e) { + // EXCEPTION IS EXPECTED + out("Caught permissable IAE"); + } + + seq.setLoopCount(0); + if (seq.getLoopCount() != 0) { + out("setLoopCount()", isSequenceLoaded, + "doesn't set the loop count correctly!"); + result = false; + } + + return result; + } + + private static boolean testPlay(Sequencer seq) { + boolean result = true; + long stopTime; + + out("TestPlay"); + + TestMetaEventListener listener = new TestMetaEventListener(); + seq.addMetaEventListener(listener); + long startTime = System.currentTimeMillis(); + try { + seq.open(); + out("Playing sequence, length="+(seq.getMicrosecondLength()/1000)+"millis"); + seq.start(); + while (true) { + stopTime = listener.getStopTime(); + if (stopTime != 0) { + break; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + } + long measuredDuration = stopTime - startTime; + out("play duration (us): " + measuredDuration); + } catch (Exception e) { + out("test not executed; exception:"); + e.printStackTrace(); + } + seq.close(); + return result; + } + + /** + * Create a new Sequence for testing. + * + * @return a dummy Sequence, or null, if a problem occured while creating + * the Sequence + */ + private static Sequence createSequence() { + Sequence sequence = null; + int lengthInSeconds = 2; + long lengthInMicroseconds = lengthInSeconds * 1000000; + int resolution = 480; + long lengthInTicks = (lengthInMicroseconds * 120 * resolution) / 60000000l; + out("length in ticks: " + lengthInTicks); + try { + sequence = new Sequence(Sequence.PPQ, resolution, 1); + Track track = sequence.createTrack(); + ShortMessage mm = new ShortMessage(); + mm.setMessage(0xF6, 0, 0); + MidiEvent me = new MidiEvent(mm, lengthInTicks); + track.add(me); + } catch (InvalidMidiDataException e) { + // DO NOTHING + } + out("sequence length (ticks): " + sequence.getTickLength()); + out("sequence length (us): " + sequence.getMicrosecondLength()); + return sequence; + } + + + private static void out(String m1, boolean isSequenceLoaded, String m2) { + out(m1 + (isSequenceLoaded ? " with Sequence " : " without Sequence ") + m2); + } + + private static void out(String message) { + System.out.println(message); + } + + private static class TestMetaEventListener implements MetaEventListener { + private long stopTime; + + + public void meta(MetaMessage m) { + System.out.print(" Got MetaMessage: "); + if (m.getType() == 47) { + stopTime = System.currentTimeMillis(); + System.out.println(" End Of Track -- OK"); + } else { + System.out.println(" unknown. Ignored."); + } + } + + public long getStopTime() { + return stopTime; + } + } +} diff --git a/test/javax/sound/midi/Sequencer/MetaCallback.java b/test/javax/sound/midi/Sequencer/MetaCallback.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/MetaCallback.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.Instrument; +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaEventListener; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4347135 + * @summary MIDI MetaMessage callback inconsistent + * @run main/othervm MetaCallback + */ +public class MetaCallback implements MetaEventListener { + + static ShortMessage MidiMsg3(int a, int b, int c) { + try { + ShortMessage msg = new ShortMessage(); + msg.setMessage((byte)a,(byte)b,(byte)c); + return msg; + } catch(InvalidMidiDataException ex) { + throw new RuntimeException(); + } + } + + //Synthesizer synth; + Instrument[] instruments; + Sequencer sequencer; + Sequence sequence; + Track track; + + public static int TOTAL_COUNT = 100; + + int metaCount = 0; + boolean finished = false; + + MetaCallback() throws Exception { + + sequencer=MidiSystem.getSequencer(); + sequence=new Sequence(Sequence.PPQ,240); + track=sequence.createTrack(); + sequencer.addMetaEventListener(this); + + byte[] data = new byte[1]; + + track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,100),0)); + track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,0),0 + 240)); + int c; + for(c=0; c < TOTAL_COUNT; c++) { + data[0]=(byte)(c+1); + MetaMessage meta = new MetaMessage(); + meta.setMessage(1, data, 1); // type, data, length + track.add(new MidiEvent(meta,c*20)); + } + track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,100),c*20)); + track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,0),c*20 + 10)); + + sequencer.setSlaveSyncMode(Sequencer.SyncMode.INTERNAL_CLOCK); + sequencer.setMasterSyncMode(Sequencer.SyncMode.INTERNAL_CLOCK); + sequencer.open(); + sequencer.setSequence(sequence); + sequencer.setTempoInBPM(100); + System.out.println("Starting playback..."); + this.start(); + while (!finished && sequencer.getTickPosition() < sequencer.getTickLength()) { + System.out.println("Tick "+sequencer.getTickPosition()+"..."); + Thread.sleep(1000); + } + System.out.println("Stopping playback..."); + this.stop(); + if (metaCount != TOTAL_COUNT) { + throw new Exception("Expected "+TOTAL_COUNT+" callbacks, but got "+metaCount+"!"); + } + } + void start() {sequencer.start();} + void stop() {sequencer.stop();} + + public void meta(MetaMessage msg) { + System.out.println(""+metaCount+": got "+msg); + if (msg.getType() == 0x2F) { + finished = true; + } else if (msg.getData().length > 0 && msg.getType() == 1) { + metaCount++; + } + } + + public static void main(String[] argv) throws Exception { + if (hasSequencer()) { + new MetaCallback(); + System.out.println("Test passed"); + } + } + + static boolean hasSequencer() { + try { + Sequencer seq = MidiSystem.getSequencer(); + if (seq != null) { + seq.open(); + seq.close(); + return true; + } + } catch (Exception e) {} + System.out.println("No sequencer available! Cannot execute test."); + return false; + } +} diff --git a/test/javax/sound/midi/Sequencer/Recording.java b/test/javax/sound/midi/Sequencer/Recording.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/Recording.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4932841 + * @key intermittent + * @summary Sequencer's recording feature does not work + */ +public class Recording { + + public static boolean failed = false; + public static boolean passed = false; + private static Sequencer seq = null; + + public static void main(String[] args) throws Exception { + try { + seq = MidiSystem.getSequencer(); + + // create an arbitrary sequence which lasts 10 seconds + Sequence sequence = createSequence(10, 120, 240); + + seq.setSequence(sequence); + out("Set Sequence to Sequencer. Tempo="+seq.getTempoInBPM()); + + Track track = sequence.createTrack(); + int oldSize = track.size(); + seq.recordEnable(track, -1); + + seq.open(); + + // if getReceiver throws Exception, failed! + failed = true; + Receiver rec = seq.getReceiver(); + + // start recording and add various events + seq.startRecording(); + + // is exception from here on, not failed + failed = false; + + if (!seq.isRecording()) { + failed = true; + throw new Exception("Sequencer did not start recording!"); + } + if (!seq.isRunning()) { + failed = true; + throw new Exception("Sequencer started recording, but is not running!"); + } + + // first: add an event to the middle of the sequence + ShortMessage msg = new ShortMessage(); + msg.setMessage(0xC0, 80, 00); + rec.send(msg, 5l * 1000l * 1000l); + + Thread.sleep(1000); + + // then add a real-time event + msg = new ShortMessage(); + msg.setMessage(0xC0, 81, 00); + long secondEventTick = seq.getTickPosition(); + rec.send(msg, -1); + + seq.stopRecording(); + if (seq.isRecording()) { + failed = true; + throw new Exception("Stopped recording, but Sequencer is still recording!"); + } + if (!seq.isRunning()) { + failed = true; + throw new Exception("Stopped recording, but Sequencer but is not running anymore!"); + } + + seq.stop(); + if (seq.isRunning()) { + failed = true; + throw new Exception("Stopped Sequencer, but it is still running!"); + } + + // now examine the contents of the recorded track: + // 1) number of events: should be 2 more + int newSize = track.size(); + int addedEventCount = newSize - oldSize; + + out("Added "+addedEventCount+" events to recording track."); + if (addedEventCount != 2) { + failed = true; + throw new Exception("Did not add 2 events!"); + } + + // 2) the first event should be at roughly "secondEventTick" + MidiEvent ev = track.get(0); + msg = (ShortMessage) ev.getMessage(); + out("The first recorded event is at tick position: "+ev.getTick()); + if (Math.abs(ev.getTick() - secondEventTick) > 1000) { + out(" -> but expected something like: "+secondEventTick+"! FAILED."); + failed = true; + } + + ev = track.get(1); + msg = (ShortMessage) ev.getMessage(); + out("The 2nd recorded event is at tick position: "+ev.getTick()); + out(" -> sequence's tick length is "+seq.getTickLength()); + if (Math.abs(ev.getTick() - (sequence.getTickLength() / 2)) > 1000) { + out(" -> but expected something like: "+(seq.getTickLength()/2)+"! FAILED."); + failed = true; + } + + passed = true; + } catch (Exception e) { + out(e.toString()); + if (!failed) out("Test not failed."); + } + if (seq != null) { + seq.close(); + } + + if (failed) { + throw new Exception("Test FAILED!"); + } + else if (passed) { + out("Test Passed."); + } + } + + /** + * Create a new Sequence for testing. + */ + private static Sequence createSequence(int lengthInSeconds, int tempoInBPM, + int resolution) { + Sequence sequence = null; + long lengthInMicroseconds = lengthInSeconds * 1000000; + boolean createTempoEvent = true; + if (tempoInBPM == 0) { + tempoInBPM = 120; + createTempoEvent = false; + System.out.print("Creating sequence: "+lengthInSeconds+"sec, " + +"resolution="+resolution+" ticks/beat..."); + } else { + System.out.print("Creating sequence: "+lengthInSeconds+"sec, " + +tempoInBPM+" beats/min, " + +"resolution="+resolution+" ticks/beat..."); + } + //long lengthInTicks = (lengthInMicroseconds * resolution) / tempoInBPM; + long lengthInTicks = (lengthInMicroseconds * tempoInBPM * resolution) / 60000000l; + //out("expected length in ticks: " + lengthInTicks); + try { + sequence = new Sequence(Sequence.PPQ, resolution); + Track track = sequence.createTrack(); + if (createTempoEvent) { + int tempoInMPQ = (int) (60000000l / tempoInBPM); + MetaMessage tm = new MetaMessage(); + byte[] msg = new byte[3]; + msg[0] = (byte) (tempoInMPQ >> 16); + msg[1] = (byte) ((tempoInMPQ >> 8) & 0xFF); + msg[2] = (byte) (tempoInMPQ & 0xFF); + + tm.setMessage(0x51 /* Meta Tempo */, msg, msg.length); + track.add(new MidiEvent(tm, 0)); + //out("regtest: tempoInMPQ="+tempoInMPQ); + //out("Added tempo event: new size="+track.size()); + } + ShortMessage mm = new ShortMessage(); + mm.setMessage(0xF6, 0, 0); + MidiEvent me = new MidiEvent(mm, lengthInTicks); + track.add(me); + //out("Added realtime event: new size="+track.size()); + } catch (InvalidMidiDataException e) { + out(e); + } + out("OK"); + + return sequence; + } + + private static void out(Throwable t) { + t.printStackTrace(System.out); + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/midi/Sequencer/SeqRecordDoesNotCopy.java b/test/javax/sound/midi/Sequencer/SeqRecordDoesNotCopy.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/SeqRecordDoesNotCopy.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 5048381 + * @summary Sequencer doesn't create distinct messages when recording events. + * @key headful + */ +public class SeqRecordDoesNotCopy { + public static void main(String argv[]) throws Exception { + Sequencer s = MidiSystem.getSequencer(); + s.open(); + try { + Sequence seq = new Sequence(Sequence.PPQ, 384, 2); + s.setSequence(seq); + Track t = seq.getTracks()[0]; + ShortMessage msg = new ShortMessage(); + msg.setMessage(0x90, 0x40, 0x7F); + t.add(new MidiEvent(msg, 11000)); + msg.setMessage(0x90, 0x40, 0x00); + t.add(new MidiEvent(msg, 12000)); + t = seq.getTracks()[1]; + s.recordEnable(t, -1); + System.out.println("Started recording..."); + s.startRecording(); + Receiver r = s.getReceiver(); + Thread.sleep(100); + // send a normal message + System.out.println("Recording a normal NOTE ON message..."); + msg.setMessage(0x90, 0x40, 0x6F); + r.send(msg, -1); + Thread.sleep(100); + // send a normal message + System.out.println("Recording a normal NOTE OFF message..."); + msg.setMessage(0x90, 0x40, 0x00); + r.send(msg, -1); + Thread.sleep(100); + s.stop(); + // now see if the messages were recorded + System.out.println("Recorded messages:"); + int sameMessage = 0; + for (int i = 0; i < t.size(); i++) { + System.out.print(" "+(i+1)+". "); + printEvent(t.get(i)); + if (t.get(i).getMessage() == msg) { + System.out.println("## Failed: Same Message reference!"); + sameMessage++; + } + } + if (sameMessage > 0) { + System.out.println("## Failed: The same instance was recorded!"); + throw new Exception("Test FAILED!"); + } + System.out.println("Did not detect any duplicate messages."); + System.out.println("Test passed."); + } catch (Exception e) { + System.out.println("Unexpected Exception: "+e); + //e.printStackTrace(); + throw new Exception("Test FAILED!"); + } finally { + s.close(); + } + } + public static void printEvent(MidiEvent event) + { + MidiMessage message = event.getMessage(); + long tick = event.getTick(); + byte[] data = message.getMessage(); + + StringBuffer sb = new StringBuffer((data.length * 3) - 1); + + for (int i = 0; i < data.length; i++) + { + sb.append(toHexByteString(data[i])); + if (i < data.length - 1) sb.append(' '); + } + System.out.printf("%5d: %s%n", tick, sb); + } + + private static String toHexByteString(int n) + { + if (n < 0) n &= 0xFF; + String s = Integer.toHexString(n).toUpperCase(); + if (s.length() == 1) s = '0' + s; + return s; + } +} diff --git a/test/javax/sound/midi/Sequencer/SeqRecordsRealTimeEvents.java b/test/javax/sound/midi/Sequencer/SeqRecordsRealTimeEvents.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/SeqRecordsRealTimeEvents.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 5048381 + * @summary Sequencer records real time messages into the sequence + * @key headful + */ +public class SeqRecordsRealTimeEvents { + public static void main(String argv[]) throws Exception { + Sequencer s = MidiSystem.getSequencer(); + s.open(); + try { + Sequence seq = new Sequence(Sequence.PPQ, 384, 2); + s.setSequence(seq); + Track t = seq.getTracks()[0]; + ShortMessage msg = new ShortMessage(); + msg.setMessage(0x90, 0x40, 0x7F); + t.add(new MidiEvent(msg, 11000)); + msg = new ShortMessage(); + msg.setMessage(0x90, 0x40, 0x00); + t.add(new MidiEvent(msg, 12000)); + t = seq.getTracks()[1]; + s.recordEnable(t, -1); + System.out.println("Started recording..."); + s.startRecording(); + Receiver r = s.getReceiver(); + Thread.sleep(100); + int oldTrackSize = t.size(); + // send a realtime message to the track + System.out.println("Recording real time message..."); + msg = new ShortMessage(); + msg.setMessage(0xF8, 0, 0); + r.send(msg, -1); + Thread.sleep(100); + // send a normal message + msg = new ShortMessage(); + System.out.println("Recording a normal NOTE ON message..."); + msg.setMessage(0x90, 0x40, 0x6F); + r.send(msg, -1); + Thread.sleep(100); + s.stop(); + // now see if the messages were recorded + int newMessages = t.size() - oldTrackSize; + System.out.println("Recorded messages:"); + for (int i = 0; i < t.size(); i++) { + System.out.print(" "+(i+1)+". "); + printEvent(t.get(i)); + } + if (newMessages == 0) { + System.out.println("## Failed: No messages were recorded!"); + throw new Exception("Test FAILED!"); + } else if (newMessages == 1) { + System.out.println("Only one message was recorded. Correct!"); + } else if (newMessages > 1) { + System.out.println("## Failed: 2 or more messages were recorded!"); + throw new Exception("Test FAILED!"); + } + System.out.println("Test passed."); + } catch (Exception e) { + System.out.println("Unexpected Exception: "+e); + //e.printStackTrace(); + throw new Exception("Test FAILED!"); + } finally { + s.close(); + } + } + public static void printEvent(MidiEvent event) + { + MidiMessage message = event.getMessage(); + long tick = event.getTick(); + byte[] data = message.getMessage(); + + StringBuffer sb = new StringBuffer((data.length * 3) - 1); + + for (int i = 0; i < data.length; i++) + { + sb.append(toHexByteString(data[i])); + if (i < data.length - 1) sb.append(' '); + } + System.out.printf("%5d: %s%n", tick, sb); + } + + private static String toHexByteString(int n) + { + if (n < 0) n &= 0xFF; + String s = Integer.toHexString(n).toUpperCase(); + if (s.length() == 1) s = '0' + s; + return s; + } +} diff --git a/test/javax/sound/midi/Sequencer/SeqStartRecording.java b/test/javax/sound/midi/Sequencer/SeqStartRecording.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/SeqStartRecording.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequencer; + +/** + * @test + * @bug 5001943 + * @summary Sequencer.startRecording throws unexpected NPE + * @key headful + */ +public class SeqStartRecording { + public static void main(String argv[]) throws Exception { + Sequencer seq = MidiSystem.getSequencer(); + seq.open(); + try { + seq.startRecording(); + System.out.println("Test passed."); + } catch (NullPointerException npe) { + System.out.println("Caught NPE: "+npe); + npe.printStackTrace(); + throw new Exception("Test FAILED!"); + } catch (Exception e) { + System.out.println("Unexpected Exception: "+e); + e.printStackTrace(); + System.out.println("Test NOT failed."); + } finally { + seq.close(); + } + } +} diff --git a/test/javax/sound/midi/Sequencer/SequencerCacheValues.java b/test/javax/sound/midi/Sequencer/SequencerCacheValues.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/SequencerCacheValues.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Sequencer; + +/** + * @test + * @bug 4716740 + * @summary default sequencer does not set the tempo factor + */ +public class SequencerCacheValues { + + static boolean failed = false; + + public static void main(String args[]) throws Exception { + Sequencer seq = null; + int totalNumberOfSequencers = 0; + + MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + for (int device=0; device72) { + System.out.println(s); + s=""; + } + } + System.out.println(s); + } + + public static Sequence getSequence() throws Exception { + ByteArrayInputStream bais = new ByteArrayInputStream(pitchbend); + Sequence seq = MidiSystem.getSequence(bais); + return seq; + } + + public static byte[] pitchbend = { + 77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 2, 0, 120, 77, 84, 114, 107, 0, 0, + 0, 27, 0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32, + 116, 114, 97, 99, 107, 32, 48, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, -44, + 0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32, 116, 114, + 97, 99, 107, 32, 49, 0, -64, 30, 0, -112, 68, 126, 0, -32, 6, 67, 0, 14, + 71, 0, 20, 74, 0, 26, 77, 0, 32, 80, 0, 42, 85, 6, 50, 89, 6, 56, 92, 5, + 66, 97, 6, 74, 101, 6, 80, 104, 11, 84, 106, 20, 76, 102, 6, 70, 99, 5, 60, + 94, 6, 52, 90, 5, 44, 86, 4, 34, 81, 5, 26, 77, 5, 20, 74, 6, 10, 69, 5, + 2, 65, 7, 0, 64, 42, -112, 66, 123, 11, 68, 0, 72, 63, 126, 4, 66, 0, 43, + -32, 0, 63, 6, 0, 60, 7, 0, 56, 6, 0, 53, 5, 0, 49, 5, 0, 43, 4, 0, 37, 3, + 0, 30, 3, 0, 25, 3, 0, 19, 3, 0, 13, 4, 0, 8, 4, 0, 2, 4, 0, 0, 70, 0, 3, + 5, 0, 9, 3, 0, 14, 7, 0, 16, 25, 0, 21, 5, 0, 25, 7, 0, 28, 5, 0, 32, 5, + 0, 36, 5, 0, 41, 6, 0, 46, 5, 0, 50, 5, 0, 53, 4, 0, 58, 7, 0, 61, 7, 0, + 64, 117, -112, 63, 0, 0, -1, 47, 0 + }; + + static boolean hasSequencer() { + try { + Sequencer seq = MidiSystem.getSequencer(); + if (seq != null) { + seq.open(); + seq.close(); + return true; + } + } catch (Exception e) {} + System.out.println("No sequencer available! Cannot execute test."); + return false; + } +} diff --git a/test/javax/sound/midi/Sequencer/SequencerState.java b/test/javax/sound/midi/Sequencer/SequencerState.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/SequencerState.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; + +/** + * @test + * @bug 4913027 + * @summary several Sequencer methods should specify behaviour on closed Sequencer + */ +public class SequencerState { + + private static boolean hasSequencer() { + try { + Sequencer seq = MidiSystem.getSequencer(); + if (seq != null) { + seq.open(); + seq.close(); + return true; + } + } catch (Exception e) {} + System.out.println("No sequencer available! Cannot execute test."); + return false; + } + + + public static void main(String[] args) throws Exception { + out("4913027: several Sequencer methods should should specify behaviour on closed Sequencer"); + if (hasSequencer()) { + boolean passed = testAll(); + if (passed) { + out("Test PASSED."); + } else { + throw new Exception("Test FAILED."); + } + } + } + + /** + * Execute the test on all available Sequencers. + * + * @return true if the test passed for all Sequencers, false otherwise + */ + private static boolean testAll() throws Exception { + boolean result = true; + MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo(); + for (int i = 0; i < devices.length; i++) { + MidiDevice device = MidiSystem.getMidiDevice(devices[i]); + if (device instanceof Sequencer) { + result &= testSequencer((Sequencer) device); + } + } + return result; + } + + /** + * Execute the test on the passed Sequencer. + * + * @return true if the test is passed this Sequencer, false otherwise + */ + private static boolean testSequencer(Sequencer seq) throws Exception { + boolean result = true; + + out("testing: " + seq); + /* test calls in closed state. + */ + if (seq.isOpen()) { + out("Sequencer is already open, cannot test!"); + return result; + } + + try { + seq.start(); + out("closed state: start() does not throw IllegalStateException!"); + result = false; + } catch (IllegalStateException e) { + } + + try { + seq.stop(); + out("closed state: stop() does not throw IllegalStateException!"); + result = false; + } catch (IllegalStateException e) { + } + + try { + seq.startRecording(); + out("closed state: startRecording() does not throw IllegalStateException!"); + result = false; + } catch (IllegalStateException e) { + } + + try { + seq.stopRecording(); + out("closed state: stopRecording() does not throw IllegalStateException!"); + result = false; + } catch (IllegalStateException e) { + } + + Sequence sequence = createSequence(); + if (sequence == null) { + out("created Sequence is null, cannot test!"); + return result; + } + try { + seq.setSequence(sequence); + } catch (IllegalStateException e) { + out("closed state: setSequence(Sequence) throws IllegalStateException!"); + result = false; + } + + InputStream inputStream = createSequenceInputStream(); + if (inputStream == null) { + out("created InputStream is null, cannot test!"); + return result; + } + try { + seq.setSequence(inputStream); + } catch (IllegalStateException e) { + out("closed state: setSequence(InputStream) throws IllegalStateException!"); + result = false; + } + + try { + seq.getSequence(); + } catch (IllegalStateException e) { + out("closed state: getSequence() throws IllegalStateException!"); + result = false; + } + + /* test calls in open state. + */ + seq.open(); + if (! seq.isOpen()) { + out("Sequencer is not open, cannot test!"); + return result; + } + + try { + seq.start(); + } catch (IllegalStateException e) { + out("open state: start() throws IllegalStateException!"); + result = false; + } + + try { + seq.stop(); + } catch (IllegalStateException e) { + out("open state: stop() throws IllegalStateException!"); + result = false; + } + + try { + seq.startRecording(); + } catch (IllegalStateException e) { + out("open state: startRecording() throws IllegalStateException!"); + result = false; + } + + try { + seq.stopRecording(); + } catch (IllegalStateException e) { + out("open state: stopRecording() throws IllegalStateException!"); + result = false; + } + + sequence = createSequence(); + if (sequence == null) { + out("created Sequence is null, cannot test!"); + return result; + } + try { + seq.setSequence(sequence); + } catch (IllegalStateException e) { + out("open state: setSequence(Sequence) throws IllegalStateException!"); + result = false; + } + + inputStream = createSequenceInputStream(); + if (inputStream == null) { + out("created InputStream is null, cannot test!"); + return result; + } + try { + seq.setSequence(inputStream); + } catch (IllegalStateException e) { + out("open state: setSequence(InputStream) throws IllegalStateException!"); + result = false; + } + + try { + seq.getSequence(); + } catch (IllegalStateException e) { + out("open state: getSequence() throws IllegalStateException!"); + result = false; + } + + seq.close(); + return result; + } + + /** + * Create a new Sequence for testing. + * + * @return a dummy Sequence, or null, if a problem occured while creating + * the Sequence + */ + private static Sequence createSequence() { + Sequence sequence = null; + try { + sequence = new Sequence(Sequence.PPQ, 480, 1); + } catch (InvalidMidiDataException e) { + // DO NOTHING + } + return sequence; + } + + /** + * Create a new InputStream containing a Sequence for testing. + * + * @return an InputStream containing a dummy Sequence, or null, if a problem + * occured while creating the InputStream + */ + private static InputStream createSequenceInputStream() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Sequence sequence = createSequence(); + if (sequence == null) { + return null; + } + try { + MidiSystem.write(sequence, 0, baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + return bais; + } catch (IOException e) { + return null; + } + } + + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/midi/Sequencer/SetTickPosition.java b/test/javax/sound/midi/Sequencer/SetTickPosition.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/SetTickPosition.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4493775 + * @summary Sequncer method, setTickPosition(long) doesnot set the Tick position + */ +public class SetTickPosition { + private static boolean testPassed = true; + + public void runTest() + { + Sequencer theSequencer = null; + try + { + System.out.print("Getting Sequencer..."); + theSequencer = MidiSystem.getSequencer(); + System.out.println("got "+theSequencer); + + if(!(theSequencer.isOpen())) + { + System.out.println("Opening Sequencer..."); + theSequencer.open(); + + if(!(theSequencer.isOpen())) + { + System.out.println("Unable to open the Sequencer. Test NOT FAILED."); + return; + } + } + + System.out.println("theSequencer is open!\n"); + + System.out.println("Creating New Sequence..."); + Sequence theSequence = new Sequence(Sequence.PPQ, 120); + + System.out.println("Adding Track To Sequence..."); + Track theTrack = theSequence.createTrack(); + + int theChannel = 0; + + int theNote = 60; + int theVelocity = 100; + ShortMessage theShortMessage = new ShortMessage(); + + for (int tick=0; tick<2000; tick+=120) { + //System.out.println("Adding NOTE_ON To Track At Tick: " + tick + "...\n"); + theShortMessage.setMessage(ShortMessage.NOTE_ON, theChannel, theNote, theVelocity); + MidiEvent theMidiEvent = new MidiEvent(theShortMessage, tick); + theTrack.add(theMidiEvent); + + //System.out.println("Adding NOTE_OFF To Track At Tick: " + (tick+60) + "...\n"); + theShortMessage.setMessage(ShortMessage.NOTE_OFF, theChannel, theNote, theVelocity); + theMidiEvent = new MidiEvent(theShortMessage, tick+60); + theTrack.add(theMidiEvent); + } + theSequencer.setSequence(theSequence); + + float theTempoInBPM = 120; + theSequencer.setTempoInBPM(theTempoInBPM); + long theTickLengthOfSequence = theSequencer.getTickLength(); + System.out.println("Length Of Sequence In Ticks: " + theTickLengthOfSequence); + System.out.println("Sequence resolution: " + theSequencer.getSequence().getResolution()); + + theSequencer.start(); + for(long theTickPosition = 0; theTickPosition < theTickLengthOfSequence; theTickPosition += (theTickLengthOfSequence / 10)) + { + System.out.println("Now Setting Tick Position To: " + theTickPosition); + theSequencer.setTickPosition(theTickPosition); + + long theCurrentTickPosition = theSequencer.getTickPosition(); + long theCurrentMsPosition = (long) (theSequencer.getMicrosecondPosition()/1000); + System.out.println("IsRunning()=" + theSequencer.isRunning()); + System.out.println("Now Current Tick Position Is: " + theCurrentTickPosition); + //System.out.println("Now Current micro Position Is: " + theCurrentMsPosition); + System.out.println(""); + + try { + Thread.sleep(800); + } catch (InterruptedException ie) {} + + // last time, set tick pos to 0 + if (theTickPosition>0 && theTickPosition<(theTickLengthOfSequence / 10)) { + theTickPosition=(theTickLengthOfSequence / 10); + } + + // 30 = 1/4 * 120, the resolution of the sequence + if(Math.abs(theCurrentTickPosition - theTickPosition) > 30) { + System.out.println("theCurrentTickPosition != theTickPosition!"); + testPassed = false; + } + } + + } + catch (Exception ex) { ex.printStackTrace(); } + if (theSequencer != null) { + theSequencer.close(); + } + if (testPassed) { + System.out.println("Test Passed."); + } + } + + public static void main(String[] args) throws Exception { + SetTickPosition thisTest = new SetTickPosition(); + thisTest.runTest(); + if (!testPassed) { + throw new Exception("Test FAILED"); + } + } +} diff --git a/test/javax/sound/midi/Sequencer/TickLength.java b/test/javax/sound/midi/Sequencer/TickLength.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Sequencer/TickLength.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaEventListener; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4427890 + * @run main/othervm TickLength + * @summary Sequencer.getTickLength() and Sequence.getTickLength() report the + * wrong length + */ +public class TickLength implements MetaEventListener { + private Sequence theSequence; + private Sequencer theSequencer; + + public TickLength() { + this.initMidiCompoments(); + System.out.println("Got Sequencer "+theSequencer); + theSequence = this.generateSequence(); + try { + theSequencer.setSequence(theSequence); + } + catch(Exception e) { + System.out.println(this.getClass()+"\tCannot set sequence to sequencer ("+e+")"); + return; + } + } + + public void start() { + theSequencer.start(); + } + + /* + instantiate the necessary midi components + */ + private boolean initMidiCompoments() { + + + try { + theSequencer = MidiSystem.getSequencer(); + } + catch(Exception e) { + System.out.println(this.getClass()+"\tSequencer Device not supported"+e+")"); + return false; + } + + try { + theSequencer.open(); + } + catch(Exception e) { + System.out.println(this.getClass()+"Cannot open Sequencer Device"); + return false; + } + if(!theSequencer.addMetaEventListener(this)) { + System.out.println(this.getClass()+"\tCould not register MetaEventListener - there will be problems with scrolling! "); + return false; + } + return true; + } + + static int lastTick = 0; + + private Sequence generateSequence() { + MidiEvent dummyMidiEvent; + ShortMessage dummyShortMessage; + Sequence dummySequence = null; + Track[] allTracks ; + Track theTrack; + + try { + dummySequence = new Sequence(Sequence.PPQ,1500); + } + catch(InvalidMidiDataException e) { + System.out.println("O o "+e); + } + + dummySequence.createTrack(); + allTracks = dummySequence.getTracks(); + theTrack = allTracks[0]; + lastTick = 0; + for(int i=0;i<20; i++) { + theTrack.add(this.createShortMidiEvent(ShortMessage.NOTE_ON, 2, 30+i, 100,100+1000*i)); + theTrack.add(this.createMetaMidiEvent(1,"start",100+1000*i)); + lastTick = (1000*i)+600; + theTrack.add(this.createShortMidiEvent(ShortMessage.NOTE_OFF, 2, 30+i, 100, lastTick)); + theTrack.add(this.createMetaMidiEvent(1,"end",lastTick)); + } + + return dummySequence; + } + + /* + A method to create a short midi event (sound) + */ + + public MidiEvent createShortMidiEvent(int theCommand, int theChannel, int theData1, int theData2, long theTime) { + ShortMessage dummyShortMessage; + MidiEvent dummyMidiEvent; + + try { + dummyShortMessage = new ShortMessage(); + dummyShortMessage.setMessage(theCommand, theChannel, theData1, theData2); + dummyMidiEvent = new MidiEvent(dummyShortMessage,theTime); + } + catch (Exception e) { + System.out.println(this.getClass()+"\t"+e); + return null; + } + + return dummyMidiEvent; + } + + /* + A method to create a meta midi event (used in meta() method) + */ + public MidiEvent createMetaMidiEvent(int theType, String theData1, long theTime) { + MetaMessage dummyMetaMessage; + MidiEvent dummyMidiEvent; + + try { + dummyMetaMessage = new MetaMessage(); + dummyMetaMessage.setMessage(theType, theData1.getBytes(), theData1.length()); + dummyMidiEvent = new MidiEvent(dummyMetaMessage,theTime); + } + catch (Exception e) { + System.out.println(e); + return null; + } + + return dummyMidiEvent; + } + + /* + the method is activated by each meta midi event + it puts out the actual tick position, as well as the WRONG total tick length and the RIGHT + tick length using the work around by dividing the total length by 64 + */ + public void meta(MetaMessage p1) { + if(p1.getType() ==47) { + return; + } + System.out.println("getTickPosition:\t"+theSequencer.getTickPosition() + +"\t Sequencer.getTickLength:\t"+theSequencer.getTickLength() + +"\tReal Length:\t"+lastTick + +"\t Sequence.getTickLength:\t"+theSequence.getTickLength() + //(theSequencer.getTickLength()/64)); + ); + } + + public void checkLengths() throws Exception { + System.out.println("Sequencer.getTickLength() = "+theSequencer.getTickLength()); + System.out.println("Sequence.getTickLength() = "+theSequence.getTickLength()); + long diff = theSequencer.getTickLength() - theSequence.getTickLength(); + if (diff > 100 || diff < -100) { + throw new Exception("Difference too large! Failed."); + } + System.out.println("Passed"); + } + + public static void main(String[] args) throws Exception { + if (!hasSequencer()) { + return; + } + TickLength tlt = new TickLength(); + //tlt.start(); + tlt.checkLengths(); + } + + static boolean hasSequencer() { + try { + Sequencer seq = MidiSystem.getSequencer(); + if (seq != null) { + seq.open(); + seq.close(); + return true; + } + } catch (Exception e) {} + System.out.println("No sequencer available! Cannot execute test."); + return false; + } + +} diff --git a/test/javax/sound/midi/ShortMessage/FastShortMessage.java b/test/javax/sound/midi/ShortMessage/FastShortMessage.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/ShortMessage/FastShortMessage.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4851018 + * @summary MidiMessage.getLength and .getData return wrong values. + * also: 4890405: Reading MidiMessage byte array fails in 1.4.2 + */ +public class FastShortMessage { + public static void main(String args[]) throws Exception { + int[] dataMes = {ShortMessage.NOTE_ON | 9, 0x24, 0x50}; + int res = 240; + Sequence midiData = new Sequence(Sequence.PPQ, res); + + Track track = midiData.createTrack(); + ShortMessage msg = new ShortMessage(); + msg.setMessage(dataMes[0], dataMes[1], dataMes[2]); + track.add(new MidiEvent(msg, 0)); + + // save sequence to outputstream + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + MidiSystem.write(midiData, 0, baos); + + // reload that sequence + InputStream is = new ByteArrayInputStream(baos.toByteArray()); + Sequence seq = MidiSystem.getSequence(is); + + track = seq.getTracks()[0]; + msg = (ShortMessage) (track.get(0).getMessage()); + byte[] msgData = msg.getMessage(); + + if (msgData.length != dataMes.length + || (msgData[0] & 0xFF) != dataMes[0] + || (msgData[1] & 0xFF) != dataMes[1] + || (msgData[2] & 0xFF) != dataMes[2]) { + throw new Exception("test failed. read length="+msgData.length); + } + System.out.println("Test Passed."); + } +} diff --git a/test/javax/sound/midi/ShortMessage/FastShortMessage2.java b/test/javax/sound/midi/ShortMessage/FastShortMessage2.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/ShortMessage/FastShortMessage2.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 5011306 + * @summary FastShortMessage.setMessage does not use the data2 parameter + */ +public class FastShortMessage2 { + + public static void main(String args[]) throws Exception { + int[] dataMes = {ShortMessage.NOTE_ON | 9, 0x24, 0x50}; + + Sequence midiData = new Sequence(Sequence.PPQ, 240); + Track track = midiData.createTrack(); + ShortMessage msg = new ShortMessage(); + msg.setMessage(dataMes[0], dataMes[1], dataMes[2]); + track.add(new MidiEvent(msg, 0)); + // save sequence to outputstream + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + MidiSystem.write(midiData, 0, baos); + // reload that sequence + InputStream is = new ByteArrayInputStream(baos.toByteArray()); + Sequence seq = MidiSystem.getSequence(is); + track = seq.getTracks()[0]; + msg = (ShortMessage) (track.get(0).getMessage()); + if (!msg.getClass().toString().contains("FastShortMessage")) { + System.out.println("msg is not FastShortMessage, this test is useless then..."+msg.getClass()); + } + + msg.setMessage(dataMes[0], dataMes[1], dataMes[2]); + byte[] msgData = msg.getMessage(); + + if (msgData.length != dataMes.length + || (msgData[0] & 0xFF) != dataMes[0] + || (msgData[1] & 0xFF) != dataMes[1] + || (msgData[2] & 0xFF) != dataMes[2]) { + System.out.println("status="+(msgData[0] & 0xFF)+" and expected "+dataMes[0]); + System.out.println("data1="+(msgData[1] & 0xFF)+" and expected "+dataMes[1]); + System.out.println("data2="+(msgData[2] & 0xFF)+" and expected "+dataMes[2]); + throw new Exception("Test FAILED!"); + } + System.out.println("Test Passed."); + } +} diff --git a/test/javax/sound/midi/Soundbanks/ExtraCharInSoundbank.java b/test/javax/sound/midi/Soundbanks/ExtraCharInSoundbank.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Soundbanks/ExtraCharInSoundbank.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Soundbank; +import javax.sound.midi.Synthesizer; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4429762 + * @summary Some instrument names in some soundbanks include bad extra characters + */ +public class ExtraCharInSoundbank { + + private static void printName(String loadedName) + { + System.out.println("Loaded Name: " + loadedName); + byte[] theLoadedNameByteArray = loadedName.getBytes(); + + System.out.print("Name Bytes: "); + for(int i = 0; i < theLoadedNameByteArray.length; i++) + System.out.print((Integer.toHexString((int)theLoadedNameByteArray[i]).toUpperCase()) + " "); + System.out.println(""); + System.out.println(""); + } + + private static boolean containsControlChar(String name) { + byte[] bytes = name.getBytes(); + for (int i = 0; i < bytes.length; i++) { + if (bytes[i] < 32) { + return true; + } + } + return false; + } + + public static boolean checkInstrumentNames(Synthesizer theSynthesizer) + { + boolean containsControlCharacters = false; + + Instrument[] theLoadedInstruments = theSynthesizer.getLoadedInstruments(); + + System.out.println("Checking soundbank..."); + for(int theInstrumentIndex = 0; theInstrumentIndex < theLoadedInstruments.length; theInstrumentIndex++) { + String name = theLoadedInstruments[theInstrumentIndex].getName(); + if (containsControlChar(name)) { + containsControlCharacters = true; + System.out.print("Instrument[" + theInstrumentIndex + "] contains unexpected control characters: "); + printName(name); + } + } + return !containsControlCharacters; + } + + public static void main(String[] args) throws Exception { + // the internal synthesizer needs a soundcard to work properly + if (!isSoundcardInstalled()) { + return; + } + Synthesizer theSynth = MidiSystem.getSynthesizer(); + System.out.println("Got synth: "+theSynth); + theSynth.open(); + try { + Soundbank theSoundbank = theSynth.getDefaultSoundbank(); + System.out.println("Got soundbank: "+theSoundbank); + theSynth.loadAllInstruments(theSoundbank); + try { + if (!checkInstrumentNames(theSynth)) { + throw new Exception("Test failed"); + } + } finally { + theSynth.unloadAllInstruments(theSoundbank); + } + } finally { + theSynth.close(); + } + System.out.println("Test passed."); + } + + /** + * Returns true if at least one soundcard is correctly installed + * on the system. + */ + public static boolean isSoundcardInstalled() { + boolean result = false; + try { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + if (mixers.length > 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } +} diff --git a/test/javax/sound/midi/Soundbanks/GetSoundBankIOException.java b/test/javax/sound/midi/Soundbanks/GetSoundBankIOException.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Soundbanks/GetSoundBankIOException.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiSystem; + +/** + * @test + * @bug 4629810 + * @summary MidiSystem.getSoundbank() throws unexpected IOException + */ +public class GetSoundBankIOException { + + public static void main(String args[]) throws Exception { + boolean failed = false; + try { + String filename = "GetSoundBankIOException.java"; + System.out.println("Opening "+filename+" as soundbank..."); + File midiFile = new File(System.getProperty("test.src", "."), filename); + MidiSystem.getSoundbank(midiFile); + //Soundbank sBank = MidiSystem.getSoundbank(new NonMarkableIS()); + System.err.println("InvalidMidiDataException was not thrown!"); + failed = true; + } catch (InvalidMidiDataException invMidiEx) { + System.err.println("InvalidMidiDataException was thrown. OK."); + } catch (IOException ioEx) { + System.err.println("Unexpected IOException was caught!"); + System.err.println(ioEx.getMessage()); + ioEx.printStackTrace(); + failed = true; + } + + if (failed) throw new Exception("Test FAILED!"); + System.out.println("Test passed."); + } + + private static class NonMarkableIS extends InputStream { + int counter = 0; + + public NonMarkableIS() { + } + + public int read() throws IOException { + if (counter > 1000) return -1; + return (++counter) % 256; + } + + public synchronized void mark(int readlimit) { + System.out.println("Called mark with readlimit= "+readlimit); + } + + public synchronized void reset() throws IOException { + throw new IOException("mark/reset not supported"); + } + + public boolean markSupported() { + return false; + } + + } +} diff --git a/test/javax/sound/midi/Synthesizer/AsynchronousMidiChannel.java b/test/javax/sound/midi/Synthesizer/AsynchronousMidiChannel.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Synthesizer/AsynchronousMidiChannel.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import java.io.PrintStream; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.Synthesizer; + +/** + * @test + * @bug 4987585 + * @summary Some MidiChannel methods are asynchronous + */ +public class AsynchronousMidiChannel { + static PrintStream log = System.err; + static PrintStream ref = System.out; + + public static void main(String args[]) { + doIt(args); + } + + public static void doIt(String args[]) { + Synthesizer synth = null; + MidiChannel mChanArr[]; + MidiChannel chan = null; + boolean failed = false; + int i = 0; + int chanNum = 0; + + int val = 1; + int contr = 0; + Soundbank sBank; + Instrument[] insArr; + Instrument instr = null; + Object ev = new Object(); + + try { + synth = MidiSystem.getSynthesizer(); + System.out.println("Got synth: "+synth); + synth.open(); + + int latency = (int) synth.getLatency(); + System.out.println(" -> latency: " + +latency + +" microseconds"); + + mChanArr = synth.getChannels(); + while ((i < mChanArr.length) && (chan == null)) { + chanNum = i; + chan = mChanArr[i++]; + } + if (chan == null) { + System.out.println("No channels in " + +"this synthesizer!"); + return; + } + System.out.println("Got MidiChannel: "+chan); + + + sBank = synth.getDefaultSoundbank(); + if (sBank == null) { + System.out.println("No default sound bank!"); + return; + } + + + insArr = sBank.getInstruments(); + for (int j = 0; j < insArr.length; j++) { + if (insArr[j].getPatch().getBank() == val) { + instr = insArr[j]; + synth.loadInstrument(instr); + } + } + if (instr == null) { + System.out.println("No instr. with this bank!"); + return; + } + + chan.controlChange(contr, val); + + // need to respect the synthesizer's latency + if (latency > 0) { + try { + Thread.sleep(latency/1000); + } catch (InterruptedException inEx) { + } + } + + if (chan.getController(contr) != val) { + failed = true; + System.err.println("getController() does not " + +"return proper value: " + + chan.getController(contr)); + } else { + System.out.println("getController(" + + contr + ") returns proper value: " + + chan.getController(contr)); + } + + } catch (MidiUnavailableException mue) { + System.err.println("MidiUnavailableException was " + +"thrown: " + mue); + System.out.println("could not test."); + return; + } catch(SecurityException se) { + se.printStackTrace(); + System.err.println("Sound access is not denied but " + + "SecurityException was thrown!"); + return; + + } finally { + if (synth != null) synth.close(); + } + + + if (failed == true) { + System.out.println("test failed"); + } else { + System.out.println("OKAY"); + } + return; + } +} diff --git a/test/javax/sound/midi/Synthesizer/Receiver/bug6186488.java b/test/javax/sound/midi/Synthesizer/Receiver/bug6186488.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Synthesizer/Receiver/bug6186488.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2005, 2016, 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. + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.MidiSystem; + +/** + * @test + * @bug 6186488 + * @summary Tests that software Java Syntesizer processed + * non-ShortMessage-derived messages + * @run main/manual=yesno bug6186488 + */ +public class bug6186488 { + public static void main(String[] args) throws Exception { + MidiDevice/*Synthesizer*/ synth = null; + + try { + synth = MidiSystem.getSynthesizer(); + //synth = MidiSystem.getMidiDevice(infos[0]); + + System.out.println("Synthesizer: " + synth.getDeviceInfo()); + synth.open(); + MidiMessage msg = new GenericMidiMessage(0x90, 0x3C, 0x40); + //ShortMessage msg = new ShortMessage(); + //msg.setMessage(0x90, 0x3C, 0x40); + + synth.getReceiver().send(msg, 0); + Thread.sleep(2000); + + } catch (Exception ex) { + ex.printStackTrace(); + throw ex; + } finally { + if (synth != null && synth.isOpen()) + synth.close(); + } + System.out.print("Did you heard a note? (enter 'y' or 'n') "); + int result = System.in.read(); + System.in.skip(1000); + if (result == 'y' || result == 'Y') + { + System.out.println("Test passed sucessfully."); + } + else + { + System.out.println("Test FAILED."); + throw new RuntimeException("Test failed."); + } + } + + private static class GenericMidiMessage extends MidiMessage { + GenericMidiMessage(int... message) { + super(new byte[message.length]); + for (int i=0; i latency: " + +latency + +" microseconds"); + if (latency < 5000 && latency > 0) { + System.out.println("## This latency is VERY small, probably due to this bug."); + System.out.println("## This causes failure of this test."); + failed = true; + } + } catch (MidiUnavailableException mue) { + System.err.println("MidiUnavailableException was " + +"thrown: " + mue); + System.out.println("could not test."); + notexec = true; + } catch(SecurityException se) { + se.printStackTrace(); + System.err.println("Sound access is not denied but " + + "SecurityException was thrown!"); + notexec = true; + } finally { + if (synth != null) synth.close(); + } + + + if (failed) { + throw new Exception("Test FAILED!"); + } + if (notexec) { + System.out.println("Test not failed."); + } else { + System.out.println("Test Passed."); + } + } +} diff --git a/test/javax/sound/midi/Synthesizer/bug4685396.java b/test/javax/sound/midi/Synthesizer/bug4685396.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Synthesizer/bug4685396.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2006, 2016, 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. + */ + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Soundbank; +import javax.sound.midi.Synthesizer; + +/** + * @test + * @bug 4685396 + * @summary Tests that Synthesizer.remapInstrument works + * @run main bug4685396 + * @key headful + */ +public class bug4685396 { + + static Synthesizer synth = null; + + public static boolean isInstrumentExist(Instrument inst, Instrument[] insts) { + for (int i = 0; i < insts.length; i++) { + if (inst.equals(insts[i])) + return true; + } + return false; + } + + static boolean test( + boolean reloadInstr, // reload all instruments? + boolean unloadFrom, // unload "from" instrument? + boolean unloadTo // unload "to" instrument? + ) throws Exception + { + log("Starting test: reloadInstr=" + reloadInstr + + ", unloadFrom=" + unloadFrom + + ", unloadTo=" + unloadTo + + ""); + + log(" creating synthesizer..."); + synth = MidiSystem.getSynthesizer(); + log(" opening synthesizer..."); + synth.open(); + + Soundbank sbank = synth.getDefaultSoundbank(); + if (sbank == null) + throw new RuntimeException("ERROR: Could not get default soundbank"); + + if (reloadInstr) { + synth.unloadAllInstruments(sbank); + synth.loadAllInstruments(sbank); + } + + Instrument[] instrs = synth.getLoadedInstruments(); + + log(" " + instrs.length + " instruments loaded."); + + if (instrs.length < 2) + throw new RuntimeException("ERROR: need at least 2 loaded instruments"); + + Instrument from = instrs[0]; + Instrument to = instrs[instrs.length - 1]; + + if (unloadFrom) + synth.unloadInstrument(from); + if (unloadTo) + synth.unloadInstrument(to); + + log(" from instrument (" + (unloadFrom ? "UNLOADED" : "LOADED") + + "): " + from.toString()); + log(" to instrument (" + (unloadTo ? "UNLOADED" : "LOADED") + + "): " + to.toString()); + + boolean result = false; + boolean excepted = false; + try { + result = synth.remapInstrument(from, to); + log(" remapInstrument(from, to) returns " + result); + } catch (IllegalArgumentException ex) { + excepted = true; + log(" EXCEPTION:"); + ex.printStackTrace(System.out); + } + + instrs = synth.getLoadedInstruments(); + log(" " + instrs.length + " instruments remains loaded."); + + boolean toUnloaded = !isInstrumentExist(to, instrs); + boolean fromUnloaded = !isInstrumentExist(from, instrs); + + log(" from instrument is " + (fromUnloaded ? "UNLOADED" : "LOADED")); + log(" to instrument is " + (toUnloaded ? "UNLOADED" : "LOADED")); + + boolean bOK = true; + if (result) { + if (unloadTo) { + bOK = false; + log("ERROR: unloaded to, but sucessfull remap"); + } + if (!fromUnloaded) { + bOK = false; + log("ERROR: sucessfull remap, but from hasn't been unloaded"); + } + if (toUnloaded) { + bOK = false; + log("ERROR: to has been unloaded!"); + } + } else { + if (!excepted) { + bOK = false; + log("ERROR: remap returns false, exception hasn't been thrown"); + } + if (!unloadTo) { + bOK = false; + log("ERROR: to is loaded, but remap returns false"); + } + if (unloadFrom != fromUnloaded) { + bOK = false; + log("ERROR: remap returns false, but status of from has been changed"); + } + } + + if (bOK) { + log("Test result: OK\n"); + } else { + log("Test result: FAIL\n"); + } + + return bOK; + } + + static void cleanup() { + if (synth != null) { + synth.close(); + synth = null; + } + } + + static boolean runTest( + boolean reloadInstr, // reload all instruments? + boolean unloadTo, // unload "to" instrument? + boolean unloadFrom // unload "from" instrument? + ) + { + boolean success = false; + try { + success = test(reloadInstr, unloadFrom, unloadTo); + } catch (Exception ex) { + log("Exception: " + ex.toString()); + } + cleanup(); + return success; + } + + public static void main(String args[]) throws Exception { + boolean failed = false; + if (!runTest(true, false, false)) + failed = true; + if (!runTest(true, false, true)) + failed = true; + if (!runTest(true, true, false)) + failed = true; + if (!runTest(true, true, true)) + failed = true; + + if (failed) { + throw new RuntimeException("Test FAILED."); + } + log("Test sucessfully passed."); + } + + + // helper routines + static long startTime = currentTimeMillis(); + static long currentTimeMillis() { + //return System.nanoTime() / 1000000L; + return System.currentTimeMillis(); + } + static void log(String s) { + long time = currentTimeMillis() - startTime; + long ms = time % 1000; + time /= 1000; + long sec = time % 60; + time /= 60; + long min = time % 60; + time /= 60; + System.out.println("" + + (time < 10 ? "0" : "") + time + + ":" + (min < 10 ? "0" : "") + min + + ":" + (sec < 10 ? "0" : "") + sec + + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms + + " (" + Thread.currentThread().getName() + ") " + s); + } + static void delay(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) {} + } +} diff --git a/test/javax/sound/midi/Track/TrackAddSameTick.java b/test/javax/sound/midi/Track/TrackAddSameTick.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Track/TrackAddSameTick.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.midi.MidiEvent; +import javax.sound.midi.Sequence; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Track; + +/** + * @test + * @bug 4941944 + * @summary Track may not have a determined order for inserting events at same + * tick time + */ +public class TrackAddSameTick { + + static boolean failed = false; + static MidiEvent[] evs = new MidiEvent[10]; + + public static void main(String argv[]) throws Exception { + Sequence seq = new Sequence(Sequence.PPQ, 240); + Track t = seq.createTrack(); + + log("add 10 events in random order"); + t.add(createEvent(10, 5)); + t.add(createEvent(0, 0)); + t.add(createEvent(10, 6)); + t.add(createEvent(11, 8)); + t.add(createEvent(10, 7)); + t.add(createEvent(0, 1)); + t.add(createEvent(0, 2)); + t.add(createEvent(15, 9)); + t.add(createEvent(0, 3)); + t.add(createEvent(1, 4)); + + // now compare the events. + // The note param will tell us the + // the expected position + long lastTick = 0; + for (int i = 0; i < t.size(); i++) { + MidiEvent ev = t.get(i); + if (ev.getMessage() instanceof ShortMessage) { + ShortMessage msg = (ShortMessage) ev.getMessage(); + log(""+i+": ShortMessage at tick "+ev.getTick() + +" with expected position "+msg.getData1()); + if (ev.getTick() < lastTick) { + log(" FAILED: last tick is larger than this event's tick!"); + failed = true; + } + if (i != msg.getData1()) { + log(" FAILED: Track did not order correctly."); + failed = true; + } + } + } + + if (failed) throw new Exception("Test FAILED!"); + log("Test passed."); + } + + public static MidiEvent createEvent(long tick, int expectedPos) + throws Exception { + ShortMessage msg = new ShortMessage(); + msg.setMessage(0x90, (int) expectedPos, 00); + MidiEvent ev = new MidiEvent(msg, tick); + return ev; + } + + public static void log(String s) { + System.out.println(s); + } + + public static void log(Exception e) { + //System.out.println(s); + e.printStackTrace(); + } +} diff --git a/test/javax/sound/midi/Track/bug6416024.java b/test/javax/sound/midi/Track/bug6416024.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Track/bug6416024.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2006, 2016, 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. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.Sequence; +import javax.sound.midi.Track; + +/** + * @test + * @bug 6416024 + * @summary Tests that sequence correctly handle removing of EndOfTrack event + * @run main bug6416024 + */ +public class bug6416024 { + + boolean test() { + Sequence sequence = null; + Track track = null; + MidiEvent event = null; + + log("creating sequence..."); + try { + sequence = new Sequence(Sequence.PPQ, 10); + log(" - OK: " + sequence); + } catch(InvalidMidiDataException e ) { + log(" - FAILED: got exception"); + e.printStackTrace(System.out); + return false; + } + + log("creating track..."); + track = sequence.createTrack(); + log(" - OK: " + track); + log("initial track size=" + track.size()); + + log("removing all track events..."); + while (track.size() > 0) { + try { + event = track.get(0); + log(" ..removing event " + event); + track.remove(event); + log(" - OK, track size=" + track.size()); + } catch (Exception e) { + log(" - FAILED: got exception"); + e.printStackTrace(System.out); + return false; + } + } + + MetaMessage newMsg = new MetaMessage(); + MidiEvent newEvent = new MidiEvent(newMsg, 10); + log("adding new event..."); + try { + if (!track.add(newEvent)) { + log("event hasn't been added"); + return false; + } + log(" - OK, track size=" + track.size()); + } catch (Exception e) { + log(" - FAILED: got exception"); + e.printStackTrace(System.out); + return false; + } + + return true; + } + + public static void main(String args[]) throws Exception { + bug6416024 This = new bug6416024(); + if (This.test()) { + log("Test passed sucessfully."); + } else { + log("Test FAILED!"); + delay(1000); + throw new RuntimeException("Test failed!"); + } + } + + // helper routines + static long startTime = currentTimeMillis(); + static long currentTimeMillis() { + //return System.nanoTime() / 1000000L; + return System.currentTimeMillis(); + } + static void log(String s) { + long time = currentTimeMillis() - startTime; + long ms = time % 1000; + time /= 1000; + long sec = time % 60; + time /= 60; + long min = time % 60; + time /= 60; + System.out.println("" + + (time < 10 ? "0" : "") + time + + ":" + (min < 10 ? "0" : "") + min + + ":" + (sec < 10 ? "0" : "") + sec + + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms + + " (" + Thread.currentThread().getName() + ") " + s); + } + static void delay(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) {} + } +} diff --git a/test/javax/sound/midi/Transmitter/bug6415669.java b/test/javax/sound/midi/Transmitter/bug6415669.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/midi/Transmitter/bug6415669.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2006, 2016, 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. + */ + +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Transmitter; + +/** + * @test + * @bug 6415669 + * @summary Tests that terminating thread which got transmitter doesn't cause + * JVM crash (windows) + * @run main bug6415669 + */ +public class bug6415669 { + + public static void main(String args[]) throws Exception { + String osStr = System.getProperty("os.name"); + boolean isWin = osStr.toLowerCase().startsWith("windows"); + log("OS: " + osStr); + log("Arch: " + System.getProperty("os.arch")); + if (!isWin) { + log("The test is for Windows only"); + return; + } + + bug6415669 This = new bug6415669(); + if (This.test()) { + log("Test sucessfully passed."); + } else { + log("Test FAILED!"); + throw new RuntimeException("Test FAILED!"); + } + } + + volatile Transmitter transmitter = null; + Thread openThread = null; + boolean test() { + openThread = new Thread(new Runnable() { + public void run() { + try { + log("openThread: getting transmitter..."); + transmitter = MidiSystem.getTransmitter(); + log("openThread: - OK: " + transmitter); + } catch (MidiUnavailableException ex) { + log("openThread: - Exception: "); + ex.printStackTrace(System.out); + log("openThread: skipping..."); + } + log("openThread: exiting..."); + } + }); + log("starting openThread..."); + openThread.start(); + + while (openThread.isAlive()) + delay(500); + // make additional delay + delay(500); + + if (transmitter == null) { + return true; // midi is not available, just ignore + } + + log("closing transmitter"); + transmitter.close(); + log(" - OK"); + + return true; + } + + // helper routines + static long startTime = currentTimeMillis(); + static long currentTimeMillis() { + //return System.nanoTime() / 1000000L; + return System.currentTimeMillis(); + } + static void log(String s) { + long time = currentTimeMillis() - startTime; + long ms = time % 1000; + time /= 1000; + long sec = time % 60; + time /= 60; + long min = time % 60; + time /= 60; + System.out.println("" + + (time < 10 ? "0" : "") + time + + ":" + (min < 10 ? "0" : "") + min + + ":" + (sec < 10 ? "0" : "") + sec + + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms + + " (" + Thread.currentThread().getName() + ") " + s); + } + static void delay(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) {} + } +} diff --git a/test/javax/sound/sampled/AudioFileFormat/AudioFileFormatToString.java b/test/javax/sound/sampled/AudioFileFormat/AudioFileFormatToString.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioFileFormat/AudioFileFormatToString.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; + +/** + * @test + * @bug 4672864 + * @summary AudioFileFormat.toString() throws unexpected NullPointerException + */ +public class AudioFileFormatToString { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + public static void main(String argv[]) throws Exception { + int testExitStatus = run(argv, System.out); + if (testExitStatus != STATUS_PASSED) { + throw new Exception("Test FAILED " + testExitStatus); + } + System.out.println("Test passed."); + } + + public static int run(String argv[], java.io.PrintStream out) { + int testResult = STATUS_PASSED; + + out.println("\n==> Test for AudioFileFormat class:"); + + AudioFormat testAudioFormat = + new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, // AudioFormat.Encoding + (float) 44100.0, // float SampleRate + (int) 8, // int sampleSizeInBits + (int) 2, // int channels + (int) 2, // int frameSize + (float) 110.0, // float frameRate + true // boolean bigEndian + ); + AudioFormat nullAudioFormat = null; + + AudioFileFormat.Type testAudioFileFormatType = AudioFileFormat.Type.WAVE; + AudioFileFormat.Type nullAudioFileFormatType = null; + + AudioFileFormat testedAudioFileFormat = null; + out.println("\n>> public AudioFileFormat constructor for AudioFileFormat.Type = null: "); + try { + testedAudioFileFormat = + new AudioFileFormat(nullAudioFileFormatType, // AudioFileFormat.Type + testAudioFormat, // AudioFormat + (int) 1024 // int frameLength + ); + out.println("> No any Exception was thrown!"); + out.println("> testedAudioFileFormat.getType():"); + try { + AudioFileFormat.Type producedType = testedAudioFileFormat.getType(); + out.println("> PASSED: producedType = " + producedType); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + out.println("> testedAudioFileFormat.toString():"); + try { + String producedString = testedAudioFileFormat.toString(); + out.println("> PASSED: producedString = " + producedString); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + } catch (IllegalArgumentException illegArgExcept) { + out.println("> PASSED: expected IllegalArgumentException was thrown:"); + illegArgExcept.printStackTrace(out); + } catch (NullPointerException nullPE) { + out.println("> PASSED: expected NullPointerException was thrown:"); + nullPE.printStackTrace(out); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + out.println("\n>> public AudioFileFormat constructor for AudioFormat = null: "); + try { + testedAudioFileFormat = + new AudioFileFormat(testAudioFileFormatType, // AudioFileFormat.Type + nullAudioFormat, // AudioFormat + (int) 1024 // int frameLength + ); + out.println("> No any Exception was thrown!"); + out.println("> testedAudioFileFormat.getFormat():"); + try { + AudioFormat producedFormat = testedAudioFileFormat.getFormat(); + out.println("> PASSED: producedFormat = " + producedFormat); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + out.println("> testedAudioFileFormat.toString():"); + try { + String producedString = testedAudioFileFormat.toString(); + out.println("> PASSED: producedString = " + producedString); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + } catch (IllegalArgumentException illegArgExcept) { + out.println("> PASSED: expected IllegalArgumentException was thrown:"); + illegArgExcept.printStackTrace(out); + } catch (NullPointerException nullPE) { + out.println("> PASSED: expected NullPointerException was thrown:"); + nullPE.printStackTrace(out); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + out.println("\n>> protected AudioFileFormat constructor for AudioFileFormat.Type = null: "); + try { + testedAudioFileFormat = + new TestAudioFileFormat(nullAudioFileFormatType, // AudioFileFormat.Type + (int) 1024, // byteLength + testAudioFormat, // AudioFormat + (int) 1024 // int frameLength + ); + out.println("> No any Exception was thrown!"); + out.println("> testedAudioFileFormat.getType():"); + try { + AudioFileFormat.Type producedType = testedAudioFileFormat.getType(); + out.println("> PASSED: producedType = " + producedType); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + out.println("> testedAudioFileFormat.toString():"); + try { + String producedString = testedAudioFileFormat.toString(); + out.println("> PASSED: producedString = " + producedString); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + } catch (IllegalArgumentException illegArgExcept) { + out.println("> PASSED: expected IllegalArgumentException was thrown:"); + illegArgExcept.printStackTrace(out); + } catch (NullPointerException nullPE) { + out.println("> PASSED: expected NullPointerException was thrown:"); + nullPE.printStackTrace(out); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + out.println("\n>> protected AudioFileFormat constructor for AudioFormat = null: "); + try { + testedAudioFileFormat = + new TestAudioFileFormat(testAudioFileFormatType, // AudioFileFormat.Type + (int) 1024, // byteLength + nullAudioFormat, // AudioFormat + (int) 1024 // int frameLength + ); + out.println("> No any Exception was thrown!"); + out.println("> testedAudioFileFormat.getFormat():"); + try { + AudioFormat producedFormat = testedAudioFileFormat.getFormat(); + out.println("> PASSED: producedFormat = " + producedFormat); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + out.println("> testedAudioFileFormat.toString():"); + try { + String producedString = testedAudioFileFormat.toString(); + out.println("> PASSED: producedString = " + producedString); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + } catch (IllegalArgumentException illegArgExcept) { + out.println("> PASSED: expected IllegalArgumentException was thrown:"); + illegArgExcept.printStackTrace(out); + } catch (NullPointerException nullPE) { + out.println("> PASSED: expected NullPointerException was thrown:"); + nullPE.printStackTrace(out); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + if (testResult == STATUS_FAILED) { + out.println("\n==> test FAILED!"); + } else { + out.println("\n==> test PASSED!"); + } + return testResult; + } +} + +class TestAudioFileFormat extends AudioFileFormat { + + TestAudioFileFormat(AudioFileFormat.Type type, int byteLength, + AudioFormat format, int frameLength) { + super(type, byteLength, format, frameLength); + } +} diff --git a/test/javax/sound/sampled/AudioFileFormat/Properties.java b/test/javax/sound/sampled/AudioFileFormat/Properties.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioFileFormat/Properties.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.sound.midi.MidiFileFormat; +import javax.sound.midi.Sequence; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; + +/** + * @test + * @bug 4666845 + * @summary RFE: Add properties to AudioFileFormat and MidiFileFormat + */ +public class Properties { + + static boolean g_failed = false; + + // all of p1 need to be in p2 + static boolean compare(Map p1, Map p2) { + boolean failed = false; + for(String key: (Set) p1.keySet()) { + out(" testing key: "+key); + if (!p2.containsKey(key)) { + out(" missing property: '"+key+"'. Failed"); + failed = true; + } + Object v1 = p1.get(key); + Object v2 = p2.get(key); + if (((v1 == null) && (v2 != null)) + || ((v1 != null) && (v2 == null)) + || !(v1.equals(v2))) { + out(" property '"+key+"' is different: " + +"expected='"+v1+"' " + +"actual='"+v2+"'. Failed"); + failed = true; + } + } + // test if we can modify p2 + try { + int oldSize = p2.size(); + p2.clear(); + if (oldSize > 0 && p2.size() == 0) { + out(" could clear the properties! Failed."); + failed = true; + } + } catch (Exception e) { + // correct + } + return failed; + } + + public static void main(String argv[]) throws Exception { + // don't need to catch exceptions: any exception is a + // failure of this test + + Map p = new HashMap(); + p.put("author", "Florian"); + p.put("duration", new Long(1000)); + p.put("MyProp", "test"); + + out("Testing AudioFileFormat properties:"); + // create an AudioFileFormat with properties + AudioFormat format = new AudioFormat( 44100.0f, 16, 2, true, false); + AudioFileFormat aff = + new AudioFileFormat(AudioFileFormat.Type.WAVE, + format, 1000, p); + // test that it has the properties + boolean failed = compare(p, aff.properties()); + // test getProperty() + Object o = aff.getProperty("author"); + if (o == null || !o.equals("Florian")) { + out(" getProperty did not report an existing property!"); + failed = true; + } + o = aff.getProperty("does not exist"); + if (o != null) { + out(" getProperty returned something for a non-existing property!"); + failed = true; + } + if (!failed) { + out(" OK"); + } else { + g_failed = true; + } + + + + out("Testing MidiFileFormat properties:"); + // create a MidiFileFormat with properties + MidiFileFormat mff = + new MidiFileFormat(0, Sequence.PPQ, 240, + 1000, 100, p); + // test that it has the properties + failed = compare(p, mff.properties()); + // test getProperty() + o = mff.getProperty("author"); + if (o == null || !o.equals("Florian")) { + out(" getProperty did not report an existing property!"); + failed = true; + } + o = mff.getProperty("does not exist"); + if (o != null) { + out(" getProperty returned something for a non-existing property!"); + failed = true; + } + if (!failed) { + out(" OK"); + } else { + g_failed = true; + } + + + if (g_failed) throw new Exception("Test FAILED!"); + System.out.println("Test passed."); + } + + static void out(String s) { + System.out.println(s); + } +} diff --git a/test/javax/sound/sampled/AudioFileFormat/TypeEquals.java b/test/javax/sound/sampled/AudioFileFormat/TypeEquals.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioFileFormat/TypeEquals.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioFileFormat; + +/** + * @test + * @bug 4925483 + * @summary RFE: equals() should compare string in Encoding and Type + */ +public class TypeEquals { + + public static void main(String argv[]) throws Exception { + // first test that we can create our own type + // (the constructor was made public) + AudioFileFormat.Type myType = new AudioFileFormat.Type("WAVE", "wav"); + + // then check if this one equals this new one + // with the static instance in AudioFileFormat.Type + if (!myType.equals(AudioFileFormat.Type.WAVE)) { + throw new Exception("Types do not equal!"); + } + } +} diff --git a/test/javax/sound/sampled/AudioFormat/AudioFormatBitSize.java b/test/javax/sound/sampled/AudioFormat/AudioFormatBitSize.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioFormat/AudioFormatBitSize.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2016, 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 4754759 + * @summary AudioFormat does not handle uncommon bit sizes correctly + */ + +import javax.sound.sampled.AudioFormat; + +public class AudioFormatBitSize { + + public static void main(String[] args) throws Exception { + int bits = 18; + AudioFormat format = new AudioFormat(44100.0f, bits, 1, true, false); + if (format.getFrameSize() * 8 < bits) { + System.out.println("bits = "+bits+" do not fit into a "+format.getFrameSize()+" bytes sample!"); + throw new Exception("Test failed"); + } else + System.out.println("bits = "+bits+" fit OK into a "+format.getFrameSize()+" bytes sample!"); + System.out.println("Test passed"); + } +} diff --git a/test/javax/sound/sampled/AudioFormat/EncodingEquals.java b/test/javax/sound/sampled/AudioFormat/EncodingEquals.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioFormat/EncodingEquals.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; + +/** + * @test + * @bug 4925483 + * @summary RFE: equals() should compare string in Encoding and Type + */ +public class EncodingEquals { + + public static void main(String argv[]) throws Exception { + // first test that we can create our own encoding + // (the constructor was made public) + AudioFormat.Encoding myType = new AudioFormat.Encoding("PCM_SIGNED"); + + // then check if this one equals this new one + // with the static instance in AudioFormat.Encoding + if (!myType.equals(AudioFormat.Encoding.PCM_SIGNED)) { + throw new Exception("Encodings do not equal!"); + } + } +} diff --git a/test/javax/sound/sampled/AudioFormat/Properties.java b/test/javax/sound/sampled/AudioFormat/Properties.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioFormat/Properties.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.sound.sampled.AudioFormat; + +/** + * @test + * @bug 4925767 + * @summary RFE: Add Properties to AudioFormat + */ +public class Properties { + + static boolean g_failed = false; + + // all of p1 need to be in p2 + static boolean compare(Map p1, Map p2) { + boolean failed = false; + for(String key: (Set) p1.keySet()) { + out(" testing key: "+key); + if (!p2.containsKey(key)) { + out(" missing property: '"+key+"'. Failed"); + failed = true; + } + Object v1 = p1.get(key); + Object v2 = p2.get(key); + if (((v1 == null) && (v2 != null)) + || ((v1 != null) && (v2 == null)) + || !(v1.equals(v2))) { + out(" property '"+key+"' is different: " + +"expected='"+v1+"' " + +"actual='"+v2+"'. Failed"); + failed = true; + } + } + // test if we can modify p2 + try { + int oldSize = p2.size(); + p2.clear(); + if (oldSize > 0 && p2.size() == 0) { + out(" could clear the properties! Failed."); + failed = true; + } + } catch (Exception e) { + // correct + } + return failed; + } + + + public static void main(String argv[]) throws Exception { + // don't need to catch exceptions: any exception is a + // failure of this test + + Map p = new HashMap(); + p.put("bitrate", new Integer(128)); + p.put("quality", new Integer(10)); + p.put("MyProp", "test"); + + out("Testing AudioFileFormat properties:"); + // create an AudioFileFormat with properties + AudioFormat format = + new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, + 44100.0f, 16, 2, 4, 44100.0f, false, p); + // test that it has the properties + boolean failed = compare(p, format.properties()); + // test getProperty() + Object o = format.getProperty("MyProp"); + if (o == null || !o.equals("test")) { + out(" getProperty did not report an existing property!"); + failed = true; + } + o = format.getProperty("does not exist"); + if (o != null) { + out(" getProperty returned something for a non-existing property!"); + failed = true; + } + if (!failed) { + out(" OK"); + } else { + g_failed = true; + } + + if (g_failed) throw new Exception("Test FAILED!"); + System.out.println("Test passed."); + } + + static void out(String s) { + System.out.println(s); + } + +} diff --git a/test/javax/sound/sampled/AudioInputStream/AISReadFraction.java b/test/javax/sound/sampled/AudioInputStream/AISReadFraction.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioInputStream/AISReadFraction.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4948663 + * @summary AudioInputStream does not use the original stream passed to its constructor + */ +public class AISReadFraction { + + static int failed = 0; + static byte[] testData = new byte[256]; + static boolean DEBUG = false; + + static AudioFormat[] formats = { + new AudioFormat(44100.0f, 8, 1, false, false), // frameSize = 1 + new AudioFormat(44100.0f, 8, 2, false, false), // frameSize = 2 + new AudioFormat(44100.0f, 16, 1, true, false), // frameSize = 2 + new AudioFormat(44100.0f, 24, 1, true, false), // frameSize = 3 + new AudioFormat(44100.0f, 16, 2, true, false), // frameSize = 4 + new AudioFormat(44100.0f, 8, 5, false, false), // frameSize = 5 + new AudioFormat(44100.0f, 16, 3, true, false), // frameSize = 6 + new AudioFormat(44100.0f, 8, 7, false, false), // frameSize = 7 + new AudioFormat(44100.0f, 32, 2, true, false) // frameSize = 8 + }; + + + public static void main(String args[]) throws Exception { + for (int i = 0; i0) throw new Exception("Test FAILED!"); + out("Test passed."); + } + + static void doTest(AudioFormat format, boolean doMark) { + out("Test with"+(doMark?"":"out")+" marking. Audio format: " + +"sampleSize="+format.getSampleSizeInBits()+"bits " + +"channels="+format.getChannels()+" " + +"frameSize="+format.getFrameSize()+"byte(s)"); + int maxReadBytes = (testData.length / format.getFrameSize()) * format.getFrameSize(); + InputStream is = new FractionalIS(testData, doMark); + AudioInputStream ais = new AudioInputStream(is, format, AudioSystem.NOT_SPECIFIED); + // first some general tests + if (ais.markSupported() && !doMark) { + out(" #AIS reports markSupported, but underlying stream cannot! FAILED"); + failed ++; + } + if (!ais.markSupported() && doMark) { + out(" #AIS does not report markSupported, but underlying stream can mark! FAILED"); + failed++; + } + byte[] data = new byte[1000]; + int frameSize = format.getFrameSize(); + int counter = 5; + int totalReadBytes = 0; + boolean hasRead0 = false; + boolean hasMarked = false; + boolean hasReset = false; + int markPos = 0; + while (true) { + try { + int toBeRead = frameSize * counter; + counter += 3; + if (counter > 14) { + counter -= 14; + } + int read = ais.read(data, 0, toBeRead); + if (DEBUG) out(" -> ais.read(data, 0, "+toBeRead+"): "+read+" (frameSize="+frameSize+")"); + if ((totalReadBytes == maxReadBytes) && (read != -1) + && ((read > 0) || hasRead0)) { + if (read == 0) { + out(" #stream was read to the end ("+maxReadBytes+"), but ais.read returned repeatedly 0 bytes. FAILED"); + } else { + out(" #stream was read to the end ("+maxReadBytes+"), but ais.read returned "+read+" bytes... FAILED"); + } + failed++; + break; + } + if (read > 0) { + verifyReadBytes(data, totalReadBytes, read); + if ((read % frameSize) != 0) { + out(" #Read non-integral number of frames: "+read+" bytes, frameSize="+frameSize+" bytes. FAILED"); + failed++; + } + totalReadBytes += read; + hasRead0 = false; + } + else if (read == 0) { + //out(" wanted to read "+toBeRead+" at position "+totalReadBytes+", but got 0 bytes!"); + if (hasRead0) { + out(" read 0 twice in a row! FAILED"); + failed++; + break; + } + hasRead0 = true; + } else { + // end of stream + out(" End of stream reached. Total read bytes: "+totalReadBytes); + if (totalReadBytes != maxReadBytes) { + out(" #Failed: should have read "+maxReadBytes+" bytes! FAILED."); + failed++; + } + break; + } + + // test marking + if (totalReadBytes > 50 && !hasMarked && !hasReset && doMark) { + out(" Marking at position "+totalReadBytes); + hasMarked = true; + ais.mark(0); + markPos = totalReadBytes; + } + if (totalReadBytes > 100 && hasMarked && !hasReset && doMark) { + out(" Resetting at position "+totalReadBytes+" back to "+markPos); + hasReset = true; + ais.reset(); + totalReadBytes = markPos; + } + + } catch (IOException e) { + out(" #caught unexpected exception:"); + e.printStackTrace(); + failed++; + } + } + } + + static void verifyReadBytes(byte[] data, int offset, int len) { + int firstWrongByte = -1; + for (int i = 0; i < len; i++) { + int expected = ((offset + i) % 128); + if (data[i] != expected) { + out(" read data is not correct! offset="+offset+" expected="+expected+" actual="+data[i]); + failed++; + break; + } + } + } + + + public static void out(String s) { + System.out.println(s); + } + + + static class FractionalIS extends InputStream { + byte[] data; + int pos = 0; + boolean canMark; + // a counter how many bytes are not returned + int missingBytes = 0; + int markPos = -1; + + FractionalIS(byte[] data, boolean canMark) { + this.data = data; + this.canMark = canMark; + } + + public int read() throws IOException { + if (pos >= data.length) { + return -1; + } + return data[pos++] & 0xFF; + } + + public int read(byte[] b, int off, int len) throws IOException { + if (++missingBytes > 5) { + missingBytes = 0; + } + int reducedLen = len - missingBytes; + if (reducedLen <= 0) reducedLen = 1; + if (DEBUG) out(" FIS.read(data, 0, "+len+"): reducing len to "+reducedLen+" bytes."); + int ret = super.read(b, off, reducedLen); + if (DEBUG) out(" returning "+ret+" bytes. Now at pos="+pos); + return ret; + } + + public void mark(int readlimit) { + markPos = pos; + if (DEBUG) out(" FIS.mark(): marking at "+pos); + } + + public void reset() throws IOException { + if (!canMark) { + throw new IOException("reset not supported!"); + } + if (markPos == -1) { + throw new IOException("Mark position not set!"); + } + pos = markPos; + if (DEBUG) out(" FIS.reset(): now back at "+pos); + } + + public boolean markSupported() { + return canMark; + } + + } + +} diff --git a/test/javax/sound/sampled/AudioInputStream/bug6188860.java b/test/javax/sound/sampled/AudioInputStream/bug6188860.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioInputStream/bug6188860.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2005, 2016, 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. + */ + +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 6188860 + * @summary Tests that method AudioInputStream.read() returns right value + */ +public class bug6188860 { + + public static void main(String[] args) throws Exception { + byte[] testData = new byte[256]; + + // fill data + for (int i = 0; i < testData.length; i++) + testData[i] = (byte) (i % 128); + + InputStream streamSrc = new TestInputStream(testData); + AudioFormat format = new AudioFormat(44100.0f, 8, 1, false, false); // frameSize = 1 + AudioInputStream streamAudio = new AudioInputStream(streamSrc, format, AudioSystem.NOT_SPECIFIED); + + int nErrCount = 0; + int nTotal = 0; + + int dataSrc, dataRead; + while (nTotal < (testData.length - 1)) { + dataRead = streamAudio.read(); + if (dataRead < 0) { + System.out.println("end of stream"); + break; + } + + dataSrc = testData[nTotal]; + + if (dataRead != dataSrc) { + System.out.println("" + nTotal + " - mismatch :" + dataRead + " <> " + dataSrc); + nErrCount++; + } + nTotal++; + } + + System.out.println("Total: " + nTotal + "; Mismatches: " + nErrCount); + + if (nErrCount > 0) { + throw new RuntimeException("test failed: " + nErrCount + " mismatches of total " + nTotal + " bytes."); + } + System.out.println("Test sucessfully passed."); + } + + + static class TestInputStream extends InputStream { + byte[] data; + int pos = 0; + + TestInputStream(byte[] data) { + this.data = data; + } + + public int read() throws IOException { + if (pos >= data.length) { + return -1; + } + return data[pos++] & 0xFF; + } + } + +} diff --git a/test/javax/sound/sampled/AudioSystem/AudioFileTypes/AudioFileTypeUniqueness.java b/test/javax/sound/sampled/AudioSystem/AudioFileTypes/AudioFileTypeUniqueness.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioSystem/AudioFileTypes/AudioFileTypeUniqueness.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4883060 + * @summary AudioSystem.getAudioFileTypes returns duplicates + */ +public class AudioFileTypeUniqueness { + + public static void main(String[] args) throws Exception { + boolean foundDuplicates = false; + AudioFileFormat.Type[] aTypes = AudioSystem.getAudioFileTypes(); + for (int i = 0; i < aTypes.length; i++) + { + for (int j = 0; j < aTypes.length; j++) + { + if (aTypes[i].equals(aTypes[j]) && i != j) { + foundDuplicates = true; + } + } + } + if (foundDuplicates) { + throw new Exception("Test failed"); + } else { + System.out.println("Test passed"); + } + } +} diff --git a/test/javax/sound/sampled/AudioSystem/AudioFileTypes/ShowAudioFileTypes.java b/test/javax/sound/sampled/AudioSystem/AudioFileTypes/ShowAudioFileTypes.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioSystem/AudioFileTypes/ShowAudioFileTypes.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2001, 2016, 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. + */ + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4303037 + * @summary Shows the existing audio file types of AudioSystem and checks + * whether there are some at all + */ +public class ShowAudioFileTypes { + + public static void main(String[] args) throws Exception { + AudioFileFormat.Type[] aTypes = AudioSystem.getAudioFileTypes(); + System.out.println(aTypes.length+" supported target types:"); + for (int i = 0; i < aTypes.length; i++) + { + System.out.println(" "+(i+1)+". " + aTypes[i]+" with ext. '"+aTypes[i].getExtension()+"'"); + } + if (aTypes.length<3) { + throw new Exception("Test failed"); + } else { + System.out.println("Test passed"); + } + } +} diff --git a/test/javax/sound/sampled/AudioSystem/DefaultMixers.java b/test/javax/sound/sampled/AudioSystem/DefaultMixers.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioSystem/DefaultMixers.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.util.List; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.Port; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.TargetDataLine; +import javax.sound.sampled.spi.MixerProvider; + +import com.sun.media.sound.JDK13Services; + +/** + * @test + * @bug 4776511 + * @summary RFE: Setting the default MixerProvider. Test the retrieving of lines + * with defaut mixer properties. + * @modules java.desktop/com.sun.media.sound + */ +public class DefaultMixers { + + private static final String ERROR_PROVIDER_CLASS_NAME = "abc"; + private static final String ERROR_INSTANCE_NAME = "def"; + + private static final Class[] lineClasses = { + SourceDataLine.class, + TargetDataLine.class, + Clip.class, + Port.class, + }; + + public static void main(String[] args) throws Exception { + boolean allOk = true; + Mixer.Info[] infos; + + out("Testing Mixers retrieved via AudioSystem"); + infos = AudioSystem.getMixerInfo(); + allOk &= testMixers(infos, null); + + out("Testing MixerProviders"); + List providers = JDK13Services.getProviders(MixerProvider.class); + for (int i = 0; i < providers.size(); i++) { + MixerProvider provider = (MixerProvider) providers.get(i); + infos = provider.getMixerInfo(); + allOk &= testMixers(infos, provider.getClass().getName()); + } + + if (! allOk) { + throw new Exception("Test failed"); + } else { + out("Test passed"); + } + } + + private static boolean testMixers(Mixer.Info[] infos, + String providerClassName) { + boolean allOk = true; + + for (int i = 0; i < infos.length; i++) { + Mixer mixer = null; + try { + mixer = AudioSystem.getMixer(infos[i]); + } catch (NullPointerException e) { + out("Exception thrown; Test NOT failed."); + e.printStackTrace(); + } + for (int j = 0; j < lineClasses.length; j++) { + if (mixer.isLineSupported(new Line.Info(lineClasses[j]))) { + allOk &= testMixer(mixer, lineClasses[j], + providerClassName); + } + } + } + return allOk; + } + + private static boolean testMixer(Mixer mixer, Class lineType, + String providerClassName) { + boolean allOk = true; + String instanceName = mixer.getMixerInfo().getName(); + + // no error + allOk &= testMixer(mixer, lineType, + providerClassName, instanceName); + + // erroneous provider class name, correct instance name + allOk &= testMixer(mixer, lineType, + ERROR_PROVIDER_CLASS_NAME, instanceName); + + // erroneous provider class name, no instance name + allOk &= testMixer(mixer, lineType, + ERROR_PROVIDER_CLASS_NAME, ""); + + // erroneous provider class name, erroneous instance name + allOk &= testMixer(mixer, lineType, + ERROR_PROVIDER_CLASS_NAME, ERROR_INSTANCE_NAME); + + return allOk; + } + + private static boolean testMixer(Mixer mixer, Class lineType, + String providerClassName, + String instanceName) { + boolean allOk = true; + + try { + String propertyValue = (providerClassName != null) ? providerClassName: "" ; + propertyValue += "#" + instanceName; + out("property value: " + propertyValue); + System.setProperty(lineType.getName(), propertyValue); + Line line = null; + Line.Info info = null; + Line.Info[] infos; + AudioFormat format = null; + if (lineType == SourceDataLine.class || lineType == Clip.class) { + infos = mixer.getSourceLineInfo(); + format = getFirstLinearFormat(infos); + info = new DataLine.Info(lineType, format); + } else if (lineType == TargetDataLine.class) { + infos = mixer.getTargetLineInfo(); + format = getFirstLinearFormat(infos); + info = new DataLine.Info(lineType, format); + } else if (lineType == Port.class) { + /* Actually, a Ports Mixer commonly has source infos + as well as target infos. We ignore this here, since we + just need a random one. */ + infos = mixer.getSourceLineInfo(); + for (int i = 0; i < infos.length; i++) { + if (infos[i] instanceof Port.Info) { + info = infos[i]; + break; + } + } + } + out("Line.Info: " + info); + line = AudioSystem.getLine(info); + out("line: " + line); + if (! lineType.isInstance(line)) { + out("type " + lineType + " failed: class should be '" + + lineType + "' but is '" + line.getClass() + "'!"); + allOk = false; + } + } catch (Exception e) { + out("Exception thrown; Test NOT failed."); + e.printStackTrace(); + } + return allOk; + } + + private static AudioFormat getFirstLinearFormat(Line.Info[] infos) { + for (int i = 0; i < infos.length; i++) { + if (infos[i] instanceof DataLine.Info) { + AudioFormat[] formats = ((DataLine.Info) infos[i]).getFormats(); + for (int j = 0; j < formats.length; j++) { + AudioFormat.Encoding encoding = formats[j].getEncoding(); + int sampleSizeInBits = formats[j].getSampleSizeInBits(); + if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED) && + sampleSizeInBits == 16 || + encoding.equals(AudioFormat.Encoding.PCM_UNSIGNED) && + sampleSizeInBits == 16) { + return formats[j]; + } + } + } + } + return null; + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/sampled/AudioSystem/DefaultProperties.java b/test/javax/sound/sampled/AudioSystem/DefaultProperties.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioSystem/DefaultProperties.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.File; + +import com.sun.media.sound.JDK13Services; + +/** + * @test + * @bug 4776511 + * @build DefaultProperties + * @run main/othervm DefaultProperties + * @summary RFE: Setting the default MixerProvider. Test the retrieving and + * parsing of properties. + * @modules java.desktop/com.sun.media.sound + */ +public class DefaultProperties { + + private static final Class[] lineTypeClasses = { + javax.sound.sampled.SourceDataLine.class, + javax.sound.sampled.TargetDataLine.class, + javax.sound.sampled.Clip.class, + javax.sound.sampled.Port.class, + }; + + public static void main(String[] args) throws Exception { + boolean allOk = true; + File file = new File(System.getProperty("test.src", "."), "testdata"); + System.setProperty("java.home", file.getCanonicalPath()); + + for (int i = 0; i < lineTypeClasses.length; i++) { + Class cls = lineTypeClasses[i]; + String propertyName = cls.getName(); + String result; + String provClassName; + String instanceName; + + // properties file, both provider class name and instance name + provClassName = "xyz"; + instanceName = "123"; + result = JDK13Services.getDefaultProviderClassName(cls); + if (! provClassName.equals(result)) { + out("type " + cls + " failed: provider class should be '" + + provClassName + "' but is '" + result + "'!"); + allOk = false; + } + result = JDK13Services.getDefaultInstanceName(cls); + if (! instanceName.equals(result)) { + out("type " + cls + " failed: instance name should be '" + + instanceName + "' but is '" + result + "'!"); + allOk = false; + } + + // system property, provider class name only, no trailing hash + provClassName = "abc"; + System.setProperty(propertyName, provClassName); + result = JDK13Services.getDefaultProviderClassName(cls); + if (! provClassName.equals(result)) { + out("type " + cls + " failed: provider class should be '" + + provClassName + "' but is '" + result + "'!"); + allOk = false; + } + result = JDK13Services.getDefaultInstanceName(cls); + if (result != null) { + out("type " + cls + " failed: instance name should be " + + "null but is '" + result + "'!"); + allOk = false; + } + + // system property, provider class name only, trailing hash + provClassName = "def"; + System.setProperty(propertyName, provClassName + "#"); + result = JDK13Services.getDefaultProviderClassName(cls); + if (! provClassName.equals(result)) { + out("type " + cls + " failed: provider class should be '" + + provClassName + "' but is '" + result + "'!"); + allOk = false; + } + result = JDK13Services.getDefaultInstanceName(cls); + if (result != null) { + out("type " + cls + " failed: instance name should be " + + "null but is '" + result + "'!"); + allOk = false; + } + + // system property, instance name only + instanceName = "ghi"; + System.setProperty(propertyName, "#" + instanceName); + result = JDK13Services.getDefaultProviderClassName(cls); + if (result != null) { + out("type " + cls + " failed: provider class should be " + + "null but is '" + result + "'!"); + allOk = false; + } + result = JDK13Services.getDefaultInstanceName(cls); + if (! instanceName.equals(result)) { + out("type " + cls + " failed: instance name should be '" + + instanceName + "' but is '" + result + "'!"); + allOk = false; + } + + // system property, both provider class and instance name + provClassName = "jkl"; + instanceName = "mno"; + System.setProperty(propertyName, provClassName + "#" + instanceName); + result = JDK13Services.getDefaultProviderClassName(cls); + if (! provClassName.equals(result)) { + out("type " + cls + " failed: provider class should be '" + + provClassName + "' but is '" + result + "'!"); + allOk = false; + } + result = JDK13Services.getDefaultInstanceName(cls); + if (! instanceName.equals(result)) { + out("type " + cls + " failed: instance name should be '" + + instanceName + "' but is '" + result + "'!"); + allOk = false; + } + + // system property, empty + System.setProperty(propertyName, ""); + result = JDK13Services.getDefaultProviderClassName(cls); + if (result != null) { + out("type " + cls + " failed: provider class should be " + + "null but is '" + result + "'!"); + allOk = false; + } + result = JDK13Services.getDefaultInstanceName(cls); + if (result != null) { + out("type " + cls + " failed: instance name should be " + + "null but is '" + result + "'!"); + allOk = false; + } + } + if (! allOk) { + throw new Exception("Test failed"); + } else { + out("Test passed"); + } + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/sampled/AudioSystem/ProviderCacheing.java b/test/javax/sound/sampled/AudioSystem/ProviderCacheing.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioSystem/ProviderCacheing.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.util.List; +import com.sun.media.sound.JDK13Services; + +/** + * @test + * @bug 4776511 + * @summary RFE: Setting the default MixerProvider. Test the cacheing of + * providers. + * @modules java.desktop/com.sun.media.sound + */ +public class ProviderCacheing { + + private static final Class[] providerClasses = { + javax.sound.sampled.spi.AudioFileReader.class, + javax.sound.sampled.spi.AudioFileWriter.class, + javax.sound.sampled.spi.FormatConversionProvider.class, + javax.sound.sampled.spi.MixerProvider.class, + }; + + public static void main(String[] args) throws Exception { + boolean allCached = true; + for (int i = 0; i < providerClasses.length; i++) { + List list0 = JDK13Services.getProviders(providerClasses[i]); + List list1 = JDK13Services.getProviders(providerClasses[i]); + if (list0 == list1) { + out("Providers should not be cached for " + providerClasses[i]); + allCached = false; + } + } + + if (! allCached) { + throw new Exception("Test failed"); + } else { + out("Test passed"); + } + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/sampled/AudioSystem/testdata/lib/conf/sound.properties b/test/javax/sound/sampled/AudioSystem/testdata/lib/conf/sound.properties new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/AudioSystem/testdata/lib/conf/sound.properties @@ -0,0 +1,27 @@ +# +# Copyright (c) 2003, 2016, 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. +# + +javax.sound.sampled.SourceDataLine=xyz#123 +javax.sound.sampled.TargetDataLine=xyz#123 +javax.sound.sampled.Clip=xyz#123 +javax.sound.sampled.Port=xyz#123 diff --git a/test/javax/sound/sampled/Clip/ClipCloseLoss.java b/test/javax/sound/sampled/Clip/ClipCloseLoss.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/ClipCloseLoss.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4946913 + * @summary DirectClip doesn't kill the thread correctly, sometimes + * @run main/othervm ClipCloseLoss + * @key headful + */ +public class ClipCloseLoss { + static int frameCount = 441000; // lets say 10 seconds + static AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false); + static ByteArrayInputStream bais = + new ByteArrayInputStream(new byte[frameCount * format.getFrameSize()]); + + static int success = 0; + static boolean failed = false; + + public static void run(Mixer m) { + Clip clip = null; + try { + if (m == null) { + out("Using default mixer"); + clip = (Clip) AudioSystem.getClip(); + } else { + out("Using mixer: "+m); + DataLine.Info info = new DataLine.Info(Clip.class, format, AudioSystem.NOT_SPECIFIED); + clip = (Clip) m.getLine(info); + } + out(" got clip: "+clip); + if (!clip.getClass().toString().contains("Direct")) { + out(" no direct audio clip -> do not test."); + return; + } + + out(" open"); + bais.reset(); + clip.open(new AudioInputStream(bais, format, frameCount)); + + out(" clip.close()"); + //long t = System.currentTimeMillis(); + clip.close(); + //if (System.currentTimeMillis() - t > 1950) { + // out(" clip.close needed more than 2 seconds! Causes failure of this test."); + // failed = true; + //} + out(" clip closed"); + success++; + } catch (LineUnavailableException luae) { + // line not available, test not failed + System.err.println(luae); + } catch (IllegalArgumentException iae) { + // line not available, test not failed + System.err.println(iae); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public static int getClipThreadCount() { + int ret = 0; + ThreadGroup tg = Thread.currentThread().getThreadGroup(); + while (tg.getParent() != null) { tg = tg.getParent(); } + Thread[] threads = new Thread[500]; + int count = tg.enumerate(threads, true); + for (int i = 0; i < count; i++) { + if (threads[i].getName().contains("Direct") + && threads[i].getName().contains("Clip")) { + out("Found Direct Clip thread object: "+threads[i]); + ret++; + } + } + return ret; + } + + public static void main(String[] args) throws Exception { + if (isSoundcardInstalled()) { + bais.mark(0); + run(null); + Mixer.Info[] infos = AudioSystem.getMixerInfo(); + for (int i = 0; i 0) { + out("Unused clip threads exist! Causes test failure"); + failed = true; + } + if (failed) throw new Exception("Test FAILED!"); + if (success > 0) { + out("Test passed."); + } else { + System.err.println("Test could not execute: please install an audio device"); + } + } + } + + /** + * Returns true if at least one soundcard is correctly installed + * on the system. + */ + public static boolean isSoundcardInstalled() { + boolean result = false; + try { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + if (mixers.length > 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } + + public static void out(String s) { + /*long t = System.nanoTime() / 1000000l; + String ts = ""+(t % 1000); + while (ts.length() < 3) ts = "0"+ts; + System.out.println(""+(t/1000)+":"+ts+" "+s); + System.out.flush();*/ + System.out.println(s); + } +} diff --git a/test/javax/sound/sampled/Clip/ClipFlushCrash.java b/test/javax/sound/sampled/Clip/ClipFlushCrash.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/ClipFlushCrash.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4946945 + * @summary Crash in javasound while running TicTacToe demo applet tiger b26 + */ +public class ClipFlushCrash { + static int frameCount = 441000; // lets say 10 seconds + static AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false); + static ByteArrayInputStream bais = + new ByteArrayInputStream(new byte[frameCount * format.getFrameSize()]); + + static int success = 0; + + public static void run(Mixer m) { + Clip clip = null; + try { + if (m == null) { + out("Using default mixer"); + clip = (Clip) AudioSystem.getClip(); + } else { + out("Using mixer: "+m); + DataLine.Info info = new DataLine.Info(Clip.class, format, AudioSystem.NOT_SPECIFIED); + clip = (Clip) m.getLine(info); + } + out(" got clip: "+clip); + if (!clip.getClass().toString().contains("Direct")) { + out(" no direct audio clip -> do not test."); + return; + } + + out(" open"); + bais.reset(); + clip.open(new AudioInputStream(bais, format, frameCount)); + + AT at1 = new AT(clip, "flush thread", 123) { + public void doAction() throws Exception { + log("flush"); + clip.flush(); + } + }; + AT at2 = new AT(clip, "setFramePosition thread", 67) { + public void doAction() throws Exception { + int pos = (int) (Math.random() * clip.getFrameLength()); + log("setPosition to frame "+pos); + clip.setFramePosition(pos); + } + }; + AT at3 = new AT(clip, "start/stop thread", 300) { + public void doAction() throws Exception { + if (clip.isRunning()) { + log("stop"); + clip.stop(); + } else { + log("start"); + clip.setFramePosition(0); + clip.start(); + } + } + }; + AT at4 = new AT(clip, "open/close thread", 600) { + public synchronized void doAction() throws Exception { + log("close"); + clip.close(); + wait(50); + if (!terminated) { + log("open"); + bais.reset(); + clip.open(new AudioInputStream(bais, format, frameCount)); + } + } + }; + + out(" clip.start"); + clip.start(); + out(" for 10 seconds, call start/stop, setFramePosition, and flush from other threads"); + at1.start(); + at2.start(); + at3.start(); + at4.start(); + try { + Thread.sleep(10000); + } catch (InterruptedException ie) {} + out(" finished."); + at1.terminate(); + at2.terminate(); + at3.terminate(); + at4.terminate(); + out(" clip.close()"); + clip.close(); + success++; + } catch (LineUnavailableException luae) { + // line not available, test not failed + System.err.println(luae); + } catch (IllegalArgumentException iae) { + // line not available, test not failed + System.err.println(iae); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public static void main(String[] args) throws Exception { + if (isSoundcardInstalled()) { + bais.mark(0); + run(null); + Mixer.Info[] infos = AudioSystem.getMixerInfo(); + for (int i = 0; i 0) { + out("No crash -> Test passed"); + } else { + System.err.println("Test could not execute: please install an audio device"); + } + } + } + + /** + * Returns true if at least one soundcard is correctly installed + * on the system. + */ + public static boolean isSoundcardInstalled() { + boolean result = false; + try { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + if (mixers.length > 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } + + public static void out(String s) { + /*long t = System.nanoTime() / 1000000l; + String ts = ""+(t % 1000); + while (ts.length() < 3) ts = "0"+ts; + System.out.println(""+(t/1000)+":"+ts+" "+s); + System.out.flush();*/ + System.out.println(s); + } + + private abstract static class AT extends Thread { + protected boolean terminated = false; + protected Clip clip; + private int waitTime; + + public AT(Clip clip, String name, int waitTime) { + super(name); + this.clip = clip; + this.waitTime = waitTime; + } + + public abstract void doAction() throws Exception; + + public void run() { + log("start"); + while (!terminated) { + try { + synchronized(this) { + wait(waitTime); + } + if (!terminated) { + doAction(); + } + } catch(Exception e) { + log("exception: "+e); + } + } + log("exit"); + } + + public synchronized void terminate() { + log("terminate"); + terminated = true; + notifyAll(); + } + + protected void log(String s) { + //out(" "+Thread.currentThread().getId()+" "+getName()+": "+s); + out(" "+getName()+": "+s); + } + } +} diff --git a/test/javax/sound/sampled/Clip/Drain/ClipDrain.java b/test/javax/sound/sampled/Clip/Drain/ClipDrain.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/Drain/ClipDrain.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4732218 + * @summary Clip.drain does not actually block until all I/O is complete as + * documented. + */ +public class ClipDrain { + static int successfulTests = 0; + static AudioFormat format = new AudioFormat(8000, 16, 1, true, false); + // create a 10-second file + static byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * 10)]; + + static int TOLERANCE_MS = 2500; // how many milliseconds too short is tolerated... + + private static void doMixerClip(Mixer mixer) throws Exception { + boolean waitedEnough=false; + try { + DataLine.Info info = new DataLine.Info(Clip.class, format); + Clip clip = (Clip) mixer.getLine(info); + clip.open(format, soundData, 0, soundData.length); + + // sanity + if (clip.getMicrosecondLength()/1000 < 9900) { + throw new Exception("clip's microsecond length should be at least 9900000, but it is "+clip.getMicrosecondLength()); + } + long start = System.currentTimeMillis(); + + System.out.println(" ---------- start --------"); + clip.start(); + // give time to actually start it. ALSA implementation needs that... + Thread.sleep(300); + System.out.println("drain ... "); + clip.drain(); + long elapsedTime = System.currentTimeMillis() - start; + System.out.println("close ... "); + clip.close(); + System.out.println("... done"); + System.out.println("Playback duration: "+elapsedTime+" milliseconds."); + waitedEnough = elapsedTime >= ((clip.getMicrosecondLength() / 1000) - TOLERANCE_MS); + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - "+t.toString()); + return; + } + if (!waitedEnough) { + throw new Exception("Drain did not wait long enough to play entire clip."); + } + successfulTests++; + } + + + private static void doAll() throws Exception { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + for (int i=0; i 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } +} diff --git a/test/javax/sound/sampled/Clip/Duration/ClipDuration.java b/test/javax/sound/sampled/Clip/Duration/ClipDuration.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/Duration/ClipDuration.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001, 2016, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4237703 + * @summary Check that Clip.getMicrosecondLength() returns correct value. + */ +public class ClipDuration { + + public static int run(Mixer m) { + int res=1; // failed + int frameCount = 441000; // lets say 10 seconds + AudioFormat f = new AudioFormat(44100.0f, 16, 2, true, false); + AudioInputStream audioInputStream = + new AudioInputStream(new ByteArrayInputStream(new byte[frameCount * f.getFrameSize()]), + f, frameCount); + AudioFormat format = audioInputStream.getFormat(); + Clip m_clip = null; + try { + if (m == null) { + m_clip = (Clip) AudioSystem.getClip(); + } else { + DataLine.Info info = new DataLine.Info(Clip.class, format, AudioSystem.NOT_SPECIFIED); + m_clip = (Clip) m.getLine(info); + } + System.out.println("Got clip: "+m_clip); + m_clip.open(audioInputStream); + long microseconds=m_clip.getMicrosecondLength(); + System.out.println("getFrameLength()="+m_clip.getFrameLength()+" frames"); + System.out.println("getMicrosecondLength()="+microseconds+" us"); + if (Math.abs(microseconds-10000000)<50) { + System.out.println("->Clip OK"); + res=0; // passes if less than 50us error + } + } catch (LineUnavailableException luae) { + System.err.println(luae); + res = 3; // line not available, test not failed + } catch (Throwable t) { + System.out.println("->Exception:"+t); + t.printStackTrace(); + res=2; // exception + } + if (m_clip != null) { + m_clip.close(); + } + return res; + } + + + + public static void main(String[] args) throws Exception { + if (isSoundcardInstalled()) { + int res=3; + res = run(null); + Mixer.Info[] infos = AudioSystem.getMixerInfo(); + for (int i = 0; i 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } +} diff --git a/test/javax/sound/sampled/Clip/Endpoint/ClipSetEndPoint.java b/test/javax/sound/sampled/Clip/Endpoint/ClipSetEndPoint.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/Endpoint/ClipSetEndPoint.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2005, 2016, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4385928 + * @summary Verify that an endpoint -1 in Clip does not throw an exception + */ +//public class test048 extends TRTest +public class ClipSetEndPoint { + + private Clip theClip; + + boolean testPassed = true; + + //_______________________________________________ + // Method: runTest + //_______________________________________________ + public boolean runTest() { + AudioInputStream theAudioInputStream = new AudioInputStream( + new ByteArrayInputStream(new byte[2000]), + new AudioFormat(8000.0f, 8, 1, false, false), 2000); // + + AudioFormat theAudioFormat = theAudioInputStream.getFormat(); + + DataLine.Info info = new DataLine.Info(Clip.class, theAudioFormat, + AudioSystem.NOT_SPECIFIED); + try { + theClip = (Clip) AudioSystem.getLine(info); + theClip.open(theAudioInputStream); + + int theStartLoopPoint = 0; + int theEndLoopPoint = -1; // -1 signifies the last frame + + theClip.setLoopPoints(theStartLoopPoint, theEndLoopPoint); + //theClip.start(); + } catch (LineUnavailableException e) { + e.printStackTrace(); + testPassed = true; + } catch (Exception e) { + e.printStackTrace(); + testPassed = false; + } + return testPassed; + } + + //_______________________________________________ + // Method: main + //_______________________________________________ + public static void main(String[] args) throws Exception { + if (isSoundcardInstalled()) { + ClipSetEndPoint thisTest = new ClipSetEndPoint(); + boolean testResult = thisTest.runTest(); + if (testResult) { + System.out.println("Test passed"); + } else { + System.out.println("Test failed"); + throw new Exception("Test failed"); + } + } + } + + /** + * Returns true if at least one soundcard is correctly installed + * on the system. + */ + public static boolean isSoundcardInstalled() { + boolean result = false; + try { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + if (mixers.length > 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: " + e); + } + if (!result) { + System.err.println( + "Soundcard does not exist or sound drivers not installed!"); + System.err.println( + "This test requires sound drivers for execution."); + } + return result; + } +} diff --git a/test/javax/sound/sampled/Clip/IsRunningHang.java b/test/javax/sound/sampled/Clip/IsRunningHang.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/IsRunningHang.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016, 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. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineUnavailableException; + +/** + * @test + * @bug 8156169 + * @run main/othervm/timeout=300 IsRunningHang + */ +public final class IsRunningHang { + + private static CountDownLatch go; + + /** + * We will try to use all usually supported formats. + */ + private static final List formats = new ArrayList<>(); + + private static final AudioFormat.Encoding[] encodings = { + AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW, + AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED, + AudioFormat.Encoding.PCM_FLOAT + }; + + private static final int[] sampleRates = {8000, 16000, 48000}; + + private static final int[] sampleBits = {8, 16, 24, 32, 64}; + + private static final int[] channels = {1, 2, 3, 5}; + + static { + for (final Boolean end : new boolean[]{false, true}) { + for (final int sampleSize : sampleBits) { + for (final int sampleRate : sampleRates) { + for (final int channel : channels) { + for (final AudioFormat.Encoding enc : encodings) { + int s = ((sampleSize + 7) / 8) * channel; + formats.add(new AudioFormat(enc, sampleRate, + sampleSize, channel, + s, sampleRate, end)); + } + } + } + } + } + } + + public static void main(final String[] args) throws Exception { + for (final AudioFormat format : formats) { + System.out.println("format = " + format); + // create a 0.5-second data + byte[] soundData = new byte[(int) (format.getFrameRate() + * format.getFrameSize() + / 2)]; + try { + test(format, soundData); + } catch (LineUnavailableException | IllegalArgumentException ignored) { + // the test is not applicable + } + } + } + + private static void test(final AudioFormat format, final byte[] data) + throws Exception { + final Line.Info info = new DataLine.Info(Clip.class, format); + final Clip clip = (Clip) AudioSystem.getLine(info); + + go = new CountDownLatch(1); + clip.addLineListener(event -> { + if (event.getType().equals(LineEvent.Type.START)) { + go.countDown(); + } + }); + + clip.open(format, data, 0, data.length); + clip.start(); + go.await(); + while (clip.isRunning()) { + // This loop should not hang + } + while (clip.isActive()) { + // This loop should not hang + } + clip.close(); + } +} diff --git a/test/javax/sound/sampled/Clip/Open/ClipOpenBug.java b/test/javax/sound/sampled/Clip/Open/ClipOpenBug.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/Open/ClipOpenBug.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, 2016, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.FloatControl; + +/** + * @test + * @bug 4479444 + * @summary Verify that the error string of Clip.open() is meaningful + */ +public class ClipOpenBug { + + public static void main(String args[]) throws Exception { + boolean res = true; + try { + AudioInputStream ais = new AudioInputStream( + new ByteArrayInputStream(new byte[2000]), + new AudioFormat(8000.0f, 8, 1, false, false), 2000); // + AudioFormat format = ais.getFormat(); + DataLine.Info info = new DataLine.Info(Clip.class, format, + ((int) ais.getFrameLength() + * format + .getFrameSize())); + Clip clip = (Clip) AudioSystem.getLine(info); + clip.open(); + FloatControl rateControl = (FloatControl) clip.getControl( + FloatControl.Type.SAMPLE_RATE); + int c = 0; + while (c++ < 10) { + clip.stop(); + clip.setFramePosition(0); + clip.start(); + for (float frq = 22000; frq < 44100; frq = frq + 100) { + try { + Thread.currentThread().sleep(20); + } catch (Exception e) { + break; + } + rateControl.setValue(frq); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + res = ex.getMessage().indexOf( + "This method should not have been invoked!") < 0; + } + if (res) { + System.out.println("Test passed"); + } else { + System.out.println("Test failed"); + throw new Exception("Test failed"); + } + } +} diff --git a/test/javax/sound/sampled/Clip/bug5070081.java b/test/javax/sound/sampled/Clip/bug5070081.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/bug5070081.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2005, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; + +/* + * @test + * @bug 5070081 + * @summary Tests that javax.sound.sampled.Clip does not loses position through + * stop/start + * @key headful + */ +public class bug5070081 { + + static AudioFormat format = new AudioFormat(22050, 8, 1, false, false); + // create a 3-second file + static byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * 3)]; + + static final int LOOP_COUNT = 5; + + static boolean test() throws Exception { + DataLine.Info info = new DataLine.Info(Clip.class, format); + Clip clip = (Clip)AudioSystem.getLine(info); + clip.open(format, soundData, 0, soundData.length); + + boolean bSuccess = true; + + long nLengthMS = clip.getMicrosecondLength()/1000; + + System.out.println(" Clip length:"); + System.out.println(" frames: " + clip.getFrameLength()); + System.out.println(" seconds: " + nLengthMS/1000.0); + + clip.start(); // start playing + Thread.sleep(1000); // wait a sec + long time1 = System.currentTimeMillis(); + long pos1 = clip.getFramePosition(); // store the position + System.out.println(" Position before stop: " + pos1); + clip.stop(); // and then stop + long pos2 = clip.getFramePosition(); // 2nd try + long time2 = System.currentTimeMillis(); + System.out.println(" Position after stop: " + pos2); + + System.out.println(" d(time): " + Math.abs(time2-time1) + " ms;" + + "d(clip pos): " + Math.abs(pos2 - pos1) + " ms."); + + long nDerivation = Math.abs(pos2 - pos1) - Math.abs(time2-time1); + // add 50 ms for deviation (delay for stopping and errors due timer precision) + if (nDerivation > 50) { + System.out.println(" ERROR(1): The deviation is too much: " + nDerivation + " ms"); + bSuccess = false; + } + + Thread.sleep(1000); + clip.start(); // start again + Thread.sleep(100); + while(clip.isRunning()); // wait for the sound to finish + + int nEndPos = clip.getFramePosition(); + System.out.println(" Position at end: " + nEndPos); + if (nEndPos > clip.getFrameLength()) { + System.out.println(" ERROR(2): end position if out of range"); + bSuccess = false; + } + + clip.close(); + + return bSuccess; + } + + public static void main(String[] args) throws Exception { + for (int count=1; count <= LOOP_COUNT; count++) + { + System.out.println("loop " + count + "/" + LOOP_COUNT); + if (!test()) + { + System.out.println("Test FAILED"); + throw new RuntimeException("Test FAILED."); + } + } + + System.out.println("Test passed sucessfully"); + } +} diff --git a/test/javax/sound/sampled/Clip/bug6251460.java b/test/javax/sound/sampled/Clip/bug6251460.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Clip/bug6251460.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2005, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; + +/** + * @test + * @bug 6251460 8047222 + * @requires (os.family == "windows" | os.family == "mac") + * @summary Tests that JavaSound plays short sounds (less then 1 second) + */ +public class bug6251460 { + private static final class MutableBoolean { + public boolean value; + + public MutableBoolean(boolean initialValue) { + value = initialValue; + } + } + + // static helper routines + static long startTime = currentTimeMillis(); + static long currentTimeMillis() { + return System.nanoTime() / 1000000L; + } + static void log(String s) { + long time = currentTimeMillis() - startTime; + long ms = time % 1000; + time /= 1000; + long sec = time % 60; + time /= 60; + long min = time % 60; + time /= 60; + System.out.println("" + + (time < 10 ? "0" : "") + time + + ":" + (min < 10 ? "0" : "") + min + + ":" + (sec < 10 ? "0" : "") + sec + + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms + + " " + s); + } + + + static private int countErrors = 0; + static private final int LOOP_COUNT = 30; + + static AudioFormat format = new AudioFormat(8000, 16, 1, true, false); + // create a 250-ms clip + static byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * 0.25)]; + + static protected void test() + throws LineUnavailableException, InterruptedException { + DataLine.Info info = new DataLine.Info(Clip.class, format); + Clip clip = (Clip)AudioSystem.getLine(info); + final MutableBoolean clipStoppedEvent = new MutableBoolean(false); + clip.addLineListener(new LineListener() { + @Override + public void update(LineEvent event) { + if (event.getType() == LineEvent.Type.STOP) { + synchronized (clipStoppedEvent) { + clipStoppedEvent.value = true; + clipStoppedEvent.notifyAll(); + } + } + } + }); + clip.open(format, soundData, 0, soundData.length); + + long lengthClip = clip.getMicrosecondLength() / 1000; + log("Clip length " + lengthClip + " ms"); + log("Playing..."); + for (int i=1; i<=LOOP_COUNT; i++) { + long startTime = currentTimeMillis(); + log(" Loop " + i); + clip.start(); + + synchronized (clipStoppedEvent) { + while (!clipStoppedEvent.value) { + clipStoppedEvent.wait(); + } + clipStoppedEvent.value = false; + } + + long endTime = currentTimeMillis(); + long lengthPlayed = endTime - startTime; + + if (lengthClip > lengthPlayed + 20) { + log(" ERR: Looks like sound didn't play: played " + lengthPlayed + " ms instead " + lengthClip); + countErrors++; + } else { + log(" OK: played " + lengthPlayed + " ms"); + } + clip.setFramePosition(0); + + } + log("Played " + LOOP_COUNT + " times, " + countErrors + " errors detected."); + } + + public static void main(String[] args) throws InterruptedException { + try { + test(); + } catch (LineUnavailableException | IllegalArgumentException + | IllegalStateException ignored) { + System.out.println("Test is not applicable. Automatically passed"); + return; + } + if (countErrors > 0) { + throw new RuntimeException( + "Test FAILED: " + countErrors + " error detected (total " + + LOOP_COUNT + ")"); + } + } +} diff --git a/test/javax/sound/sampled/Controls/CompoundControl/ToString.java b/test/javax/sound/sampled/Controls/CompoundControl/ToString.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Controls/CompoundControl/ToString.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.CompoundControl; +import javax.sound.sampled.Control; + +/** + * @test + * @bug 4629190 + * @summary CompoundControl: getMemberControls() and toString() throw + * NullPointerException + */ +public class ToString { + public static void main(String args[]) throws Exception { + System.out.println(); + System.out.println(); + System.out.println("4629190: CompoundControl: getMemberControls() and toString() throw NullPointerException"); + + String firstControlTypeName = "first_Control_Type_Name"; + String secondControlTypeName = "second_Control_Type_Name"; + String thirdControlTypeName = "third_Control_Type_Name"; + + Control.Type firstControlType = new TestControlType(firstControlTypeName); + Control.Type secondControlType = new TestControlType(secondControlTypeName); + Control.Type thirdControlType = new TestControlType(thirdControlTypeName); + + Control firstControl = new TestControl(firstControlType); + Control secondControl = new TestControl(secondControlType); + Control thirdControl = new TestControl(thirdControlType); + + String testCompoundControlTypeName = "CompoundControl_Type_Name"; + CompoundControl.Type testCompoundControlType + = new TestCompoundControlType(testCompoundControlTypeName); + + Control[] setControls = { firstControl, secondControl, thirdControl }; + CompoundControl testedCompoundControl + = new TestCompoundControl(testCompoundControlType, setControls); + + // this may throw exception if bug applies + Control[] producedControls = testedCompoundControl.getMemberControls(); + System.out.println("Got "+producedControls.length+" member controls."); + + // this may throw exception if bug applies + String producedString = testedCompoundControl.toString(); + System.out.println("toString() returned: "+producedString); + + System.out.println("Test passed."); + } + +} + +class TestControl extends Control { + + TestControl(Control.Type type) { + super(type); + } +} + +class TestControlType extends Control.Type { + + TestControlType(String name) { + super(name); + } +} + +class TestCompoundControl extends CompoundControl { + + TestCompoundControl(CompoundControl.Type type, Control[] memberControls) { + super(type, memberControls); + } +} + +class TestCompoundControlType extends CompoundControl.Type { + + TestCompoundControlType(String name) { + super(name); + } +} diff --git a/test/javax/sound/sampled/Controls/FloatControl/FloatControlBug.java b/test/javax/sound/sampled/Controls/FloatControl/FloatControlBug.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Controls/FloatControl/FloatControlBug.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 2016, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.FloatControl; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4385654 + * @summary Check that the MASTER_GAIN control has a valid precision + */ +//public class test047 extends TRTest +public class FloatControlBug { + + private Clip theClip; + + boolean testPassed = true; + + private AudioFormat.Encoding theEncoding = AudioFormat.Encoding.PCM_SIGNED; + + private float theSampleRate = 44100; + + private int theSampleSize = 16; + + private int theNumberOfChannels = 1; + + private int theFrameSize = 2; + + private float theFrameRate = 44100; + + private boolean isBigEndian = false; + + //_______________________________________________ + // Method: runTest + //_______________________________________________ + public boolean runTest() { + AudioInputStream theAudioInputStream = new AudioInputStream( + new ByteArrayInputStream(new byte[0]), + new AudioFormat(44100.0f, 16, 2, true, false), 441000); + + AudioFormat theAudioFormat = theAudioInputStream.getFormat(); + + DataLine.Info info = new DataLine.Info(Clip.class, theAudioFormat, + AudioSystem.NOT_SPECIFIED); + try { + theClip = (Clip) AudioSystem.getLine(info); + theClip.open(theAudioInputStream); + FloatControl theFloatControl = (FloatControl) (theClip.getControl( + FloatControl.Type.MASTER_GAIN)); + float theFloatControlPrecision = theFloatControl.getPrecision(); + System.out.println( + "theFloatControlPrecision: " + theFloatControlPrecision); + System.out.println("Minimum: " + theFloatControl.getMinimum()); + System.out.println("Maximum: " + theFloatControl.getMaximum()); + System.out.println("Value : " + theFloatControl.getValue()); + testPassed = theFloatControlPrecision > 0; + } catch (LineUnavailableException e) { + e.printStackTrace(); + testPassed = true; + } catch (Exception e) { + e.printStackTrace(); + testPassed = false; + } + return testPassed; + } + + //_______________________________________________ + // Method: main + //_______________________________________________ + public static void main(String[] args) throws Exception { + //test047 thisTest = new test047(); + if (isSoundcardInstalled()) { + FloatControlBug thisTest = new FloatControlBug(); + boolean testResult = thisTest.runTest(); + if (testResult) { + System.out.println("Test passed"); + } else { + System.out.println("Test failed"); + throw new Exception("Test failed"); + } + } + } + + /** + * Returns true if at least one soundcard is correctly installed + * on the system. + */ + public static boolean isSoundcardInstalled() { + boolean result = false; + try { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + if (mixers.length > 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: " + e); + } + if (!result) { + System.err.println( + "Soundcard does not exist or sound drivers not installed!"); + System.err.println( + "This test requires sound drivers for execution."); + } + return result; + } +} diff --git a/test/javax/sound/sampled/DataLine/DataLineInfoNegBufferSize.java b/test/javax/sound/sampled/DataLine/DataLineInfoNegBufferSize.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/DataLine/DataLineInfoNegBufferSize.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 5021234 + * @summary Using -2 for buffer size will fail retrieval of lines + */ +public class DataLineInfoNegBufferSize { + + /** + * returns: + * 0: OK + * 1: IAE + * 2: other exception + * 3: line not available + */ + public static int run(Mixer m, int bufferSize) { + int res; + int frameCount = 441000; // lets say 10 seconds + AudioFormat f = new AudioFormat(44100.0f, 16, 2, true, false); + Clip clip = null; + try { + System.out.println("Requesting clip from Mixer " + +(m==null?"default":m.toString()) + +" with bufferSize"+bufferSize); + DataLine.Info info = new DataLine.Info(Clip.class, f, bufferSize); + if (m==null) { + clip = (Clip) AudioSystem.getLine(info); + } else { + clip = (Clip) m.getLine(info); + } + System.out.println("Got clip: "+clip+" with Buffer size "+clip.getBufferSize()); + + res = 0; + } catch (LineUnavailableException luae) { + System.out.println(luae); + res = 3; // line not available + } catch (IllegalArgumentException iae) { + System.out.println(iae); + res = 1; + } catch (Throwable t) { + System.out.println("->Exception:"+t); + t.printStackTrace(); + res=2; // other exception + } + return res; + } + + public static void main(String[] args) throws Exception { + if (isSoundcardInstalled()) { + int res=0; + int count = 0; + Mixer.Info[] infos = AudioSystem.getMixerInfo(); + for (int i = -1; i 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } +} diff --git a/test/javax/sound/sampled/DataLine/LineDefFormat.java b/test/javax/sound/sampled/DataLine/LineDefFormat.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/DataLine/LineDefFormat.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.TargetDataLine; + +/** + * @test + * @bug 5053380 + * @summary Verify that getting a line initializes it with the format in + * DataLine.Info + */ +public class LineDefFormat { + + final static int samplerate = 22050; + static int passed = 0; + static int failed = 0; + + private static void doLine1(DataLine line, AudioFormat format) { + try { + System.out.println(" - got line: "+line); + System.out.println(" - line has format: "+line.getFormat()); + if (!line.getFormat().matches(format)) { + System.out.println(" ## Error: expected this format: "+format); + failed++; + } else { + passed++; + } + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - "+t.toString()); + } + } + + private static void doLine2(DataLine line, AudioFormat format) { + try { + System.out.println(" - call to open()"); + line.open(); + try { + System.out.println(" - line has format: "+line.getFormat()); + if (!line.getFormat().matches(format)) { + System.out.println("## Error: expected this format: "+format); + failed++; + } else { + passed++; + } + } finally { + line.close(); + System.out.println(" - closed"); + } + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - "+t.toString()); + } + } + + private static void doMixerClip(Mixer mixer, AudioFormat format) { + if (mixer==null) return; + try { + System.out.println("Clip from mixer "+mixer+":"); + System.out.println(" "+mixer.getMixerInfo()); + DataLine.Info info = new DataLine.Info( + Clip.class, + format); + + if (mixer.isLineSupported(info)) { + Clip clip = (Clip) mixer.getLine(info); + doLine1(clip, format); + } else { + System.out.println(" - Line not supported"); + } + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - "+t.toString()); + } + } + + private static void doMixerSDL(Mixer mixer, AudioFormat format) { + if (mixer==null) return; + try { + System.out.println("SDL from mixer "+mixer+":"); + DataLine.Info info = new DataLine.Info( + SourceDataLine.class, + format); + + if (mixer.isLineSupported(info)) { + SourceDataLine sdl = (SourceDataLine) mixer.getLine(info); + doLine1(sdl, format); + doLine2(sdl, format); + } else { + System.out.println(" - Line not supported"); + } + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - "+t.toString()); + } + } + + private static void doMixerTDL(Mixer mixer, AudioFormat format) { + if (mixer==null) return; + try { + System.out.println("TDL from mixer "+mixer+":"); + DataLine.Info info = new DataLine.Info( + TargetDataLine.class, + format); + if (mixer.isLineSupported(info)) { + TargetDataLine tdl = (TargetDataLine) mixer.getLine(info); + doLine1(tdl, format); + doLine2(tdl, format); + } else { + System.out.println(" - Line not supported"); + } + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - "+t.toString()); + } + } + + private static void doAll() throws Exception { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + AudioFormat pcm; + for (int i=0; i 100) { + failed = true; + System.out.println("## FAILED: frame positions are not the same!"); + } + } finally { + sdl.close(); + } + } catch(LineUnavailableException e){ + System.out.println(e); + System.out.println("Cannot execute test."); + return; + } + if (failed) throw new Exception("Test FAILED!"); + System.out.println("Test Passed."); + } +} diff --git a/test/javax/sound/sampled/DirectAudio/TickAtEndOfPlay.java b/test/javax/sound/sampled/DirectAudio/TickAtEndOfPlay.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/DirectAudio/TickAtEndOfPlay.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.SourceDataLine; + +/** + * @test + * @bug 5001959 + * @summary Short tick sound after finished playing with SourceDataLine + * @run main/manual TickAtEndOfPlay + */ +public class TickAtEndOfPlay { + + static boolean WorkAround1 = false; + static boolean WorkAround2 = false; + + public static void main(String[] args) throws Exception { + System.out.println("This test should only be run on Windows."); + System.out.println("Make sure that the speakers are connected and the volume is up."); + System.out.println("Close all other programs that may use the soundcard."); + + System.out.println("You'll hear a 2-second tone. when the tone finishes,"); + System.out.println(" there should be no noise. If you hear a short tick/noise,"); + System.out.println(" the bug still applies."); + + System.out.println("Press ENTER to continue."); + System.in.read(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("1")) WorkAround1 = true; + if (args[i].equals("2")) WorkAround2 = true; + } + if (WorkAround1) System.out.println("Using work around1: appending silence"); + if (WorkAround2) System.out.println("Using work around2: waiting before close"); + + int zerolen = 0; // how many 0-bytes will be appended to playback + if (WorkAround1) zerolen = 1000; + int seconds = 2; + int sampleRate = 8000; + double frequency = 1000.0; + double RAD = 2.0 * Math.PI; + AudioFormat af = new AudioFormat((float)sampleRate,8,1,true,true); + System.out.println("Format: "+af); + DataLine.Info info = new DataLine.Info(SourceDataLine.class,af); + SourceDataLine source = (SourceDataLine)AudioSystem.getLine(info); + System.out.println("Line: "+source); + if (source.toString().indexOf("MixerSourceLine")>=0) { + System.out.println("This test only applies to non-Java Sound Audio Engine!"); + return; + } + System.out.println("Opening..."); + source.open(af); + System.out.println("Starting..."); + source.start(); + int datalen = sampleRate * seconds; + byte[] buf = new byte[datalen+zerolen]; + for (int i=0; i 0 && !stopRequested) { + int avail = line.available(); + if (avail > 0) { + if (avail > remaining) + avail = remaining; + int written = line.write(data, data.length - remaining, avail); + remaining -= written; + log("WriteThread: " + written + " bytes written"); + } else { + delay(100); + } + } + if (remaining == 0) { + log("WriteThread: all data has been written, draining"); + line.drain(); + } else { + log("WriteThread: stop requested"); + } + log("WriteThread: stopping"); + line.stop(); + log("WriteThread: exiting"); + } + + public boolean isCompleted() { + return (remaining <= 0); + } + + public void requestStop() { + stopRequested = true; + } + } + + void testPlayback() throws LineUnavailableException { + // prepare audio data + AudioFormat format = new AudioFormat(22050, 8, 1, false, false); + byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)]; + + // create & open source data line + //SourceDataLine line = AudioSystem.getSourceDataLine(format); + DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); + SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info); + + line.open(format); + + // start write data thread + WriteThread p1 = new WriteThread(line, soundData); + p1.start(); + + // start line + PlayThread p2 = new PlayThread(line); + p2.start(); + + // monitor line + long lineTime1 = line.getMicrosecondPosition() / 1000; + long realTime1 = currentTimeMillis(); + while (true) { + delay(500); + if (!line.isActive()) { + log("audio data played completely"); + break; + } + long lineTime2 = line.getMicrosecondPosition() / 1000; + long realTime2 = currentTimeMillis(); + long dLineTime = lineTime2 - lineTime1; + long dRealTime = realTime2 - realTime1; + log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED")); + if (dLineTime < 0) { + throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2); + } + if (dRealTime < 450) { + // delay() has been interrupted? + continue; + } + lineTime1 = lineTime2; + realTime1 = realTime2; + } + } + + + // recording test classes/routines + + class RecordThread extends Thread { + TargetDataLine line; + public RecordThread(TargetDataLine line) { + this.line = line; + this.setDaemon(true); + } + + public void run() { + log("RecordThread: starting..."); + line.start(); + log("RecordThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms..."); + delay(PLAYTHREAD_DELAY * 1000); + log("RecordThread: exiting..."); + } + } + + class ReadThread extends Thread { + TargetDataLine line; + byte[] data; + volatile int remaining; + public ReadThread(TargetDataLine line, byte[] data) { + this.line = line; + this.data = data; + remaining = data.length; + this.setDaemon(true); + } + + public void run() { + log("ReadThread: buffer size is " + data.length + " bytes"); + delay(200); + while ((remaining > 0) && line.isOpen()) { + int avail = line.available(); + if (avail > 0) { + if (avail > remaining) + avail = remaining; + int read = line.read(data, data.length - remaining, avail); + remaining -= read; + log("ReadThread: " + read + " bytes read"); + } else { + delay(100); + } + if (remaining <= 0) { + log("ReadThread: record buffer is full, exiting"); + break; + } + } + if (remaining > 0) { + log("ReadThread: line has been stopped, exiting"); + } + } + + public int getCount() { + return data.length - remaining; + } + public boolean isCompleted() { + return (remaining <= 0); + } + } + + void testRecord() throws LineUnavailableException { + // prepare audio data + AudioFormat format = new AudioFormat(22050, 8, 1, false, false); + + // create & open target data line + //TargetDataLine line = AudioSystem.getTargetDataLine(format); + DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); + TargetDataLine line = (TargetDataLine)AudioSystem.getLine(info); + + line.open(format); + + // start read data thread + byte[] data = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)]; + ReadThread p1 = new ReadThread(line, data); + p1.start(); + + // start line + //new RecordThread(line).start(); + RecordThread p2 = new RecordThread(line); + p2.start(); + + // monitor line + long endTime = currentTimeMillis() + DATA_LENGTH * 1000; + + long realTime1 = currentTimeMillis(); + long lineTime1 = line.getMicrosecondPosition() / 1000; + + while (realTime1 < endTime && !p1.isCompleted()) { + delay(100); + long lineTime2 = line.getMicrosecondPosition() / 1000; + long realTime2 = currentTimeMillis(); + long dLineTime = lineTime2 - lineTime1; + long dRealTime = realTime2 - realTime1; + log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED")); + if (dLineTime < 0) { + line.stop(); + line.close(); + throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2); + } + if (dRealTime < 450) { + // delay() has been interrupted? + continue; + } + lineTime1 = lineTime2; + realTime1 = realTime2; + } + log("stopping line..."); + line.stop(); + line.close(); + + /* + log(""); + log(""); + log(""); + log("recording completed, delaying 5 sec"); + log("recorded " + p1.getCount() + " bytes, " + DATA_LENGTH + " seconds: " + (p1.getCount() * 8 / DATA_LENGTH) + " bit/sec"); + log(""); + log(""); + log(""); + delay(5000); + log("starting playing..."); + playRecorded(format, data); + */ + } + + void playRecorded(AudioFormat format, byte[] data) throws Exception { + //SourceDataLine line = AudioSystem.getSourceDataLine(format); + DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); + SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info); + + line.open(); + line.start(); + + int remaining = data.length; + while (remaining > 0) { + int avail = line.available(); + if (avail > 0) { + if (avail > remaining) + avail = remaining; + int written = line.write(data, data.length - remaining, avail); + remaining -= written; + log("Playing: " + written + " bytes written"); + } else { + delay(100); + } + } + + line.drain(); + line.stop(); + } + + // helper routines + static long startTime = currentTimeMillis(); + static long currentTimeMillis() { + //return System.nanoTime() / 1000000L; + return System.currentTimeMillis(); + } + static void log(String s) { + long time = currentTimeMillis() - startTime; + long ms = time % 1000; + time /= 1000; + long sec = time % 60; + time /= 60; + long min = time % 60; + time /= 60; + System.out.println("" + + (time < 10 ? "0" : "") + time + + ":" + (min < 10 ? "0" : "") + min + + ":" + (sec < 10 ? "0" : "") + sec + + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms + + " (" + Thread.currentThread().getName() + ") " + s); + } + static void delay(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) {} + } +} diff --git a/test/javax/sound/sampled/FileTypeExtension/FileTypeExtensionTest.java b/test/javax/sound/sampled/FileTypeExtension/FileTypeExtensionTest.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/FileTypeExtension/FileTypeExtensionTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2000, 2016, 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. + */ + +import javax.sound.sampled.AudioFileFormat; + +/** + * @test + * @bug 4300529 + * @summary Filename extension test. The filename extensions for file types + * AIFF-C, SND, and WAVE should not include a ".". + */ +public class FileTypeExtensionTest { + + public static void main(String[] args) throws Exception { + + AudioFileFormat.Type[] types = { AudioFileFormat.Type.AIFC, + AudioFileFormat.Type.AIFF, + AudioFileFormat.Type.AU, + AudioFileFormat.Type.SND, + AudioFileFormat.Type.WAVE }; + + boolean failed = false; + + System.out.println("\nDefined file types and extensions:"); + + for (int i = 0; i < types.length; i++) { + System.out.println("\n"); + System.out.println(" file type: " + types[i]); + System.out.println(" extension: " + types[i].getExtension()); + if( types[i].getExtension().charAt(0) == '.' ) { + failed = true; + } + } + + if (failed) { + System.err.println("Failed!"); + throw new Exception("File type extensions begin with ."); + } else { + System.err.println("Passed!"); + } + } +} diff --git a/test/javax/sound/sampled/LineEvent/LineInfoNPE.java b/test/javax/sound/sampled/LineEvent/LineInfoNPE.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/LineEvent/LineInfoNPE.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.Control; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineListener; + +/** + * @test + * @bug 4672865 + * @summary LineEvent.toString() throws unexpected NullPointerException + */ +public class LineInfoNPE { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + public static void main(String argv[]) throws Exception { + int testExitStatus = run(argv, System.out); + if (testExitStatus != STATUS_PASSED) { + throw new Exception("test FAILED!"); + } + } + + public static int run(String argv[], java.io.PrintStream out) { + int testResult = STATUS_PASSED; + + out.println("\n==> Test for LineEvent class:"); + + Line testLine = new TestLine(); + Line nullLine = null; + + LineEvent.Type testLineEventType = LineEvent.Type.OPEN; + LineEvent.Type nullLineEventType = null; + + LineEvent testedLineEvent = null; + out.println("\n>> LineEvent constructor for Line = null: "); + try { + testedLineEvent = + new LineEvent(nullLine, // the source Line of this event + testLineEventType, // LineEvent.Type - the event type + (long) 1000 // position - the number processed of sample frames + ); + out.println("> No any Exception was thrown!"); + out.println("> testedLineEvent.getType():"); + try { + Line producedLine = testedLineEvent.getLine(); + out.println("> PASSED: producedLine = " + producedLine); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + out.println("> testedLineEvent.toString():"); + try { + String producedString = testedLineEvent.toString(); + out.println("> PASSED: producedString = " + producedString); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + } catch (IllegalArgumentException illegArgExcept) { + out.println("> PASSED: expected IllegalArgumentException was thrown:"); + illegArgExcept.printStackTrace(out); + } catch (NullPointerException nullPE) { + out.println("> PASSED: expected NullPointerException was thrown:"); + nullPE.printStackTrace(out); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + out.println("\n>> LineEvent constructor for LineEvent.Type = null: "); + try { + testedLineEvent = + new LineEvent(testLine, // the source Line of this event + nullLineEventType, // LineEvent.Type - the event type + (long) 1000 // position - the number processed of sample frames + ); + out.println("> No any Exception was thrown!"); + out.println("> testedLineEvent.getType():"); + try { + LineEvent.Type producedType = testedLineEvent.getType(); + out.println("> PASSED: producedType = " + producedType); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + out.println("> testedLineEvent.toString():"); + try { + String producedString = testedLineEvent.toString(); + out.println("> PASSED: producedString = " + producedString); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + } catch (IllegalArgumentException illegArgExcept) { + out.println("> PASSED: expected IllegalArgumentException was thrown:"); + illegArgExcept.printStackTrace(out); + } catch (NullPointerException nullPE) { + out.println("> PASSED: expected NullPointerException was thrown:"); + nullPE.printStackTrace(out); + } catch (Throwable thrown) { + out.println("## FAILED: unexpected Exception was thrown:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + if ( testResult == STATUS_FAILED ) { + out.println("\n==> test FAILED!"); + } else { + out.println("\n==> test PASSED!"); + } + return testResult; + } +} // end of test class + +class TestLine implements Line { + + public void addLineListener(LineListener listener) { + } + + public void close() { + } + + public Control getControl(Control.Type control) { + return null; + } + + public Control[] getControls() { + return new Control[0]; + } + + public Line.Info getLineInfo() { + return null; + } + + public boolean isOpen() { + return false; + } + + public boolean isControlSupported(Control.Type control) { + return false; + } + + public void open() { + } + + public void removeLineListener(LineListener listener) { + } +} diff --git a/test/javax/sound/sampled/Lines/16and32KHz/Has16and32KHz.java b/test/javax/sound/sampled/Lines/16and32KHz/Has16and32KHz.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Lines/16and32KHz/Has16and32KHz.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.TargetDataLine; + +/** + * @test + * @bug 4479441 + * @summary Verify that the lines report 16KHz and 32KHz capability + */ +public class Has16and32KHz { + + public static boolean ok32=false; + public static boolean ok16=false; + + public static void showMixerLines(Line.Info[] lineinfo) { + for (int j = 0; j < lineinfo.length; j++) { + boolean isSDL=false; // SourceDataLine + Line.Info thisInfo=lineinfo[j]; + System.out.println(" " + thisInfo); + String impl=""; + if (thisInfo.getLineClass().equals(SourceDataLine.class)) { + isSDL=true; + impl+="SourceDataLine"; + } + if (thisInfo.getLineClass().equals(Clip.class)) { + impl+="Clip"; + } + if (thisInfo.getLineClass().equals(DataLine.class)) { + impl+="DataLine"; + } + if (thisInfo.getLineClass().equals(TargetDataLine.class)) { + impl+="TargetDataLine"; + } + if (thisInfo.getLineClass().equals(Mixer.class)) { + impl+="Mixer"; + } + System.out.println(" implements "+impl); + try { + AudioFormat[] formats = ((DataLine.Info)lineinfo[j]).getFormats(); + for (int k = 0; k < formats.length; k++) { + System.out.println(" " + formats[k] + ", "+ formats[k].getFrameSize()+" bytes/frame"); + if (isSDL) { + if ((formats[k].getSampleRate()==AudioSystem.NOT_SPECIFIED) + || (formats[k].getSampleRate()==32000.0f)) { + ok32=true; + } + if ((formats[k].getSampleRate()==AudioSystem.NOT_SPECIFIED) + || (formats[k].getSampleRate()==16000.0f)) { + ok16=true; + } + } + } + } catch (ClassCastException e) { + } + } + } + + public static void main(String[] args) throws Exception { + boolean res=true; + + Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); + System.out.println(mixerInfo.length+" mixers on system."); + if (mixerInfo.length == 0) { + System.out.println("Cannot execute test. Not Failed!"); + } else { + for (int i = 0; i < mixerInfo.length; i++) { + Mixer mixer = AudioSystem.getMixer(mixerInfo[i]); + System.out.println(); + System.out.println(mixer+":"); + showMixerLines(mixer.getSourceLineInfo()); + showMixerLines(mixer.getTargetLineInfo()); + + + } + res=ok16 && ok32; + } + if (res) { + System.out.println("Test passed"); + } else { + System.out.println("Test failed"); + throw new Exception("Test failed"); + } + //ystem.exit(res?0:1); + } +} diff --git a/test/javax/sound/sampled/Lines/BufferSizeCheck.java b/test/javax/sound/sampled/Lines/BufferSizeCheck.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Lines/BufferSizeCheck.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +/** + * @test + * @bug 4661602 + * @summary Buffersize is checked when re-opening line + */ +public class BufferSizeCheck { + + public static void main(String[] args) throws Exception { + boolean realTest = false; + if (!isSoundcardInstalled()) { + return; + } + + try { + out("4661602: Buffersize is checked when re-opening line"); + AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); + SourceDataLine sdl = (SourceDataLine) AudioSystem.getLine(info); + out("Opening with buffersize 12000..."); + sdl.open(format, 12000); + out("Opening with buffersize 11000..."); + realTest=true; + sdl.open(format, 11000); + try { + sdl.close(); + } catch(Throwable t) {} + } catch (Exception e) { + e.printStackTrace(); + // do not fail if no audio device installed - bug 4742021 + if (realTest || !(e instanceof LineUnavailableException)) { + throw e; + } + } + out("Test passed"); + } + + static void out(String s) { + System.out.println(s); System.out.flush(); + } + + /** + * Returns true if at least one soundcard is correctly installed + * on the system. + */ + public static boolean isSoundcardInstalled() { + boolean result = false; + try { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + if (mixers.length > 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } +} diff --git a/test/javax/sound/sampled/Lines/ChangingBuffer.java b/test/javax/sound/sampled/Lines/ChangingBuffer.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Lines/ChangingBuffer.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +/** + * @test + * @bug 4515126 + * @summary Verify that the buffer passed to SourceDataLine.write() and + * Clip.open() will not be changed + */ +public class ChangingBuffer { + + final static int samplerate = 44100; + final static byte[] buffer = new byte[16384]; + static int successfulTests = 0; + + private static void makeBuffer() { + for (int i=0; i passed for this line"); + System.out.println(""); + } + + private static void checkBufferClip() throws Exception { + for (int i=0; i passed for this clip"); + System.out.println(""); + } + + private static boolean doMixerClip(Mixer mixer, AudioFormat format) { + if (mixer==null) return false; + try { + System.out.println("Trying mixer "+mixer+":"); + DataLine.Info info = new DataLine.Info( + Clip.class, + format, + (int) samplerate); + + Clip clip = (Clip) mixer.getLine(info); + System.out.println(" - got clip: "+clip); + System.out.println(" - open with format "+format); + clip.open(format, buffer, 0, buffer.length); + System.out.println(" - playing..."); + clip.start(); + System.out.println(" - waiting while it's active..."); + while (clip.isActive()) + Thread.sleep(100); + System.out.println(" - waiting 100millis"); + Thread.sleep(100); + System.out.println(" - drain1"); + clip.drain(); + System.out.println(" - drain2"); + clip.drain(); + System.out.println(" - stop"); + clip.stop(); + System.out.println(" - close"); + clip.close(); + System.out.println(" - closed"); + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - "+t.toString()); + return false; + } + return true; + } + + private static boolean doMixerSDL(Mixer mixer, AudioFormat format) { + if (mixer==null) return false; + try { + System.out.println("Trying mixer "+mixer+":"); + DataLine.Info info = new DataLine.Info( + SourceDataLine.class, + format, + (int) samplerate); + + SourceDataLine sdl = (SourceDataLine) mixer.getLine(info); + System.out.println(" - got sdl: "+sdl); + System.out.println(" - open with format "+format); + sdl.open(format); + System.out.println(" - start..."); + sdl.start(); + System.out.println(" - write..."); + sdl.write(buffer, 0, buffer.length); + Thread.sleep(200); + System.out.println(" - drain..."); + sdl.drain(); + System.out.println(" - stop..."); + sdl.stop(); + System.out.println(" - close..."); + sdl.close(); + System.out.println(" - closed"); + } catch (Throwable t) { + System.out.println(" - Caught exception. Not failed."); + System.out.println(" - "+t.toString()); + return false; + } + return true; + } + + private static void doAll(boolean bigEndian) throws Exception { + AudioFormat pcm = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, + samplerate, 16, 1, 2, samplerate, bigEndian); + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + for (int i=0; i 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //DialogOrient + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + Test4218609.pass(); + } + else + { + Test4218609.fail(); + } + } + + }// TestDialog class diff --git a/test/javax/sound/sampled/Lines/ClipOpenException.java b/test/javax/sound/sampled/Lines/ClipOpenException.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Lines/ClipOpenException.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.TargetDataLine; + +/** + * @test + * @bug 4679187 + * @summary Clip.open() throws unexpected Exceptions. verifies that clip, + * sourcedataline and targetdataline throw IllegalArgumentExcepotion if + * any field in the format is AudioFormat.NOT_SPECIFIED + */ +public class ClipOpenException { + static boolean failed = false; + + static byte[] audioData = new byte[2048]; + static AudioFormat[] formats = { + new AudioFormat(AudioSystem.NOT_SPECIFIED, + AudioSystem.NOT_SPECIFIED, + AudioSystem.NOT_SPECIFIED, + true, false), + new AudioFormat(0, 0, 0, true, false) + }; + static AudioFormat infoFormat = new AudioFormat(44100.0f, + 16, + 1, + true, false); + static DataLine.Info clipInfo = new DataLine.Info(Clip.class, infoFormat); + static DataLine.Info sdlInfo = new DataLine.Info(SourceDataLine.class, infoFormat); + static DataLine.Info tdlInfo = new DataLine.Info(TargetDataLine.class, infoFormat); + + + public static void print(String s) { + System.out.print(s); + } + public static void println(String s) { + System.out.println(s); + } + + public static void test(Line line) { + for (int format = 0; format < formats.length; format++) { + try { + println(" Opening the line with format "+(format+1)); + if (line instanceof Clip) { + ((Clip) line).open(formats[format], audioData, 0, audioData.length); + } else + if (line instanceof SourceDataLine) { + ((SourceDataLine) line).open(formats[format]); + } else + if (line instanceof TargetDataLine) { + ((TargetDataLine) line).open(formats[format]); + } else { + println(" Unknown type of line: "+line.getClass()); + return; + } + println(" No exception! not OK."); + failed = true; + } catch (IllegalArgumentException iae) { + println(" IllegalArgumentException: "+iae.getMessage()); + println(" OK"); + } catch (LineUnavailableException lue) { + println(" LineUnavailableException: "+lue.getMessage()); + println(" Probably incorrect, but may happen if the test system is correctly set up."); + } catch (Exception e) { + println(" Unexpected Exception: "+e.toString()); + println(" NOT OK!"); + failed = true; + } + println(" Closing line."); + line.close(); + } + } + + public static void main(String[] args) throws Exception { + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + int succMixers = 0; + println("Using formats: "); + for (int i = 0 ; i Test for SourceDataLine.write() method for not open and not started line:"); + + Mixer.Info[] installedMixersInfo = AudioSystem.getMixerInfo(); + + if ( installedMixersInfo == null ) { + out.println("## AudioSystem.getMixerInfo() returned unexpected result:"); + out.println("# expected: an array of Mixer.Info objects (may be array of length 0);"); + out.println("# produced: null;"); + return STATUS_FAILED; + } + + if ( installedMixersInfo.length == 0 ) { + // there are no mixers installed on the system - so this testcase can not be tested + return STATUS_PASSED; + } + + Mixer testedMixer = null; + for (int i=0; i < installedMixersInfo.length; i++) { + try { + testedMixer = AudioSystem.getMixer(installedMixersInfo[i]); + } catch (SecurityException securityException) { + // installed Mixer is unavailable because of security restrictions + continue; + } catch (Throwable thrown) { + out.println("## AudioSystem.getMixer() threw unexpected exception:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + continue; + } + + try { + testedMixer.open(); + } catch (LineUnavailableException lineUnavailableException) { + // testedMixer is not available due to resource restrictions + continue; + } catch (SecurityException securityException) { + // testedMixer is not available due to security restrictions + continue; + } catch (Throwable thrown) { + out.println("## Mixer.open() threw unexpected exception:"); + out.println("# Mixer = " + testedMixer); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + continue; + } + Line.Info supportedSourceLineInfo[] = null; + try { + supportedSourceLineInfo = testedMixer.getSourceLineInfo(); + } catch (Throwable thrown) { + out.println("## Mixer.getSourceLineInfo() threw unexpected exception:"); + out.println("# Mixer = " + testedMixer); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + testedMixer.close(); + continue; + } + if ( supportedSourceLineInfo == null ) { + out.println("## Mixer.getSourceLineInfo() returned null array"); + out.println("# Mixer = " + testedMixer); + testResult = STATUS_FAILED; + testedMixer.close(); + continue; + } + out.println("\n>>> testedMixer["+i+"] = " + testedMixer); + out.println("\n>> supportedSourceLineInfo.length = " + supportedSourceLineInfo.length); + + for (int j=0; j < supportedSourceLineInfo.length; j++) { + Line.Info testSourceLineInfo = supportedSourceLineInfo[j]; + + Line testSourceLine = null; + try { + testSourceLine = testedMixer.getLine(testSourceLineInfo); + } catch (LineUnavailableException lineUnavailableException) { + // line is not available due to resource restrictions + continue; + } catch (SecurityException securityException) { + // line is not available due to security restrictions + continue; + } catch (Throwable thrown) { + out.println("## Mixer.getLine(Line.Info) threw unexpected Exception:"); + out.println("# Mixer = " + testedMixer); + out.println("# Line.Info = " + testSourceLineInfo); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + continue; + } + + out.println("\n> testSourceLineInfo["+j+"] = " + testSourceLineInfo); + out.println("> testSourceLine = " + testSourceLine); + if ( ! (testSourceLine instanceof SourceDataLine) ) { + out.println("> testSourceLine is not SourceDataLine"); + continue; + } + + SourceDataLine testedSourceLine = (SourceDataLine)testSourceLine; + AudioFormat lineAudioFormat = testedSourceLine.getFormat(); + + int bufferSizeToWrite = 1; + if ( lineAudioFormat.getSampleSizeInBits() != AudioSystem.NOT_SPECIFIED ) { + bufferSizeToWrite = lineAudioFormat.getSampleSizeInBits()/8; + if ( lineAudioFormat.getSampleSizeInBits()%8 != 0 ) { + bufferSizeToWrite++; + } + } + if ( lineAudioFormat.getFrameSize() != AudioSystem.NOT_SPECIFIED ) { + bufferSizeToWrite = lineAudioFormat.getFrameSize(); + } + byte[] dataToWrite = new byte[bufferSizeToWrite]; + for (int k=0; k < bufferSizeToWrite; k++) { + dataToWrite[k] = (byte)1; + } + int offsetToWrite = 0; + + out.println + ("\n> check SourceDataLine.write() for not open line with correct length of data:"); + int writtenBytes = -1; + try { + writtenBytes = testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite); + out.println("> Bytes written: number of written bytes = " + writtenBytes); + } catch (Throwable thrown) { + out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:"); + out.println("# Unexpected Exception is thrown"); + out.println("# Mixer = " + testedMixer); + out.println("# SourceDataLine = " + testedSourceLine); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + out.println + ("\n> check SourceDataLine.write() for not open line with incorrect length of data:"); + writtenBytes = -1; + bufferSizeToWrite--; + try { + writtenBytes = testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite); + out.println("> Bytes written: number of written bytes = " + writtenBytes); + } catch (IllegalArgumentException illegalArgumentException) { + out.println("> Permissible IllegalArgumentException for the present instance is thrown:"); + illegalArgumentException.printStackTrace(out); + } catch (Throwable thrown) { + out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:"); + out.println("# Unexpected Exception is thrown"); + out.println("# Mixer = " + testedMixer); + out.println("# SourceDataLine = " + testedSourceLine); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + out.println + ("\n> open tested line:"); + bufferSizeToWrite++; + try { + testedSourceLine.open(lineAudioFormat, bufferSizeToWrite); + out.println("> OK - line is opened"); + } catch (LineUnavailableException lineUnavailableException) { + out.println("> Line is not available due to resource restrictions:"); + lineUnavailableException.printStackTrace(out); + continue; + } catch (SecurityException securityException) { + out.println("> Line is not available due to security restrictions:"); + securityException.printStackTrace(out); + continue; + } catch (Throwable thrown) { + out.println("## SourceDataLine.open(AudioFormat format) failed:"); + out.println("# Unexpected Exception is thrown"); + out.println("# Mixer = " + testedMixer); + out.println("# SourceDataLine = " + testedSourceLine); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + continue; + } + + out.println + ("\n> check SourceDataLine.write() for not started line with correct length of data:"); + writtenBytes = -1; + try { + writtenBytes = testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite); + out.println("> Bytes written: number of written bytes = " + writtenBytes); + } catch (Throwable thrown) { + out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:"); + out.println("# Unexpected Exception is thrown"); + out.println("# Mixer = " + testedMixer); + out.println("# SourceDataLine = " + testedSourceLine); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + out.println + ("\n> check SourceDataLine.write() for not started line with incorrect length of data:"); + writtenBytes = -1; + bufferSizeToWrite--; + try { + writtenBytes = testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite); + out.println("> Bytes written: number of written bytes = " + writtenBytes); + } catch (IllegalArgumentException illegalArgumentException) { + out.println("> Permissible IllegalArgumentException for the present instance is thrown:"); + illegalArgumentException.printStackTrace(out); + } catch (Throwable thrown) { + out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:"); + out.println("# Unexpected Exception is thrown"); + out.println("# Mixer = " + testedMixer); + out.println("# SourceDataLine = " + testedSourceLine); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + testedSourceLine.close(); + + } // for (int j=0; j < supportedSourceLineInfo.length; j++) + testedMixer.close(); + + } // for (int i=0; i < installedMixersInfo.length; i++) + + if ( testResult == STATUS_FAILED ) { + out.println("\n==> test FAILED!"); + } else { + out.println("\n==> test PASSED!"); + } + return testResult; + } +} diff --git a/test/javax/sound/sampled/Lines/SourceDataLineDefaultBufferSizeCrash.java b/test/javax/sound/sampled/Lines/SourceDataLineDefaultBufferSizeCrash.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Lines/SourceDataLineDefaultBufferSizeCrash.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +/** + * @test + * @bug 4681384 + * @summary SourceDataLine.write() causes Unexpected Signal 11 in native code + * outside the VM + */ +public class SourceDataLineDefaultBufferSizeCrash { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + public static void main(String argv[]) throws Exception { + int testExitStatus = run(argv, System.out) + STATUS_TEMP; + } + + public static int run(String argv[], java.io.PrintStream out) throws Exception { + int testResult = STATUS_PASSED; + + int framesNumberToExceed = 2; + if ( argv.length > 0 ) { + try { + framesNumberToExceed = Integer.parseInt(argv[0]); + } + catch (NumberFormatException e) { + } + } + + out.println + ("\n==> Test for SourceDataLine.write() method:"); + + Mixer.Info[] installedMixersInfo = AudioSystem.getMixerInfo(); + + if ( installedMixersInfo == null ) { + out.println("## AudioSystem.getMixerInfo() returned unexpected result:"); + out.println("# expected: an array of Mixer.Info objects (may be array of length 0);"); + out.println("# produced: null;"); + return STATUS_FAILED; + } + + if ( installedMixersInfo.length == 0 ) { + // there are no mixers installed on the system - + // so this testcase can not be tested + out.println("\n>>> There are no mixers installed on the system!"); + return STATUS_PASSED; + } + + out.println("\n>>> Number of mixers installed on the system = " + + installedMixersInfo.length); + Mixer installedMixer = null; + for (int i=0; i < installedMixersInfo.length; i++) { + try { + installedMixer = AudioSystem.getMixer(installedMixersInfo[i]); + } catch (SecurityException securityException) { + // installed Mixer is unavailable because of security restrictions + out.println("\n>>> installedMixer[" + i + + "] is unavailable because of security restrictions"); + continue; + } catch (Throwable thrown) { + out.println("\n## installedMixer[" + i + "] is unavailable because of"); + out.println("# AudioSystem.getMixer() threw unexpected exception:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + continue; + } + + out.println("\n>>> installedMixer["+i+"] = " + installedMixer); + try { + installedMixer.open(); + } catch (LineUnavailableException lineUnavailableException) { + // installedMixer is not available due to resource restrictions + out.println(">> installedMixer[" + i + + "] is not opened because of resource restrictions"); + continue; + } catch (SecurityException securityException) { + // installedMixer is not available due to security restrictions + out.println(">> installedMixer[" + i + + "] is not opened because of security restrictions"); + continue; + } catch (Throwable thrown) { + out.println("## installedMixer.open() throws unexpected exception:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + continue; + } + Line.Info supportedSourceLineInfo[] = null; + try { + supportedSourceLineInfo = installedMixer.getSourceLineInfo(); + } catch (Throwable thrown) { + out.println("## installedMixer.getSourceLineInfo() throws " + + "unexpected exception:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + installedMixer.close(); + continue; + } + if ( supportedSourceLineInfo == null ) { + out.println("## installedMixer.getSourceLineInfo() returned null array"); + out.println("# Mixer = " + installedMixer); + testResult = STATUS_FAILED; + installedMixer.close(); + continue; + } + out.println("\n>> Number of SourceLineInfo supported by installedMixer =" + + supportedSourceLineInfo.length); + + for (int j=0; j < supportedSourceLineInfo.length; j++) { + Line.Info testSourceLineInfo = supportedSourceLineInfo[j]; + + out.println("\n> testSourceLineInfo["+j+"] = " + testSourceLineInfo); + Line testSourceLine = null; + try { + testSourceLine = installedMixer.getLine(testSourceLineInfo); + } catch (LineUnavailableException lineUnavailableException) { + // line is not available due to resource restrictions + out.println("> Line for this SourceLine Info is not available " + + "due to resource restrictions"); + continue; + } catch (SecurityException securityException) { + // line is not available due to security restrictions + out.println("> Line for this SourceLine Info is not available " + + "due to security restrictions"); + continue; + } catch (Throwable thrown) { + out.println("## installedMixer.getLine(testSourceLineInfo) throws" + + "unexpected Exception:"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + continue; + } + + out.println("> testedSourceLine = " + testSourceLine); + if ( ! (testSourceLine instanceof SourceDataLine) ) { + out.println("> testSourceLine is not SourceDataLine"); + continue; + } + + SourceDataLine testedSourceLine = (SourceDataLine)testSourceLine; + AudioFormat lineAudioFormat = testedSourceLine.getFormat(); + + out.println("\n> opening tested SourceLine:"); + try { + //testedSourceLine.open(lineAudioFormat, 2048); + testedSourceLine.open(lineAudioFormat); + out.println("> OK - line is opened with "+testedSourceLine.getBufferSize()+" bytes buffer"); + } catch (LineUnavailableException lineUnavailableException) { + out.println("> Line is not available due to resource restrictions:"); + lineUnavailableException.printStackTrace(out); + continue; + } catch (SecurityException securityException) { + out.println("> Line is not available due to security restrictions:"); + securityException.printStackTrace(out); + continue; + } catch (Throwable thrown) { + out.println("## SourceDataLine.open(AudioFormat format) failed:"); + out.println("# Unexpected Exception is thrown"); + out.println("# Mixer = " + installedMixer); + out.println("# SourceDataLine = " + testedSourceLine); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + continue; + } + + testedSourceLine.start(); + + int frameSize = 1; + if ( lineAudioFormat.getFrameSize() != AudioSystem.NOT_SPECIFIED ) { + frameSize = lineAudioFormat.getFrameSize(); + } else { + if ( lineAudioFormat.getSampleSizeInBits() != AudioSystem.NOT_SPECIFIED ) { + frameSize = lineAudioFormat.getSampleSizeInBits()/8; + if ( lineAudioFormat.getSampleSizeInBits()%8 != 0 ) { + frameSize++; + } + } + } + int bufferSizeToWrite = testedSourceLine.available() + + (frameSize * framesNumberToExceed); + byte[] dataToWrite = new byte[bufferSizeToWrite]; + for (int k=0; k < bufferSizeToWrite; k++) { + dataToWrite[k] = (byte)1; + } + int offsetToWrite = 0; + + out.println("\n> check SourceDataLine.write() to write more data " + + "than can currently be written:"); + + out.println("> testedSourceLine.available() = " + testedSourceLine.available()); + out.println("> frame size = " + frameSize); + out.println("> number of bytes to write = " + bufferSizeToWrite); + int writtenBytes = -1; + try { + writtenBytes = + testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite); + out.println("> OK - number of written bytes = " + writtenBytes); + } catch (Throwable thrown) { + out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:"); + out.println("# Unexpected Exception is thrown"); + thrown.printStackTrace(out); + testResult = STATUS_FAILED; + } + + testedSourceLine.close(); + + } // for (int j=0; j < supportedSourceLineInfo.length; j++) + installedMixer.close(); + + } // for (int i=0; i < installedMixersInfo.length; i++) + + if ( testResult == STATUS_FAILED ) { + throw new Exception("Test FAILED!"); + } else { + out.println("\n==> test PASSED!"); + } + return testResult; + } + +} diff --git a/test/javax/sound/sampled/Lines/StopStart.java b/test/javax/sound/sampled/Lines/StopStart.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Lines/StopStart.java @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.File; +import java.util.Random; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +/** + * @test + * @bug 4828556 + * @summary stopping and starting sampled audio plays small chunk in infinite + * loop + */ +public class StopStart implements Runnable { + + static int sampleRate = 8000; + static double frequency = 2000.0; + static double RAD = 2.0 * Math.PI; + static Random random = new Random(); + + static byte[] audioData = new byte[sampleRate/2]; + static SourceDataLine source; + + static boolean terminated = false; + + static int buffersWritten = 0; + static long bytesWritten = 0; + static int buffersWrittenAfter5Seconds; + + static AudioInputStream ais = null; + static AudioFormat audioFormat; + static String filename; + + static int executedTests=0; + static int successfulTests = 0; + + public static void constructAIS() throws Exception { + ais = AudioSystem.getAudioInputStream(new File(filename)); + } + + public static void doStartStopTest1() throws Exception { + System.out.println("TEST 1: play for 3 seconds, stop/start/stop/start/play for 3 seconds..."); + source.start(); + Thread.sleep(100); + bytesWritten = 0; + System.out.println("Waiting for 3 seconds..."); + Thread.sleep(3000); + buffersWrittenAfter5Seconds = buffersWritten; + System.out.println("Buffers Written: "+buffersWritten); + System.out.println("stop()->start()->stop()->start()"); + source.stop(); + //System.out.println("start()"); + source.start(); + //System.out.println("stop()2 ----------------------------------------------------------"); + source.stop(); + //System.out.println("start()"); + source.start(); + System.out.println("Buffers Written: "+buffersWritten); + System.out.println("Waiting for 3 seconds..."); + Thread.sleep(3000); + System.out.println("Buffers Written: "+buffersWritten); + if (buffersWritten >= ((buffersWrittenAfter5Seconds * 2) - ((buffersWrittenAfter5Seconds / 4)))) { + successfulTests++; + } + } + + private static int nextWaitTime() { + int waitTime = random.nextInt(25); + waitTime*=waitTime; + if (waitTime<20) waitTime = 0; + return waitTime; + } + + + public static void doStartStopTest2() throws Exception { + System.out.println("TEST 2: start and stop 100 times with random wait in between"); + int max=100; + for (int i=0; i0) { + Thread.sleep(waitTime); + } + System.out.println("stop()"); + source.stop(); + waitTime = nextWaitTime(); + System.out.println("Waiting for "+waitTime+"ms..."); + if (waitTime>0) { + Thread.sleep(waitTime); + } + } + } + + public static void doStartStopTest3() throws Exception { + System.out.println("TEST 3: start and stop 100 times with random wait only every 10 rounds "); + int max=100; + for (int i=0; i0) { + Thread.sleep(waitTime); + } + } + System.out.println("stop()"); + source.stop(); + if (i % 13 == 12) { + int waitTime = nextWaitTime(); + System.out.println("Waiting for "+waitTime+"ms..."); + if (waitTime>0) { + Thread.sleep(waitTime); + } + } + } + } + + public static void runTest(int testNum) { + terminated = false; + Thread thread = null; + buffersWrittenAfter5Seconds = 0; + // make the tests reproduceable by always seeding with same value + random.setSeed(1); + try { + executedTests++; + thread = new Thread(new StopStart()); + thread.start(); + switch (testNum) { + case 1: doStartStopTest1(); break; + case 2: doStartStopTest2(); break; + case 3: doStartStopTest3(); break; + } + } catch (Exception e) { + e.printStackTrace(); + } + source.stop(); + source.close(); + if (thread!=null) { + terminated = true; + System.out.println("Waiting for thread to die..."); + try { + thread.join(); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + + public static void main(String[] args) throws Exception { + filename = null; + if (args.length>0) { + File f = new File(args[0]); + if (f.exists()) { + filename = args[0]; + System.out.println("Opening "+filename); + constructAIS(); + audioFormat = ais.getFormat(); + } + } + if (filename == null) { + audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true); + for (int i=0; i0) { + if (successfulTests == 0) { + if (args.length == 0) { + throw new Exception("Test FAILED"); + } + System.out.println("test FAILED."); + } else { + System.out.println("test successful."); + } + } else { + System.out.println("Could not execute any tests - are soundcards correctly installed?"); + System.out.println("Test NOT FAILED."); + } + } + + public void run() { + int len = audioData.length; + int offset = len; + System.out.println("Thread: started. Beginning audio i/o"); + while (!terminated) { + try { + //if (!source.isActive()) { + // Thread.sleep(50); + //} + if (offset >= len) { + offset = 0; + if (ais!=null) { + do { + len = ais.read(audioData, 0, audioData.length); + if (len < 0) { + constructAIS(); + } + } while (len < 0); + } + } + int toWrite = len - offset; + int written = source.write(audioData, offset, toWrite); + offset+=written; + bytesWritten += written; + buffersWritten = (int) (bytesWritten / audioData.length); + } catch (Exception e) { + e.printStackTrace(); + terminated = true; + } + } + System.out.println("Thread: closing line"); + source.stop(); + source.close(); + System.out.println("Thread finished"); + } +} diff --git a/test/javax/sound/sampled/LinuxBlock/PlaySine.java b/test/javax/sound/sampled/LinuxBlock/PlaySine.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/LinuxBlock/PlaySine.java @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.File; +import java.io.IOException; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +/** + * @test + * @bug 4834461 + * @summary Applet hang when you load it during sound card is in use + * @run main/manual PlaySine + */ +public class PlaySine { + + static int sampleRate = 8000; + static double frequency = 2000.0; + static double RAD = 2.0 * Math.PI; + + static byte[] audioData = new byte[sampleRate/2]; + static SourceDataLine source; + static Mixer mixer = null; + + static AudioInputStream ais = null; + static AudioFormat audioFormat; + static String filename; + + public static void constructAIS() { + try { + ais = AudioSystem.getAudioInputStream(new File(filename)); + } catch (Exception e) { + println("ERROR: could not open "+filename+": "+e.getMessage()); + } + } + + public static void print(String s) { + System.out.print(s); + } + public static void println(String s) { + System.out.println(s); + } + + public static void key() { + println(""); + print("Press ENTER to continue..."); + try { + System.in.read(); + } catch (IOException ioe) { + } + } + + static int audioLen = -1; + static int audioOffset = -1; + + public static void writeData() { + if (audioLen == -1) { + audioLen = audioData.length; + } + if (audioOffset < 0) { + audioOffset = audioLen; + } + try { + if (audioOffset >= audioLen) { + audioOffset = 0; + if (ais!=null) { + do { + audioLen = ais.read(audioData, 0, audioData.length); + if (audioLen < 0) { + constructAIS(); + } + } while (audioLen < 0); + } + } + int toWrite = audioLen - audioOffset; + int written = source.write(audioData, audioOffset, toWrite); + audioOffset+=written; + } catch (Exception e) { + e.printStackTrace(); + } + } + + + public static int play(boolean shouldPlay) { + int res = 0; + DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); + try { + println("Getting line from mixer..."); + source = (SourceDataLine) mixer.getLine(info); + println("Opening line..."); + println(" -- if the program is hanging here, kill the process that has blocks the audio device now."); + source.open(audioFormat); + println("Starting line..."); + source.start(); + println("Writing audio data for 1 second..."); + long startTime = System.currentTimeMillis(); + while (System.currentTimeMillis() - startTime < 1000) { + writeData(); + Thread.sleep(100); + } + res = 1; + } catch (IllegalArgumentException iae) { + println("IllegalArgumentException: "+iae.getMessage()); + println("Sound device cannot handle this audio format."); + println("ERROR: Test environment not correctly set up."); + if (source!=null) { + source.close(); + } + return 3; + } catch (LineUnavailableException lue) { + println("LineUnavailableException: "+lue.getMessage()); + if (shouldPlay) { + println("ERROR: the line should be available now!."); + println(" Verify that you killed the other audio process."); + } else { + println("Correct behavior! the bug is fixed."); + } + res = 2; + } catch (Exception e) { + println("Unexpected Exception: "+e.toString()); + } + if (source != null) { + println("Draining..."); + try { + source.drain(); + } catch (NullPointerException npe) { + println("(NullPointerException: bug fixed in J2SE 1.4.2"); + } + println("Stopping..."); + source.stop(); + println("Closing..."); + source.close(); + source = null; + } + return res; + } + + public static void main(String[] args) throws Exception { + println("This is an interactive test. You can run it with a filename as argument"); + println("It is only meant to be run on linux, with the (old) OSS kernel drivers (/dev/dsp)"); + println("This test should not be run on systems with ALSA installed, or kernel 2.6 or higher."); + println(""); + println("The test verifies that Java Sound fails correctly if another process is blocking"); + println("the audio device."); + println(""); + println("Checking sanity..."); + Mixer.Info[] mixers=null; + + mixers = AudioSystem.getMixerInfo(); + for (int i=0; i=0 + && mixerName.indexOf("Engine")>=0) { + mixer = thisMixer; + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + if (mixer == null) { + if (mixers.length==0) { + System.out.println("ERROR: No mixers available!"); + } else { + println("ERROR: Java Sound Engine could not be found."); + } + println("Cannot run this test."); + return; + } + println(" ...using mixer "+mixer.getMixerInfo()); + + String osname = System.getProperty("os.name"); + if ((osname == null) || (osname.toLowerCase().indexOf("linux")<0)) { + println("ERROR: not running on linux (you are running on "+osname+")"); + return; + } + println(" ...running on "+osname); + println(" ...sanity test OK."); + + filename = null; + if (args.length>0) { + File f = new File(args[0]); + if (f.exists()) { + filename = args[0]; + println("Opening "+filename); + constructAIS(); + if (ais!=null) { + audioFormat = ais.getFormat(); + } + } + } + if (ais == null) { + println("Using self-generated sine wave for playback"); + audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true); + for (int i=0; i /dev/dsp"); + key(); + println("After you press ENTER now, the mixer will be opened."); + println("There are 3 possible cases that can occur:"); + println("1) you'll hear a sine wave"); + println(" -> you are running with mixing OSS drivers. "); + println(" Some soundcards only provide mixing OSS drivers."); + println(" Test environment not valid. "); + println(" Repeat on another machine where you can reproduce the bug first."); + println("2) this program stops doing anything after 'Opening line...'"); + println(" -> this is the bug."); + println(" Kill the command on the other console with Ctrl-C, this program"); + println(" should continue working then."); + println("3) this program reports a LineUnavailableException"); + println(" -> bug is fixed."); + println(" OR you run with non-blocking OSS drivers."); + println(" make sure that you can reproduce this bug first with e.g. J2SE 1.4.1"); + key(); + int playedFirst = play(false); + int playedSecond = 0; + + if (playedFirst == 2) { + println(""); + println("Now kill the other process with Ctrl-C."); + println("After that, this program should be able to play "); + println("the sine wave without problems."); + key(); + playedSecond = play(true); + } + println(""); + if (playedFirst == 1) { + println("Test FAILED."); + } + else if (playedFirst == 2 && playedSecond == 1) { + println("Test SUCCESSFUL"); + } else { + println("Test not failed (but not successful either...)."); + } + } +} diff --git a/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash.java b/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineListener; + +/** + * @test + * @bug 4498848 + * @summary Sound causes crashes on Linux (part 1) + */ +public class ClipLinuxCrash { + + static Clip clip; + + public static long bytes2Ms(long bytes, AudioFormat format) { + return (long) (bytes / format.getFrameRate() * 1000 + / format.getFrameSize()); + } + + static int staticLen = 1000; + + static boolean addLen = true; + + public static long start() throws Exception { + AudioFormat fmt = new AudioFormat(44100, 16, 2, true, false); + if (addLen) { + staticLen += (int) (staticLen / 5) + 1000; + } else { + staticLen -= (int) (staticLen / 5) + 1000; + } + if (staticLen > 8 * 44100 * 4) { + staticLen = 8 * 44100 * 4; + addLen = !addLen; + } + if (staticLen < 1000) { + staticLen = 1000; + addLen = !addLen; + } + int len = staticLen; + len -= (len % 4); + byte[] fakedata = new byte[len]; + InputStream is = new ByteArrayInputStream(fakedata); + AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, + 44100, 16, 2, 4, 44100, false); + AudioInputStream ais = new AudioInputStream(is, format, fakedata.length + / format.getFrameSize()); + + out(" preparing to play back " + len + " bytes == " + bytes2Ms(len, + format) + + "ms audio..."); + + DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat()); + clip = (Clip) AudioSystem.getLine(info); + clip.addLineListener(new LineListener() { + public void update(LineEvent e) { + if (e.getType() == LineEvent.Type.STOP) { + out(" calling close() from event dispatcher thread"); + ((Clip) e.getSource()).close(); + } else if (e.getType() == LineEvent.Type.CLOSE) { + } + } + }); + + out(" opening..."); + try { + clip.open(ais); + } catch (Throwable t) { + t.printStackTrace(); + clip.close(); + clip = null; + } + ais.close(); + if (clip != null) { + out(" starting..."); + clip.start(); + } + return bytes2Ms(fakedata.length, format); + } + + public static void main(String[] args) throws Exception { + if (AudioSystem.getMixerInfo().length == 0) { + System.out.println("Cannot execute test: no mixers installed!"); + System.out.println("Not Failed."); + return; + } + try { + int COUNT = 10; + out(); + out("4498848 Sound causes crashes on Linux (testing with Clip)"); + if (args.length > 0) { + COUNT = Integer.parseInt(args[0]); + } + for (int i = 0; i < COUNT; i++) { + out(" trial " + (i + 1) + "/" + COUNT); + start(); + int waitTime = 500 + (1000 * (i + % 2)); // every second + // time wait 1500, rather than 500ms. + out(" waiting for " + waitTime + + " ms for audio playback to stop..."); + Thread.sleep(waitTime); + out(" calling close() from main thread"); + if (clip != null) { + clip.close(); + } + // let the subsystem enough time to actually close the soundcard + out(" waiting for 2 seconds..."); + Thread.sleep(2000); + out(); + } + out(" waiting for 1 second..."); + Thread.sleep(1000); + } catch (Exception e) { + e.printStackTrace(); + out(" waiting for 1 second"); + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + } + throw e; + } + out("Test passed"); + } + + static void out() { + out(""); + } + + static void out(String s) { + System.out.println(s); + System.out.flush(); + } + +} diff --git a/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash2.java b/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash2.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash2.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4498848 + * @summary Sound causes crashes on Linux (part 3) + */ +public class ClipLinuxCrash2 implements LineListener{ + Clip clip; + int stopOccured; + static final Object lock = new Object(); + + public static long bytes2Ms(long bytes, AudioFormat format) { + return (long) (bytes/format.getFrameRate()*1000/format.getFrameSize()); + } + + static int staticLen=1000; + static boolean addLen=true; + + ClipLinuxCrash2() { + } + + public void update(LineEvent e) { + if (e.getType() == LineEvent.Type.STOP) { + stopOccured++; + out(" Test program: receives STOP event for clip="+clip.toString()+" no."+stopOccured); + out(" Test program: Calling close() in event dispatcher thread"); + clip.close(); + synchronized (lock) { + lock.notifyAll(); + } + } + else if (e.getType() == LineEvent.Type.CLOSE) { + out(" Test program: receives CLOSE event for "+clip.toString()); + synchronized (lock) { + lock.notifyAll(); + } + } + else if (e.getType() == LineEvent.Type.START) { + out(" Test program: receives START event for "+clip.toString()); + } + else if (e.getType() == LineEvent.Type.OPEN) { + out(" Test program: receives OPEN event for "+clip.toString()); + } + } + + public long start() throws Exception { + AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + + if (addLen) { + staticLen+=(int) (staticLen/5)+1000; + } else { + staticLen-=(int) (staticLen/5)+1000; + } + if (staticLen>8*44100*4) { + staticLen = 8*44100*4; + addLen=!addLen; + } + if (staticLen<1000) { + staticLen = 1000; + addLen=!addLen; + } + int len = staticLen; + len -= (len % 4); + out(" Test program: preparing to play back "+len+" bytes == "+bytes2Ms(len, format)+"ms audio..."); + + byte[] fakedata=new byte[len]; + InputStream is = new ByteArrayInputStream(fakedata); + AudioInputStream ais = new AudioInputStream(is, format, fakedata.length/format.getFrameSize()); + + DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat()); + clip = (Clip) AudioSystem.getLine(info); + clip.addLineListener(this); + + out(" Test program: opening clip="+((clip==null)?"null":clip.toString())); + clip.open(ais); + ais.close(); + out(" Test program: starting clip="+((clip==null)?"null":clip.toString())); + clip.start(); + return bytes2Ms(fakedata.length, format); + } + + public static void main(String[] args) throws Exception { + if (!isSoundcardInstalled()) { + return; + } + + try { + int COUNT=10; + out(); + out("4498848 Sound causes crashes on Linux"); + if (args.length>0) { + COUNT=Integer.parseInt(args[0]); + } + for (int i=0; i 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } + +} diff --git a/test/javax/sound/sampled/LinuxCrash/SDLLinuxCrash.java b/test/javax/sound/sampled/LinuxCrash/SDLLinuxCrash.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/LinuxCrash/SDLLinuxCrash.java @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +/** + * @test + * @bug 4498848 + * @summary Sound causes crashes on Linux (part 2) + */ +public class SDLLinuxCrash implements Runnable { + SourceDataLine sdl; + int size; + + SDLLinuxCrash(SourceDataLine sdl, int size) { + this.sdl = sdl; + this.size = size - (size % 4); + } + + public void run() { + int written=0; + //byte[] buffer = new byte[4096]; + byte[] buffer = data; + out(" starting data line feed thread."); + try { + while (written size) { + toWrite = size-written; + } + toWrite -= (toWrite % 4); + //out(" writing "+toWrite+" bytes."); + int thisWritten = sdl.write(buffer, 0, toWrite); + if (thisWritten8*44100*4) { + staticLen = 8*44100*4; + addLen=!addLen; + } + if (staticLen<1000) { + staticLen = 1000; + addLen=!addLen; + } + int len = staticLen; + len -= (len % 4); + out(" preparing to play back "+len+" bytes == "+bytes2Ms(len, format)+"ms audio..."); + + DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); + SourceDataLine sdl = (SourceDataLine) AudioSystem.getLine(info); + sdl.addLineListener(new LineListener() { + public void update(LineEvent e) { + if (e.getType() == LineEvent.Type.STOP) { + out(" calling close() from event dispatcher thread"); + ((SourceDataLine) e.getSource()).close(); + } + else if (e.getType() == LineEvent.Type.CLOSE) { + } + } + }); + + out(" opening..."); + sdl.open(); + out(" starting..."); + sdl.start(); + (new Thread(new SDLLinuxCrash(sdl, len))).start(); + return sdl; + } + + public static void main(String[] args) throws Exception { + if (!isSoundcardInstalled()) { + return; + } + + try { + int COUNT=10; + out(); + out("4498848 Sound causes crashes on Linux (testing with SourceDataLine)"); + if (args.length>0) { + COUNT=Integer.parseInt(args[0]); + } + for (int i=0; i 0) { + result = AudioSystem.getSourceDataLine(null) != null; + } + } catch (Exception e) { + System.err.println("Exception occured: "+e); + } + if (!result) { + System.err.println("Soundcard does not exist or sound drivers not installed!"); + System.err.println("This test requires sound drivers for execution."); + } + return result; + } + + + + static final byte[] data = new byte[] { + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, + 123, 110, 100, 60, 11, 10, 10, 10, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, 122, 122 + }; + +} diff --git a/test/javax/sound/sampled/Mixers/BogusMixers.java b/test/javax/sound/sampled/Mixers/BogusMixers.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/BogusMixers.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4667064 + * @summary Java Sound provides bogus SourceDataLine and TargetDataLine + */ +public class BogusMixers { + + public static void main(String[] args) throws Exception { + try { + out("4667064: Java Sound provides bogus SourceDataLine and TargetDataLine"); + + Mixer.Info[] aInfos = AudioSystem.getMixerInfo(); + out(" available Mixers:"); + for (int i = 0; i < aInfos.length; i++) { + if (aInfos[i].getName().startsWith("Java Sound Audio Engine")) { + Mixer mixer = AudioSystem.getMixer(aInfos[i]); + Line.Info[] tlInfos = mixer.getTargetLineInfo(); + for (int ii = 0; ii 0) { + if (format.getSampleSizeInBits() == 8) { + // return the other signed'ness + if (isSigned) { + newEnc = AudioFormat.Encoding.PCM_UNSIGNED; + } else { + newEnc = AudioFormat.Encoding.PCM_SIGNED; + } + } else { + newEnc = format.getEncoding(); + newEndian = !newEndian; + } + if (newEnc != null) { + return new AudioFormat(newEnc, format.getSampleRate(), + format.getSampleSizeInBits(), + format.getChannels(), + format.getFrameSize(), + format.getFrameRate(), + newEndian); + } + } + return null; + } + + static void out(String s) { + System.out.println(s); System.out.flush(); + } +} diff --git a/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/DirectSoundRepeatingBuffer.java b/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/DirectSoundRepeatingBuffer.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/DirectSoundRepeatingBuffer.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import java.io.IOException; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +/** + * This is utility class for Test4997635. + */ +public class DirectSoundRepeatingBuffer { + + static int sampleRate = 8000; + static double frequency = 1000.0; + static double RAD = 2.0 * Math.PI; + + static byte[] audioData = new byte[sampleRate/8]; + static DataLine.Info info; + static SourceDataLine source; + + //static AudioInputStream ais = null; + static AudioFormat audioFormat; + //static String filename; + + public static void print(String s) { + System.out.print(s); + } + public static void println(String s) { + System.out.println(s); + } + + public static void key() { + println(""); + print("Press ENTER to continue..."); + try { + System.in.read(); + } catch (IOException ioe) { + } + println(""); + } + + public static void play(Mixer mixer) { + int res = 0; + try { + println("Getting SDL from mixer..."); + source = (SourceDataLine) mixer.getLine(info); + println("Opening SDL..."); + source.open(audioFormat); + println("Writing data to SDL..."); + source.write(audioData, 0, audioData.length); + println("Starting SDL..."); + source.start(); + println("Now open your ears:"); + println("- you should have heard a short tone,"); + println(" followed by silence."); + println("- if after a while you hear repeated tones,"); + println(" the bug is NOT fixed."); + println("- if the program remains silent after the "); + println(" initial tone, the bug is fixed."); + key(); + } catch (IllegalArgumentException iae) { + println("IllegalArgumentException: "+iae.getMessage()); + println("Sound device cannot handle this audio format."); + println("ERROR: Test environment not correctly set up."); + if (source!=null) { + source.close(); + source = null; + } + return; + } catch (LineUnavailableException lue) { + println("LineUnavailableException: "+lue.getMessage()); + println("This is normal for some mixers."); + } catch (Exception e) { + println("Unexpected Exception: "+e.toString()); + } + if (source != null) { + println("Stopping..."); + source.stop(); + println("Closing..."); + source.close(); + println("Closed."); + source = null; + } + } + + public static void main(String[] args) throws Exception { + println("This is an interactive test for DirectAudio."); + println("If the tone repeats, the test is failed."); + println(""); + println("Make sure that you have speakers connected"); + println("and that the system mixer is not muted."); + println(""); + println("Press a key to start the test."); + key(); + Mixer.Info[] mixers=null; + + println(" ...using self-generated sine wave for playback"); + audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true); + for (int i=0; inot a DirectAudio Mixer!"); + } else { + try { + Mixer mixer = AudioSystem.getMixer(mixers[i]); + if (!mixer.isLineSupported(info)) { + println(" ->doesn't support SourceDataLine!"); + } else { + succMixers++; + println(" -> is getting tested."); + play(mixer); + } + } catch (Exception e) { + println(" -> Exception occured: "+e); + e.printStackTrace(); + } + } + } + if (succMixers == 0) { + println("No DirectAudio mixers available! "); + println("Cannot run test."); + } + } +} diff --git a/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/Test4997635.java b/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/Test4997635.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/Test4997635.java @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import java.awt.Button; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @test + * @bug 4997635 + * @summary Win: SourceDataLine playback loops endlessly unless you manually + * stop() + * @build DirectSoundRepeatingBuffer + * @run main/manual Test4997635 + */ +public class Test4997635 { + + private static void init() throws Exception { + //*** Create instructions for the user here *** + + String[] instructions = + { + "To run the test follow these instructions:", + "1. Open a terminal window.", + "2. Type \"cd " + System.getProperty("test.classes") + "\".", + "3. Type \"" + System.getProperty("java.home") + "/bin/java DirectSoundRepeatingBuffer\".", + "4. Follow the instructions shown in the terminal window.", + "If no error occured during the test, and the java application ", + "in the termial exited successfully, press PASS, else press FAIL." + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + } + + /***************************************************** + Standard Test Machinery Section + DO NOT modify anything in this section -- it's a + standard chunk of code which has all of the + synchronisation necessary for the test harness. + By keeping it the same in all tests, it is easier + to read and understand someone else's test, as + well as insuring that all tests behave correctly + with the test harness. + There is a section following this for test-defined + classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + public static void main( String args[] ) throws Exception + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test passed nor test failed has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + + }// class Orient + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException + { + } + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// make listeners in a class defined here, and instantiate them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + Orient.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + Orient.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + + }// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog implements ActionListener + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //DialogOrient + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + Test4997635.pass(); + } + else + { + Test4997635.fail(); + } + } + + }// TestDialog class diff --git a/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/DirectSoundUnderrunSilence.java b/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/DirectSoundUnderrunSilence.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/DirectSoundUnderrunSilence.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.IOException; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +/** + * This is utility class for Test5032020. + */ +public class DirectSoundUnderrunSilence { + + static int sampleRate = 8000; + static double frequency = 1000.0; + static double RAD = 2.0 * Math.PI; + + static byte[] audioData = new byte[sampleRate/8]; + static DataLine.Info info; + static SourceDataLine source; + + //static AudioInputStream ais = null; + static AudioFormat audioFormat; + //static String filename; + + public static void print(String s) { + System.out.print(s); + } + public static void println(String s) { + System.out.println(s); + } + + public static void key() { + println(""); + print("Press ENTER to continue..."); + try { + System.in.read(); + } catch (IOException ioe) { + } + println(""); + } + + public static void play(Mixer mixer) { + int res = 0; + try { + println("Getting SDL from mixer..."); + source = (SourceDataLine) mixer.getLine(info); + println("Opening SDL..."); + source.open(audioFormat); + println("Writing data to SDL..."); + source.write(audioData, 0, audioData.length); + println("Starting SDL..."); + source.start(); + println("Now open your ears:"); + println("You should have heard a short tone,"); + println("followed by silence (no repeating tones)."); + key(); + source.write(audioData, 0, audioData.length); + println("Now you should have heard another short tone."); + println("If you did not hear a second tone, or more than 2 tones,"); + println("the test is FAILED."); + println("otherwise, if you heard a total of 2 tones, the bug is fixed."); + key(); + } catch (IllegalArgumentException iae) { + println("IllegalArgumentException: "+iae.getMessage()); + println("Sound device cannot handle this audio format."); + println("ERROR: Test environment not correctly set up."); + if (source!=null) { + source.close(); + source = null; + } + return; + } catch (LineUnavailableException lue) { + println("LineUnavailableException: "+lue.getMessage()); + println("This is normal for some mixers."); + } catch (Exception e) { + println("Unexpected Exception: "+e.toString()); + } + if (source != null) { + println("Stopping..."); + source.stop(); + println("Closing..."); + source.close(); + println("Closed."); + source = null; + } + } + + public static void main(String[] args) throws Exception { + println("This is an interactive test for DirectAudio."); + println("If it's impossible to play data after an underun, the test fails."); + println(""); + println("Make sure that you have speakers connected"); + println("and that the system mixer is not muted."); + println("Also stop all other programs playing sounds:"); + println("It has been seen that it alters the results."); + println(""); + println("Press a key to start the test."); + key(); + Mixer.Info[] mixers=null; + + println(" ...using self-generated sine wave for playback"); + audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true); + for (int i=0; inot a DirectAudio Mixer!"); + } else { + try { + Mixer mixer = AudioSystem.getMixer(mixers[i]); + if (!mixer.isLineSupported(info)) { + println(" ->doesn't support SourceDataLine!"); + } else { + succMixers++; + println(" -> is getting tested."); + play(mixer); + } + } catch (Exception e) { + println(" -> Exception occured: "+e); + e.printStackTrace(); + } + } + } + if (succMixers == 0) { + println("No DirectAudio mixers available! "); + println("Cannot run test."); + } + } + +} diff --git a/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/Test5032020.java b/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/Test5032020.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/Test5032020.java @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.awt.Button; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @test + * @bug 5032020 + * @summary Win: Direct Audio is silent after underrun + * @build DirectSoundUnderrunSilence + * @run main/manual Test5032020 + */ +public class Test5032020 { + + private static void init() throws Exception { + //*** Create instructions for the user here *** + + String[] instructions = + { + "To run the test follow these instructions:", + "1. Open a terminal window.", + "2. Type \"cd " + System.getProperty("test.classes") + "\".", + "3. Type \"" + System.getProperty("java.home") + "/bin/java DirectSoundUnderrunSilence\".", + "4. Follow the instructions shown in the terminal window.", + "If no error occured during the test, and the java application ", + "in the termial exited successfully, press PASS, else press FAIL." + }; + + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + } + + /***************************************************** + Standard Test Machinery Section + DO NOT modify anything in this section -- it's a + standard chunk of code which has all of the + synchronisation necessary for the test harness. + By keeping it the same in all tests, it is easier + to read and understand someone else's test, as + well as insuring that all tests behave correctly + with the test harness. + There is a section following this for test-defined + classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + public static void main( String args[] ) throws Exception + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test passed nor test failed has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + + }// class Orient + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException + { + } + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// make listeners in a class defined here, and instantiate them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + Orient.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + Orient.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + + }// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog implements ActionListener + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + show(); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //DialogOrient + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + Test5032020.pass(); + } + else + { + Test5032020.fail(); + } + } + + }// TestDialog class diff --git a/test/javax/sound/sampled/Mixers/DisabledAssertionCrash.java b/test/javax/sound/sampled/Mixers/DisabledAssertionCrash.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/DisabledAssertionCrash.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.TargetDataLine; + +/** + * @test + * @bug 4991672 + * @summary disabled assertion at maximum thread priority causes audio crash + * @run main/timeout=600 DisabledAssertionCrash + */ +public class DisabledAssertionCrash { + private static final int bufferSize = 1024; + + public static void main(String[] args) { + + System.out.println("This program hangs if priority is set,"); + System.out.println("and assertion is in the code."); + System.out.println("The program crashes the entire Windows system"); + System.out.println("if assertions are disabled."); + try { + Thread.currentThread().setPriority(Thread.MAX_PRIORITY); + AudioFormat audioFormat = new AudioFormat(44100,16,1,true,true); + Line.Info sourceDataLineInfo = new DataLine.Info(SourceDataLine.class,audioFormat); + SourceDataLine sourceDataLine = + (SourceDataLine) AudioSystem.getLine(sourceDataLineInfo); + System.out.println("SourceDataLine: "+sourceDataLine); + sourceDataLine.open(audioFormat, bufferSize); + sourceDataLine.start(); + Line.Info targetDataLineInfo = + new DataLine.Info(TargetDataLine.class,audioFormat); + TargetDataLine targetDataLine = + (TargetDataLine) AudioSystem.getLine(targetDataLineInfo); + System.out.println("TargetDataLine: "+targetDataLine); + targetDataLine.open(audioFormat, bufferSize); + targetDataLine.start(); + byte[] data = new byte[bufferSize]; + + // execute for 20 seconds + float bufferTime = (((float) data.length) / audioFormat.getFrameSize()) / audioFormat.getFrameRate(); + int count = (int) (20.0f / bufferTime); + System.out.println("Buffer time: "+(bufferTime * 1000)+" millis. "+count+" iterations."); + for (int i = 0; i < count; i++) { + int cnt = targetDataLine.read(data,0,data.length); + sourceDataLine.write(data,0,cnt); + assert cnt == data.length; + } + System.out.println("Successfully recorded/played "+count+" buffers. Passed"); + } catch(LineUnavailableException lue) { + System.out.println("Audio hardware is not available!"); + lue.printStackTrace(); + System.out.println("Cannot execute test. NOT failed."); + } catch(IllegalArgumentException iae) { + System.out.println("No audio hardware is installed!"); + iae.printStackTrace(); + System.out.println("Test system not correctly setup."); + System.out.println("Cannot execute test. NOT failed."); + } catch(Exception e) { + System.out.println("Unexpected Exception: "+e); + e.printStackTrace(); + System.out.println("Cannot execute test. NOT failed."); + } + } +} diff --git a/test/javax/sound/sampled/Mixers/NoSimpleInputDevice.java b/test/javax/sound/sampled/Mixers/NoSimpleInputDevice.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/NoSimpleInputDevice.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4936397 + * @summary Verify that there'll be either SimpleInputDevice OR DirectAudioDevice + */ +public class NoSimpleInputDevice { + + public static void main(String[] args) throws Exception { + out("4936397: Verify that there'll be either SimpleInputDevice OR DirectAudioDevice"); + boolean foundSimpleInputDevice = false; + boolean foundDirectAudioDevice = false; + + Mixer.Info[] aInfos = AudioSystem.getMixerInfo(); + for (int i = 0; i < aInfos.length; i++) { + try { + Mixer mixer = AudioSystem.getMixer(aInfos[i]); + String mixerClass = mixer.getClass().toString(); + if (mixerClass.indexOf("SimpleInputDevice") >= 0) { + out("Found SimpleInputDevice: "+aInfos[i]); + foundSimpleInputDevice = true; + } + if (mixerClass.indexOf("DirectAudioDevice") >= 0) { + out("Found DirectAudioDevice: "+aInfos[i]); + foundDirectAudioDevice = true; + } + } catch (Exception e) { + out("Unexpected exception: "+e); + } + } + if (aInfos.length == 0) { + out("[No mixers available] - cannot exercise this test."); + } else { + if (foundSimpleInputDevice && foundDirectAudioDevice) { + out("Found both types of capture devices!"); + throw new Exception("Test FAILED!"); + } + out("Did not find both types of capture devices. Test passed"); + } + } + + static void out(String s) { + System.out.println(s); System.out.flush(); + } +} diff --git a/test/javax/sound/sampled/Mixers/PhantomMixers.java b/test/javax/sound/sampled/Mixers/PhantomMixers.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/PhantomMixers.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.TargetDataLine; + +/** + * @test + * @bug 4794104 + * @summary mixers are always present, independent of available soundcards + * @run main/manual PhantomMixers + */ +public class PhantomMixers { + + public static void main(String args[]) throws Exception { + int SDLformats = 0; + int TDLformats = 0; + Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); + for(int i=0; i " + (srcLineInfo.length + dstLineInfo.length) + " line"); + switch (count) { + case 0: System.out.println("s"); break; + case 1: System.out.println(""); break; + default: System.out.println("s:"); break; + } + int l; + for (l = 0; l < srcLineInfo.length; l++) { + System.out.println(" "+srcLineInfo[l].toString()); + if (srcLineInfo[l].getLineClass() == SourceDataLine.class + && (srcLineInfo[l] instanceof DataLine.Info)) { + SDLformats += ((DataLine.Info) srcLineInfo[l]).getFormats().length; + } + } + for (l = 0; l < dstLineInfo.length; l++) { + System.out.println(" "+dstLineInfo[l].toString()); + if (dstLineInfo[l].getLineClass() == TargetDataLine.class + && (dstLineInfo[l] instanceof DataLine.Info)) { + TDLformats += ((DataLine.Info) dstLineInfo[l]).getFormats().length; + } + } + } + if (mixerInfo.length == 0) { + System.out.println("[no mixers present]"); + } + System.out.println(""+SDLformats+" total formats for SourceDataLines"); + System.out.println(""+TDLformats+" total formats for TargetDataLines"); + System.out.println(""); + System.out.println("If there are audio devices correctly installed on your"); + System.out.println("system, you should see at least one Mixer, and in total"); + System.out.println("at least each one SourceDataLine and TargetDataLine, both"); + System.out.println("providing at least one format."); + System.out.println(""); + System.out.println("Now disable your soundcard and repeat the test."); + System.out.println("The corresponding mixer(s) should not provide any formats"); + System.out.println("anymore. If you disable all available soundcards"); + System.out.println("on your computer, the number of formats above should be"); + System.out.println("0 for both line types (although mixers are allowed to exist)."); + } +} diff --git a/test/javax/sound/sampled/Mixers/PlugHwMonoAnd8bitAvailable.java b/test/javax/sound/sampled/Mixers/PlugHwMonoAnd8bitAvailable.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/PlugHwMonoAnd8bitAvailable.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 5013897 + * @summary Verify that plughw: provides mono and 8-bit lines + */ +public class PlugHwMonoAnd8bitAvailable { + static int failed = 0; + static int testedFormats = 0; + + public static void main(String[] args) throws Exception { + out("5013897: Verify that plughw: provides mono and 8-bit lines"); + + Mixer.Info[] aInfos = AudioSystem.getMixerInfo(); + for (int i = 0; i < aInfos.length; i++) { + try { + Mixer mixer = AudioSystem.getMixer(aInfos[i]); + out("Mixer "+aInfos[i]); + if (aInfos[i].getName().contains("plughw")) { + checkLines(mixer, mixer.getSourceLineInfo()); + checkLines(mixer, mixer.getTargetLineInfo()); + } else { + out(" -> not plughw, ignored."); + } + } catch (Exception e) { + out("Unexpected exception when getting a mixer: "+e); + } + } + if (testedFormats == 0) { + out("[No appropriate lines available] - cannot exercise this test."); + } else { + if (failed>0) { + throw new Exception("Test FAILED!"); + } + out("Successfully verified "+testedFormats+" formats."); + out("Test passed"); + } + } + + public static void checkLines(Mixer mixer, Line.Info[] infos) { + for (int i = 0; i 16) { + // if a bit size larger than 16 is available, also 16-bit must be there + checkFormat(formats, getOtherBits(formats[f], 16)); + } else + if (formats[f].getSampleSizeInBits() > 8) { + // if a bit size larger than 8 is available, also 8-bit must be there + checkFormat(formats, getOtherBits(formats[f], 8)); + } + if (formats[f].getChannels() > 2) { + // if more than 2 channels, also 2 channels must be there + checkFormat(formats, getOtherChannels(formats[f], 2)); + } else + if (formats[f].getChannels() > 1) { + // if more than 1 channel, also 1 channel must be there + checkFormat(formats, getOtherChannels(formats[f], 1)); + } + } catch (Exception e1) { + out(" Unexpected exception when getting a format: "+e1); + } + } + } + if (testedFormats - thisTestedFormats == 0) { + out(" -->could not test any formats"); + } else if (failed - thisFailed == 0) { + out(" -->"+(testedFormats - thisTestedFormats)+" formats tested OK"); + } + + } else { + out(" --> not a DataLine"); + } + } catch (Exception e) { + out(" Unexpected exception when getting a line: "+e); + } + } + } + + public static void checkFormat(AudioFormat[] formats, AudioFormat format) { + testedFormats++; + for (int i = 0; i < formats.length; i++) { + if (formats[i].matches(format)) { + return; + } + } + out(" ## expected this format: "+format + +" ("+format.getChannels()+" channels, " + +"frameSize="+format.getFrameSize()+", " + +(format.isBigEndian()?"big endian":"little endian") + +")"); + failed++; + } + + // only works for PCM encodings + public static AudioFormat getOtherBits(AudioFormat format, int newBits) { + boolean isSigned = format.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED); + return new AudioFormat(format.getSampleRate(), + newBits, + format.getChannels(), + isSigned, + (newBits>8)?format.isBigEndian():false); + } + + // only works for PCM encodings + public static AudioFormat getOtherChannels(AudioFormat format, int newChannels) { + int newFrameSize; + if (newChannels <= 0 || format.getChannels() <= 0 || format.getFrameSize() <= 0) { + newFrameSize = -1; + } else { + newFrameSize = format.getFrameSize() / format.getChannels() * newChannels; + } + return new AudioFormat(format.getEncoding(), + format.getSampleRate(), + format.getSampleSizeInBits(), + newChannels, + newFrameSize, + format.getFrameRate(), + format.isBigEndian()); + } + + + static void out(String s) { + System.out.println(s); System.out.flush(); + } +} diff --git a/test/javax/sound/sampled/Mixers/UnexpectedIAE.java b/test/javax/sound/sampled/Mixers/UnexpectedIAE.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/Mixers/UnexpectedIAE.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2004, 2016, 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. + */ + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; + +/** + * @test + * @bug 4964288 + * @summary Unexpected IAE raised while getting TargetDataLine + */ +public class UnexpectedIAE { + + public static void main(String argv[]) throws Exception { + boolean success = true; + + Mixer.Info [] infos = AudioSystem.getMixerInfo(); + + for (int i=0; i 100) { + inLine.close(); + System.out.println("TargetDataLine does not support buffer size of "+bufferSize+" bytes!"); + return false; + }*/ + bufferSize = inLine.getBufferSize(); + /* 3/4 of buffer size ot wait */ + WAIT_MILLIS = (int) (bufferSize / format.getFrameSize() * 750 / format.getFrameRate()); + System.out.println("Buffer size: "+bufferSize+" bytes = " + +((int) (bufferSize / format.getFrameSize() * 750 / format.getFrameRate()))+" millis"); + return true; + } + + private String available() { + int avail = inLine.available(); + int availMillis = (int) (avail / format.getFrameSize() * 1000 / format.getFrameRate()); + return "available "+avail+" bytes = "+availMillis+" millis"; + } + + private boolean recordSound(int num) throws LineUnavailableException { + if (!openInputLine(num)) { + return false; + } + byte data[] = new byte[1000]; + try { + System.out.println("Got line: "+inLine); + System.out.println("Start recording" ); + inLine.start(); + System.out.print("Warm-up..."); + //System.out.print("Waiting 500 millis..."); + try { Thread.sleep(500); } catch (InterruptedException ie) {} + //System.out.println("done. "+available()); + //System.out.print("Reading all data..."); + int avail0 = inLine.available(); + if (avail0 == 0) { + System.out.println("Problem: TargetDataLine did not deliver any data!"); + System.out.println("Not a test failure, but serious failure nonetheless."); + } else { + while ((avail0 -= inLine.read(data, 0, Math.min(data.length, avail0))) > 0); + System.out.println("done. "+available()); + System.out.print("Waiting "+(WAIT_MILLIS)+" millis..."); + try { Thread.sleep(WAIT_MILLIS); } catch (InterruptedException ie) {} + int avail1 = inLine.available(); + System.out.println("done. "+available()); + + System.out.print("Flushing..."); + inLine.flush(); + System.out.println("done. "+available()); + System.out.print("Waiting "+(WAIT_MILLIS)+" millis..."); + try { Thread.sleep(WAIT_MILLIS); } catch (InterruptedException ie) {} + int avail2 = inLine.available(); + System.out.println("done. "+available()); + if (avail2 > avail1) { + failed = true; + System.out.println("Failed: Flushing with native flush() should " + +"result in fewer bytes available."); + } + if (avail2 == 0) { + failed = true; + System.out.println("Failed: Recording after flush() did not work at all!"); + } + } + } finally { + System.out.print("Closing line...."); + inLine.close(); + System.out.println("done"); + } + return true; + } + + public void runTests(int testRuns) { + if (mixers.length > 0) { + for (int num = -1; num < mixers.length; num++) { + try { + if (num<0) { + System.out.println("------Using default line...." ); + } else { + System.out.println("------Using line "+num+" from mixer "+mixers[num]+"..."); + } + for (int testRun = 0; testRun < testRuns; testRun++) { + if (testRuns>1) { + System.out.println("--Run "+(testRun+1)+"/"+testRuns+":"); + } + if (!recordSound(num)) { + break; + } + } + } catch (Exception ex) { + System.out.println("Caught " + ex ); + } + System.out.println("------------------------------------------------------"); + if (failed) { + break; + } + } + } else { + System.out.println("No mixers present. Cannot execute this test."); + } + } + + + public static void main(String[] args) throws Exception { + System.out.println("Test TargetDataLineFlush"); + System.out.println("This verifies that TargetDataLine.flush() actually"); + System.out.println("flushes the native buffers. This is done by"); + System.out.println("comparing a manual flush (i.e. just discarding"); + System.out.println("everything that is currently available in the TargetDataLine)"); + System.out.println("to a flushed line"); + TargetDataLineFlush app = new TargetDataLineFlush(); + int testRuns = 1; + if (args.length > 0) { + try { + testRuns = Integer.parseInt(args[0]); + } catch (NumberFormatException nfe) { + System.out.println("Usage: java TargetDataLineFlush [number of runs]"); + System.out.println("Parameters ignored."); + } + } + app.runTests(testRuns); + if (failed) { + throw new Exception("Test FAILED"); + } + // test always passes if it gets here + System.out.println("Test PASSED"); + } +} diff --git a/test/javax/sound/sampled/spi/AudioFileReader/AIFFCp037.java b/test/javax/sound/sampled/spi/AudioFileReader/AIFFCp037.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileReader/AIFFCp037.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4369044 + * @summary javax.sound.sampled.AudioSystem.getAudioInputStream() works wrong + * with Cp037 + */ +public class AIFFCp037 { + + public static void main(String args[]) throws Exception { + System.setProperty("file.encoding", "Cp037"); + // try to read this file with Cp037 encoding + AudioSystem.getAudioInputStream(new ByteArrayInputStream(SHORT_AIFF)); + System.out.println(" test passed."); + } + + public static String getString(byte b) { + //String res = Integer.toHexString(b & 0xFF).toUpperCase(); + //while (res.length()<2) res="0"+res; + //return res; + return String.valueOf(b); + } + + + public static void printFile(String filename) throws Exception { + File file = new File(filename); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + fis.read(data); + String s = ""; + for (int i=0; i72) { + System.out.println(s); + s=""; + } + } + System.out.println(s); + } + + public static byte[] SHORT_AIFF = { + 70, 79, 82, 77, 0, 0, 4, -54, 65, 73, 70, 70, 67, 79, 77, 77, 0, 0, 0, 18, + 0, 1, 0, 0, 2, 78, 0, 16, 64, 12, -84, 68, 0, 0, 0, 0, 0, 0, 83, 83, 78, + 68, 0, 0, 4, -92, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -2, 0, -2, 0, 0, 0, 0, 0, + -3, 0, -5, 0, -2, 0, 3, 0, 1, 0, -3, 0, -5, 0, -6, 0, -6, 0, -5, 0, -2, 0, + -2, 0, -5, 0, -6, 0, -3, 0, 0, 0, 0, 0, -3, 0, -5, 0, -6, 0, -8, 0, -5, 0, + 1, 0, 4, 0, 1, 0, -5, 0, -8, 0, -3, 0, 3, 0, 4, 0, 0, 0, -8, 0, -11, 0, -8, + 0, -3, 0, 0, 0, 0, 0, 1, 0, 0, 0, -5, 0, -9, 0, -8, 0, 0, 0, 6, 0, 7, 0, + 0, 0, -8, 0, -11, 0, -8, 0, 0, 0, 4, 0, 6, 0, 3, 0, -2, 0, -5, 0, -5, 0, + 0, 0, 6, 0, 6, 0, 1, 0, -5, 0, -3, 0, 1, 0, 6, 0, 6, 0, 1, 0, -3, 0, -3, + 0, 0, 0, 3, 0, 3, 0, 0, 0, -3, 0, -2, 0, 3, 0, 6, 0, 4, 0, 0, 0, -2, 0, -2, + 0, 1, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -3, 0, 1, 0, 6, + 0, 6, 0, 1, 0, 0, 0, 1, 0, 0, 0, -2, 0, -2, 0, 3, 0, 4, 0, 0, 0, -5, 0, -3, + 0, 1, 0, 4, 0, 4, 0, 0, 0, -2, 0, 1, 0, 1, 0, -2, 0, -6, 0, -6, 0, -2, 0, + 6, 0, 7, 0, 4, 0, 0, 0, -5, 0, -6, 0, -5, 0, 0, 0, 4, 0, 4, 0, 0, 0, -5, + 0, -8, 0, -8, 0, -5, 0, 1, 0, 3, 0, 1, 0, -3, 0, -6, 0, -6, 0, -5, 0, -5, + 0, -3, 0, 1, 0, 3, 0, 1, 0, -2, 0, -5, 0, -5, 0, -5, 0, -3, 0, 3, 0, 6, 0, + 6, 0, 0, 0, -3, 0, -3, 0, 0, 0, 1, 0, 0, 0, 3, 0, 4, 0, 0, 0, -3, 0, -5, + 0, -2, 0, 1, 0, -2, 0, -2, 0, 1, 0, 4, 0, 1, 0, -3, 0, -2, 0, 0, 0, 0, 0, + -3, 0, -6, 0, -5, 0, 0, 0, 3, 0, 0, 0, -3, 0, -5, 0, -5, 0, -2, 0, -2, 0, + -5, 0, -6, 0, -3, 0, 1, 0, 1, 0, -2, 0, -8, 0, -8, 0, -3, 0, 1, 0, 3, 0, + 1, 0, -5, 0, -8, 0, -6, 0, -2, 0, 3, 0, 4, 0, -2, 0, -5, 0, -6, 0, -3, 0, + -2, 0, -2, 0, -2, 0, -2, 0, -3, 0, -5, 0, -6, 0, -5, 0, -2, 0, 0, 0, 0, 0, + -2, 0, -3, 0, -5, 0, -5, 0, -3, 0, -3, 0, -2, 0, -2, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 1, 0, -2, 0, -5, 0, -3, 0, 1, 0, 4, 0, 6, 0, 4, 0, 1, 0, 0, 0, + 0, 0, 3, 0, 4, 0, 1, 0, -3, 0, -3, 0, 1, 0, 6, 0, 4, 0, 1, 0, -3, 0, -5, + 0, -2, 0, 3, 0, 6, 0, 7, 0, 1, 0, -5, 0, -5, 0, 1, 0, 7, 0, 6, 0, 3, 0, 1, + 0, -2, 0, -5, 0, -5, 0, -2, 0, 3, 0, 3, 0, 3, 0, 0, 0, -3, 0, -5, 0, -3, + 0, 0, 0, 6, 0, 9, 0, 4, 0, -2, 0, -6, 0, -5, 0, -2, 0, 3, 0, 4, 0, 3, 0, + -2, 0, -6, 0, -3, 0, 1, 0, 3, 0, -3, 0, -6, 0, 0, 0, 4, 0, 1, 0, -6, 0, -9, + 0, -5, 0, 1, 0, 1, 0, 0, 0, -2, 0, -3, 0, -5, 0, -6, 0, -5, 0, 0, 0, 3, 0, + 3, 0, -2, 0, -6, 0, -6, 0, -3, 0, -2, 0, -2, 0, -5, 0, -6, 0, -5, 0, -2, + 0, 0, 0, -2, 0, -3, 0, -3, 0, -3, 0, -2, 0, 0, 0, 1, 0, 0, 0, -2, 0, -2, + 0, -3, 0, -5, 0, -5, 0, -2, 0, 0, 0, 3, 0, 3, 0, 0, 0, -3, 0, -3, 0, 0, 0, + -2, 0, -5, 0, -3, 0, 0, 0, 1, 0, -3, 0, -8, 0, -6, 0, -2, 0, -2, 0, -6, 0, + -6, 0, -5, 0, -3, 0, -3, 0, -6, 0, -6, 0, -3, 0, -3, 0, -3, 0, -3, 0, 0, + 0, 1, 0, -3, 0, -6, 0, -3, 0, 1, 0, 0, 0, -6, 0, -9, 0, -9, 0, -6, 0, -2, + 0, 1, 0, 3, 0, -3, 0, -5, 0, -3, 0, -2, 0, -3, 0, -6, 0, -5, 0, -2, 0, -2, + 0, -5, 0, -5, 0, -2, 0, -2, 0, -5, 0, -6, 0, -6, 0, -2, 0, -2, 0, -2, 0, + -3, 0, -5, 0, -5, 0, -3, 0, 1, 0, 0, 0, 1, 0, 1, 0, 3, 0, 6, 0, 6, 0, 3, + 0, -6, 0, -12, 0, -8, 0, 1, 0, 9, 0, 7, 0, 1, 0, -3, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 3, 0, 6, 0, 7, 0, 3, 0, -3, 0, -5, 0, 0, 0, 4, 0, 4, 0, 3, 0, 1, 0, + 3, 0, 3, 0, 0, 0, -2, 0, 0, 0, 1, 0, 1, 0, 1, 0, 3, 0, 3, 0, 1, 0, 0, 0, + 0, 0, 3, 0, 1, 0, -2, 0, -2, 0, 1, 0, 1, 0, -3, 0, -3, 0, 0, 0, 4, 0, 6, + 0, 6, 0, 3, 0, -3, 0, -8, 0, -5, 0, 1, 0, 3, 0, 1, 0, 1, 0, 0, 0, -3, 0, + -6, 0, -5, 0, 1, 0, 3, 0, -2, 0, -3, 0, 0, 0, 1, 0, 1, 0, -3, 0, -5, 0, -2, + 0, -2, 0, -2, 0, 0, 0, 1, 0, 1, 0, -2, 0, -5, 0, -8, 0, -6, 0, -5, 0, -2, + 0, 1, 0, 0, 0, -5, 0, -6, 0, 0, 0, 4, 0, 1, 0, -5, 0, -5, 0, -3, 0, -2, 0, + -3, 0, -3, 0, 0, 0, 0, 0, -2, 0, -3, 0, -2, 0, 1, 0, -2, 0, -5, 0, -3, 0, + 0, 0, 3, 0, 0, 0, -3, 0, -3, 0, -3, 0, -3, 0, -3, 0, 0, 0, 3, 0, 4, 0, -2, + 0, -8, 0, -8, 0, -5, 0, 3, 0, 3, 0, -2, 0, -6, 0, -8, 0, -3, 0, 1, 0, 0, + 0, -5, 0, -5, 0, -2, 0, -2, 0, -3, 0, -5, 0, -3, 0, 0, 0, 0, 0, -2, 0, -5, + 0, -6, 0, -5, 0, -3, 0, 0, 0, 0, 0, -3, 0, -3, 0, -5, 0, -5, 0, -6, 0, -6, + 0, -6, 0, -5, 0, 0, 0, 1, 0, 0, 0, -5, 0, -6, 0, -5, 0, -2, 0, -2, 0, -3, + 0, -5, 0, -8, 0, -9, 0, -6, 0, -2, 0, 0, 0, -2, 0, -5, 0, -5, 0, -2, 0, 3, + 0, 4, 0, 0, 0, -2, 0, -2, 0, 1, 0, 1, 0, 1, 0, 3, 0 + }; + +} diff --git a/test/javax/sound/sampled/spi/AudioFileReader/AIFFLargeHeader.java b/test/javax/sound/sampled/spi/AudioFileReader/AIFFLargeHeader.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileReader/AIFFLargeHeader.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4399551 + * @summary Repost of bug candidate: cannot replay aif file. AIFF headers were + * checked for certain size also tests that ulaw encoded AIFC files can + * be read. + */ +public class AIFFLargeHeader { + + public static void main(String args[]) throws Exception { + System.out.println(); + System.out.println(); + System.out.println("4399551: Repost of bug candidate: cannot replay aif file (Review ID: 108108)"); + // try to read this file + AudioSystem.getAudioInputStream(new ByteArrayInputStream(SHORT_AIFC_ULAW)); + System.out.println(" test passed."); + } + + public static String getString(byte b) { + //String res = Integer.toHexString(b & 0xFF).toUpperCase(); + //while (res.length()<2) res="0"+res; + //return res; + return String.valueOf(b); + } + + + public static void printFile(String filename) throws Exception { + File file = new File(filename); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + fis.read(data); + String s = ""; + for (int i=0; i72) { + System.out.println(s); + s=""; + } + } + System.out.println(s); + } + + public static byte[] SHORT_AIFC_ULAW = { + 70, 79, 82, 77, 0, 0, 2, 50, 65, 73, 70, 67, 70, 86, 69, 82, 0, 0, 0, 4, + -94, -128, 81, 64, 67, 79, 77, 77, 0, 0, 0, 30, 0, 1, 0, 1, 118, -9, 0, 16, + 64, 12, -84, 68, 0, 0, 0, 0, 0, 0, 117, 108, 97, 119, 7, 117, 110, 107, 110, + 111, 119, 110, 83, 83, 78, 68, 0, 0, 1, -13, 0, 0, 0, 0, 0, 0, 0, 0, 103, + 103, 103, -1, -1, 91, 77, 103, -45, -25, 91, 77, 73, 73, 77, 103, 103, 77, + 73, 91, -1, -1, 91, 77, 73, 65, 77, -25, -51, -25, 77, 65, 91, -45, -51, + -1, 65, 58, 65, 91, -1, -1, -25, -1, 77, 62, 65, -1, -59, -63, -1, 65, 58, + 65, -1, -51, -59, -45, 103, 77, 77, -1, -59, -59, -25, 77, 91, -25, -59, + -59, -25, 91, 91, -1, -45, -45, -1, 91, 103, -45, -59, -51, -1, 103, 103, + -25, -25, -45, -45, -1, -1, -1, -1, 103, 91, -25, -59, -59, -25, -1, -25, + -1, 103, 103, -45, -51, -1, 77, 91, -25, -51, -51, -1, 103, -25, -25, 103, + 73, 73, 103, -59, -63, -51, -1, 77, 73, 77, -1, -51, -51, -1, 77, 65, 65, + 77, -25, -45, -25, 91, 73, 73, 77, 77, 91, -25, -45, -25, 103, 77, 77, 77, + 91, -45, -59, -59, -1, 91, 91, -1, -25, -1, -45, -51, -1, 91, 77, 103, -25, + 103, 103, -25, -51, -25, 91, 103, -1, -1, 91, 73, 77, -1, -45, -1, 91, 77, + 77, 103, 103, 77, 73, 91, -25, -25, 103, 65, 65, 91, -25, -45, -25, 77, 65, + 73, 103, -45, -51, 103, 77, 73, 91, 103, 103, 103, 103, 91, 77, 73, 77, 103, + -1, -1, 103, 91, 77, 77, 91, 91, 103, 103, -1, -25, -25, -1, -25, -25, 103, + 77, 91, -25, -51, -59, -51, -25, -1, -1, -45, -51, -25, 91, 91, -25, -59, + -51, -25, 91, 77, 103, -45, -59, -63, -25, 77, 77, -25, -63, -59, -45, -25, + 103, 77, 77, 103, -45, -45, -45, -1, 91, 77, 91, -1, -59, -68, -51, 103, + 73, 77, 103, -45, -51, -45, 103, 73, 91, -25, -45, 91, 73, -1, -51, -25, + 73, 62, 77, -25, -25, -1, 103, 91, 77, 73, 77, -1, -45, -45, 103, 73, 73, + 91, 103, 103, 77, 73, 77, 103, -1, 103, 91, 91, 91, 103, -1, -25, -1, 103, + 103, 91, 77, 77, 103, -1, -45, -45, -1, 91, 91, -1, 103, 77, 91, -1, -25, + 91, 65, 73, 103, 103, 73, 73, 77, 91, 91, 73, 73, 91, 91, 91, 91, -1, -25, + 91, 73, 91, -25, -1, 73, 62, 62, 73, 103, -25, -45, 91, 77, 91, 103, 91, + 73, 77, 103, 103, 77, 77, 103, 103, 77, 73, 73, 103, 103, 103, 91, 77, 77, + 91, -25, -1, -25, -25, -45, -59, -59, -45, 73, 56, 65, -25, -68, -63, -25, + 91, -1, -45, -1, -1, -45, -59, -63, -1, 103, 103, -25, -25, 103, 91, -1, + -45, -51, -25, 103, 91, 91, 103, -25, -25, -25, 103, 73, 77, -1, -51, -45, + 103, 91, 103, -25, -1, 91, 91, 91, -1, -45, -51, -25, 91, 77, 103, -1, -1, + 91, -1, -1, -1, 103, 91, 91, 73, 77, 103, -25, -25, 103, 91, 103, 103, 103, + -1, -45, -1, 77, 77, -1 + }; + +} diff --git a/test/javax/sound/sampled/spi/AudioFileReader/Aiff12bit.java b/test/javax/sound/sampled/spi/AudioFileReader/Aiff12bit.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileReader/Aiff12bit.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4895934 + * @summary AudioInputStream.getFrameLength returns wrong value for 12-bit AIFF + * file + */ +public class Aiff12bit { + + public static void test(byte[] file) throws Exception { + InputStream inputStream = new ByteArrayInputStream(file); + AudioFileFormat aff = AudioSystem.getAudioFileFormat(inputStream); + + if (aff.getFormat().getSampleSizeInBits() != 12) { + throw new Exception("Wrong sample size. test FAILED"); + } + if (aff.getFormat().getFrameSize() != 2) { + throw new Exception("Wrong frame size. test FAILED"); + } + if (aff.getFrameLength() != 100) { + throw new Exception("Wrong file length. test FAILED"); + } + } + + public static void main(String[] args) throws Exception { + test(AIFF_12BIT); + + System.out.println("Test passed."); + } + + public static byte[] AIFF_12BIT = { + 70, 79, 82, 77, 0, 0, 0, -10, 65, 73, 70, 70, 67, 79, 77, 77, + 0, 0, 0, 18, 0, 1, 0, 0, 0, 100, 0, 12, 64, 8, -6, 0, + 0, 0, 0, 0, 0, 0, 83, 83, 78, 68, 0, 0, 0, -48, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 32, 0, 48, 0, 64, + 0, 80, 0, 96, 0, 112, 0, -128, 0, -112, 0, -96, 0, -80, 0, -64, + 0, -48, 0, -32, 0, -16, 1, 0, 1, 16, 1, 32, 1, 48, 1, 64, + 1, 80, 1, 96, 1, 112, 1, -128, 1, -112, 1, -96, 1, -80, 1, -64, + 1, -48, 1, -32, 1, -16, 2, 0, 2, 16, 2, 32, 2, 48, 2, 64, + 2, 80, 2, 96, 2, 112, 2, -128, 2, -112, 2, -96, 2, -80, 2, -64, + 2, -48, 2, -32, 2, -16, 3, 0, 3, 16, 3, 32, 3, 48, 3, 64, + 3, 80, 3, 96, 3, 112, 3, -128, 3, -112, 3, -96, 3, -80, 3, -64, + 3, -48, 3, -32, 3, -16, 4, 0, 4, 16, 4, 32, 4, 48, 4, 64, + 4, 80, 4, 96, 4, 112, 4, -128, 4, -112, 4, -96, 4, -80, 4, -64, + 4, -48, 4, -32, 4, -16, 5, 0, 5, 16, 5, 32, 5, 48, 5, 64, + 5, 80, 5, 96, 5, 112, 5, -128, 5, -112, 5, -96, 5, -80, 5, -64, + 5, -48, 5, -32, 5, -16, 6, 0, 6, 16, 6, 32, 6, 48, + }; + +} diff --git a/test/javax/sound/sampled/spi/AudioFileReader/AuNotSpecified.java b/test/javax/sound/sampled/spi/AudioFileReader/AuNotSpecified.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileReader/AuNotSpecified.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4940459 + * @summary AudioInputStream.getFrameLength() returns 0 instead of NOT_SPECIFIED + */ +public class AuNotSpecified { + public static boolean failed = false; + + public static void main(String[] params) throws Exception { + + AudioInputStream is = + AudioSystem.getAudioInputStream(new + ByteArrayInputStream(new byte[] { + (byte)0x2E, (byte)0x73, (byte)0x6E, (byte)0x64, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x18, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x03, + (byte)0x00, (byte)0x00, (byte)0x1F, (byte)0x40, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, + })); + if (is.getFrameLength() != AudioSystem.NOT_SPECIFIED) { + System.out.println("frame length should be NOT_SPECIFIED, but is: "+is.getFrameLength()); + failed=true; + } + //assertTrue(is.getFrameLength() == AudioSystem.NOT_SPECIFIED); + //assertTrue(is.read(new byte[8]) == 8); + //assertTrue(is.read(new byte[2]) == -1); + if (failed) throw new Exception("Test FAILED!"); + System.out.println("Test Passed."); + } +} diff --git a/test/javax/sound/sampled/spi/AudioFileReader/AuZeroLength.java b/test/javax/sound/sampled/spi/AudioFileReader/AuZeroLength.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileReader/AuZeroLength.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4629669 + * @summary AU file reader: problems with empty files + */ +public class AuZeroLength { + + public static String getString(byte b) { + //String res = Integer.toHexString(b & 0xFF).toUpperCase(); + //while (res.length()<2) res="0"+res; + //return res; + return String.valueOf(b); + } + + + public static void printFile(String filename) throws Exception { + File file = new File(filename); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + fis.read(data); + String s = ""; + for (int i=0; i72) { + System.out.println(s); + s=""; + } + } + System.out.println(s); + } + + public static void test(byte[] file) throws Exception { + InputStream inputStream = new ByteArrayInputStream(file); + AudioFileFormat aff = AudioSystem.getAudioFileFormat(inputStream); + + if (aff.getFrameLength() != 0) { + throw new Exception("File length is "+aff.getFrameLength()+" instead of 0. test FAILED"); + } + System.out.println(aff.getType()+" file length is 0."); + } + + public static void main(String[] args) throws Exception { + test(ZERO_AU); + test(ZERO_WAV); + test(ZERO_AIFF); + + System.out.println("Test passed."); + } + + public static byte[] ZERO_AU = { + 46, 115, 110, 100, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, -84, 68, 0, + 0, 0, 1, 116, 101, 115, 116, 46, 119, 97, 118 + }; + + public static byte[] ZERO_WAV = { + 82, 73, 70, 70, 36, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, + 0, 1, 0, 1, 0, 68, -84, 0, 0, -120, 88, 1, 0, 2, 0, 16, 0, 100, 97, 116, + 97, 0, 0, 0, 0 + }; + + public static byte[] ZERO_AIFF = { + 70, 79, 82, 77, 0, 0, 0, 46, 65, 73, 70, 70, 67, 79, 77, 77, 0, 0, 0, 18, + 0, 1, 0, 0, 0, 0, 0, 16, 64, 14, -84, 68, 0, 0, 0, 0, 0, 0, 83, 83, 78, 68, + 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0 + }; + +} diff --git a/test/javax/sound/sampled/spi/AudioFileReader/OpenWaveFile.java b/test/javax/sound/sampled/spi/AudioFileReader/OpenWaveFile.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileReader/OpenWaveFile.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4489272 + * @summary AudioSystem.getAudioFileFormat() fails for InputStream, but works + * for URL + */ +public class OpenWaveFile { + + static void check(Object source) throws Exception { + AudioFileFormat aff2 = null; + if (source instanceof File) { + aff2 = AudioSystem.getAudioFileFormat((File) source); + } + else if (source instanceof InputStream) { + aff2 = AudioSystem.getAudioFileFormat((InputStream) source); + } + else if (source instanceof URL) { + aff2 = AudioSystem.getAudioFileFormat((URL) source); + } else throw new Exception("wrong source. Test FAILED"); + System.out.println("Got: "+aff2); + if (aff2.getFormat().getSampleSizeInBits()==-1) { + throw new Exception("wrong audio format. Test FAILED"); + } + } + + public static void main(String args[]) throws Exception { + //check(new File(args[0])); + //check(new URL("file", "", args[0])); + check(new ByteArrayInputStream(SHORT_AU)); + check(new ByteArrayInputStream(SHORT_WAVE)); + check(new ByteArrayInputStream(SHORT_AIFF)); + System.out.println("Test passed."); + + //printFile(args[0]); + } + + public static String getString(byte b) { + //String res = Integer.toHexString(b & 0xFF).toUpperCase(); + //while (res.length()<2) res="0"+res; + //return res; + return String.valueOf(b); + } + + + public static void printFile(String filename) throws Exception { + File file = new File(filename); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + fis.read(data); + String s = ""; + for (int i=0; i72) { + System.out.println(s); + s=""; + } + } + System.out.println(s); + } + + public static byte[] SHORT_WAVE = { + 82, 73, 70, 70, -120, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, + 0, 0, 1, 0, 1, 0, 34, 86, 0, 0, 34, 86, 0, 0, 1, 0, 8, 0, 100, 97, 116, 97, + 100, 0, 0, 0, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, -128, 127, 127, -128, 127, + 127, 127, -128, -128, -128, -128, 127, 127, -128, -128, 127, -128, -128, + -128, 127, 127, 127, -128, -128, -128, 127, 127, 127, 127, -128, -128, -128, + -128, -128, -128, 127, 127, 127, -128, -128, -128, -128, -128, 127, -128, + -128, 127, -128, -128, 127, 127, -128, -128, 127, 127, -128, -128, -128, + -128, -128, 127, 127, -128, -128, -128, 127, 127, 127, -128, 127, -128, -128, + 127, 127, 127, -128, -128, -128, 127, 127, -128, -128, + }; + + public static byte[] SHORT_AU = { + 46, 115, 110, 100, 0, 0, 0, 24, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 86, 34, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + 0, -1, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0, -1, 0, 0, 0, -1, -1, -1, 0, 0, 0, + -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, -1, + 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, -1, -1, -1, 0, + -1, 0, 0, -1, -1, -1, 0, 0, 0, -1, -1, 0, 0, + }; + + public static byte[] SHORT_AIFF = { + 70, 79, 82, 77, 0, 0, 0, -110, 65, 73, 70, 70, 67, 79, 77, 77, 0, 0, 0, 18, + 0, 1, 0, 0, 0, 100, 0, 8, 64, 13, -84, 68, 0, 0, 0, 0, 0, 0, 83, 83, 78, + 68, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0, + -1, 0, 0, 0, -1, -1, -1, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, -1, -1, + -1, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, 0, 0, + 0, -1, -1, 0, 0, 0, -1, -1, -1, 0, -1, 0, 0, -1, -1, -1, 0, 0, 0, -1, -1, + 0, 0, + }; +} diff --git a/test/javax/sound/sampled/spi/AudioFileWriter/AUwithULAW.java b/test/javax/sound/sampled/spi/AudioFileWriter/AUwithULAW.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileWriter/AUwithULAW.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4391108 + * @summary Writing au files with ulaw encoding is broken + */ +public class AUwithULAW { + public static void main(String args[]) throws Exception { + System.out.println(); + System.out.println(); + System.out.println("4391108: Writing au files with ulaw encoding is broken"); + byte[] fakedata=new byte[1234]; + InputStream is = new ByteArrayInputStream(fakedata); + AudioFormat inFormat = new AudioFormat(AudioFormat.Encoding.ULAW, 8000, 8, 1, 1, 8000, false); + + AudioInputStream ais = new AudioInputStream(is, inFormat, fakedata.length); + + ByteArrayOutputStream out = new ByteArrayOutputStream(1500); + System.out.println(" ulaw data will be written as AU to stream..."); + int t = AudioSystem.write(ais, AudioFileFormat.Type.AU, out); + byte[] writtenData = out.toByteArray(); + is = new ByteArrayInputStream(writtenData); + System.out.println(" Get AudioFileFormat of written file"); + AudioFileFormat fileformat = AudioSystem.getAudioFileFormat(is); + AudioFileFormat.Type type = fileformat.getType(); + System.out.println(" The file format type: "+type); + if (fileformat.getFrameLength()!=fakedata.length + && fileformat.getFrameLength()!=AudioSystem.NOT_SPECIFIED) { + throw new Exception("The written file's frame length is "+fileformat.getFrameLength()+" but should be "+fakedata.length+" !"); + } + ais = AudioSystem.getAudioInputStream(is); + System.out.println(" Got Stream with format: "+ais.getFormat()); + System.out.println(" test passed."); + } +} diff --git a/test/javax/sound/sampled/spi/AudioFileWriter/AiffSampleRate.java b/test/javax/sound/sampled/spi/AudioFileWriter/AiffSampleRate.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileWriter/AiffSampleRate.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4914639 + * @summary JavaSound writes wrong sample rates to AIFF files + */ +public class AiffSampleRate { + + private static final float[] testSampleRates = + {8000.0F, 8000.0F + 0.011F, 8193.975F, 10000.0F, 11025.0F, 12000.0F, + 16000.0F, 22050.0F, 24000.0F, 32000.0F, 44100.0F - 1.22222F, 44100.0F, + 47888.888F, 48000.0F, 96000.0F, 192000.0F}; + + public static void main(String[] args) throws Exception { + boolean isTestPassed = true; + + out("#4914639: JavaSound writes wrong sample rates to AIFF files"); + for (int i = 0; i < testSampleRates.length; i++) { + isTestPassed &= testSampleRate(testSampleRates[i]); + } + if (isTestPassed) { + out("Test PASSED."); + } else { + throw new Exception("Test FAILED."); + } + } + + private static boolean testSampleRate(float sampleRate) { + boolean result = true; + + try { + // create AudioInputStream with sample rate of 10000 Hz + ByteArrayInputStream data = new ByteArrayInputStream(new byte[1]); + AudioFormat format = new AudioFormat(sampleRate, 8, 1, true, true); + AudioInputStream stream = new AudioInputStream(data, format, 1); + + // write to AIFF file + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + AudioSystem.write(stream, AudioFileFormat.Type.AIFF, outputStream); + byte[] fileData = outputStream.toByteArray(); + InputStream inputStream = new ByteArrayInputStream(fileData); + AudioFileFormat aff = AudioSystem.getAudioFileFormat(inputStream); + if (! equals(sampleRate, aff.getFormat().getFrameRate())) { + out("error for sample rate " + sampleRate); + result = false; + } + } catch (Exception e) { + out(e); + out("Test NOT FAILED"); + } + return result; + } + + private static boolean equals(float f1, float f2) { + return Math.abs(f2 - f1) < 1.0E-9; + } + + private static void out(Throwable t) { + t.printStackTrace(System.out); + } + + private static void out(String message) { + System.out.println(message); + } +} diff --git a/test/javax/sound/sampled/spi/AudioFileWriter/RIFFHeader.java b/test/javax/sound/sampled/spi/AudioFileWriter/RIFFHeader.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileWriter/RIFFHeader.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2006, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4636355 + * @summary Check that RIFF headers are written with extra data length field. + */ +public class RIFFHeader { + + public static void main(String args[]) throws Exception { + System.out.println(); + System.out.println(); + System.out.println("4636355: Check that RIFF headers are written with extra data length field."); + byte[] fakedata=new byte[1234]; + MyByteArrayInputStream is = new MyByteArrayInputStream(fakedata); + AudioFormat inFormat = new AudioFormat(AudioFormat.Encoding.ULAW, 8000, 8, 1, 1, 8000, true); + + AudioInputStream ais = new AudioInputStream((InputStream) is, inFormat, fakedata.length); + ByteArrayOutputStream out = new ByteArrayOutputStream(1500); + System.out.println(" ulaw data will be written as WAVE to stream..."); + int t = AudioSystem.write(ais, AudioFileFormat.Type.WAVE, out); + byte[] writtenData = out.toByteArray(); + // now header must have at least 46 bytes + System.out.println(" Length should be "+(fakedata.length+46)+" bytes: "+writtenData.length); + // re-read this file + is = new MyByteArrayInputStream(writtenData); + System.out.println(" Get AudioFileFormat of written file"); + AudioFileFormat fileformat = AudioSystem.getAudioFileFormat(is); + AudioFileFormat.Type type = fileformat.getType(); + System.out.println(" The file format type: "+type); + if (fileformat.getFrameLength()!=fakedata.length + && fileformat.getFrameLength()!=AudioSystem.NOT_SPECIFIED) { + throw new Exception("The written file's frame length is "+fileformat.getFrameLength()+" but should be "+fakedata.length+" !"); + } + ais = AudioSystem.getAudioInputStream(is); + System.out.println(" Got Stream with format: "+ais.getFormat()); + if (is.getPos()<46) { + throw new Exception("After reading the header, stream position must be at least 46, but is "+is.getPos()+" !"); + } + System.out.println(" test passed."); + } + + static class MyByteArrayInputStream extends ByteArrayInputStream { + + MyByteArrayInputStream(byte[] data) { + super(data); + } + + int getPos() { + return pos; + } + } +} diff --git a/test/javax/sound/sampled/spi/AudioFileWriter/WaveBigEndian.java b/test/javax/sound/sampled/spi/AudioFileWriter/WaveBigEndian.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileWriter/WaveBigEndian.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2006, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 5001952 + * @summary Writing WAVE with big endian data produces corrupt file. WAVE should + * always write signed 16-bit, little endian, regardless of the + * endianness of the input data. + */ +public class WaveBigEndian { + + static boolean failed = false; + + public static byte[] writeDataAndGetAIS(boolean bigEndian) throws Exception { + if (bigEndian) { + out("Create WAVE file from big endian data..."); + } else { + out("Create WAVE file from little endian data..."); + } + byte[] data = new byte[3000]; + for (int i = 0; i < data.length; i+=2) { + if (bigEndian) { + data[i] = (byte) i; + data[i+1] = (byte) (i+1); + } else { + data[i] = (byte) (i+1); + data[i+1] = (byte) i; + } + } + AudioFormat format = new AudioFormat(44100.0f, 16, 1, true, bigEndian); + InputStream is = new ByteArrayInputStream(data); + AudioInputStream ais = new AudioInputStream(is, format, data.length); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + int written = AudioSystem.write(ais, AudioFileFormat.Type.WAVE, os); + data = os.toByteArray(); + out("Wrote "+written+" bytes, got "+data.length+" bytes in written file."); + is = new ByteArrayInputStream(data); + ais = AudioSystem.getAudioInputStream(is); + out("Got AIS with length = "+ais.getFrameLength()+" frames."); + return data; + } + + + public static void main(String args[]) throws Exception { + byte[] data1 = writeDataAndGetAIS(false); + byte[] data2 = writeDataAndGetAIS(true); + + if (data1.length != data2.length) { + out("# data1.length != data2.length!"); + failed = true; + } else { + for (int i = 0 ; i < data1.length; i++) { + if (data1[i] != data2[i]) { + out("# At index "+i+": le="+(data1[i] & 0xFF)+" be="+(data2[i] & 0xFF)+" !"); + failed = true; + } + } + } + + if (failed) throw new Exception("Test FAILED!"); + out("Files are identical."); + out("test passed"); + } + + static void out(String s) { + System.out.println(s); + } +} diff --git a/test/javax/sound/sampled/spi/AudioFileWriter/WriteAuUnspecifiedLength.java b/test/javax/sound/sampled/spi/AudioFileWriter/WriteAuUnspecifiedLength.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/AudioFileWriter/WriteAuUnspecifiedLength.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2003, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4351296 + * @summary Cannot write AudioInputStream with unspecified length + */ +public class WriteAuUnspecifiedLength { + + public static void main(String argv[]) throws Exception { + AudioFormat format = new AudioFormat(44100, 16, 2, true, true); + InputStream is = new ByteArrayInputStream(new byte[1000]); + AudioInputStream ais = new AudioInputStream(is, format, AudioSystem.NOT_SPECIFIED); + AudioSystem.write(ais, AudioFileFormat.Type.AU, new ByteArrayOutputStream()); + System.out.println("Test passed."); + } +} diff --git a/test/javax/sound/sampled/spi/FormatConversionProvider/AlawUlaw.java b/test/javax/sound/sampled/spi/FormatConversionProvider/AlawUlaw.java new file mode 100644 --- /dev/null +++ b/test/javax/sound/sampled/spi/FormatConversionProvider/AlawUlaw.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2002, 2016, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 4714846 + * @summary JavaSound ULAW (8-bit) encoder erroneously depends on endian-ness + */ +public class AlawUlaw { + static ByteArrayInputStream in; + static int byteLength = 1000; + + static boolean failed = false; + + public static void main(String[] args) throws Exception { + // generate some random data + byte[] soundData = new byte[byteLength]; + for (int i=0; i { + p = comp.getLocationOnScreen(); + }); + } catch (IllegalStateException e) { + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + } + } + } + } + + public JTreeFocusTest() throws Exception { + SwingUtilities.invokeAndWait(() -> { + fr = new JFrame("Test"); + + root = new DefaultMutableTreeNode("root"); + JPanel p = new JPanel(); + p.setBorder(new CompoundBorder(new BevelBorder(BevelBorder.RAISED), + new LineBorder(UIManager.getColor("control"), 7))); + p.setLayout(new GridLayout(2,2)); + p.add(new JLabel("one")); + JTextField tf1 = new JTextField(10); + p.add(tf1); + p.add(new JLabel("two")); + p.add(new JTextField(10)); + root.add(new DefaultMutableTreeNode(p)); + + tf1.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + setPassed(true); + } + }); + + DefaultTreeModel model = new DefaultTreeModel(root); + tree = new JTree(model) { + public void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (e.getKeyCode()==KeyEvent.VK_F2) { + synchronized (JTreeFocusTest.this) { + keysTyped = true; + JTreeFocusTest.this.notifyAll(); + } + } + } + }; + + tree.addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + if ( root.equals(e.getPath().getLastPathComponent()) ) { + synchronized (JTreeFocusTest.this) { + rootSelected = true; + JTreeFocusTest.this.notifyAll(); + } + } + } + }); + + tree.setEditable(true); + DefaultTreeCellRenderer renderer = new FormRenderer(); + tree.setCellRenderer(renderer); + DefaultTreeCellEditor editor = new FormEditor(tree, renderer); + tree.setCellEditor(editor); + fr.getContentPane().add(tree); + + fr.setSize(300,400); + fr.setVisible(true); + }); + blockTillDisplayed(tree); + SwingUtilities.invokeAndWait(() -> { + tree.requestFocus(); + tree.setSelectionRow(0); + }); + + try { + synchronized (this) { + while (!rootSelected) { + JTreeFocusTest.this.wait(); + } + } + + robot = new Robot(); + robot.setAutoDelay(50); + robot.delay(150); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_RIGHT); + robot.keyRelease(KeyEvent.VK_RIGHT); + robot.keyPress(KeyEvent.VK_F2); + robot.keyRelease(KeyEvent.VK_F2); + + synchronized (this) { + while (!keysTyped) { + JTreeFocusTest.this.wait(); + } + } + Thread.sleep(3000); + } catch(Throwable t) { + t.printStackTrace(); + } + destroy(); + } + + public void destroy() throws Exception { + SwingUtilities.invokeAndWait(()->fr.dispose()); + if ( !isPassed() ) { + throw new RuntimeException("Focus wasn't transferred to the proper component"); + } + } + + synchronized void setPassed(boolean passed) { + this.passed = passed; + } + + synchronized boolean isPassed() { + return passed; + } + + static JTree createTree() { + return tree; + } + + class FormRenderer extends DefaultTreeCellRenderer { + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + Object obj = ((DefaultMutableTreeNode)value).getUserObject(); + if (obj instanceof Component){ + return (Component)((DefaultMutableTreeNode)value).getUserObject(); + } + return super.getTreeCellRendererComponent(tree, value, sel, + expanded, leaf, row, + hasFocus); + } + } + + class FormEditor extends DefaultTreeCellEditor { + public FormEditor(JTree tree, DefaultTreeCellRenderer renderer) { + super(tree, renderer); + } + + public Component getTreeCellEditorComponent(JTree tree, Object value, + boolean sel, + boolean expanded, + boolean leaf, int row) { + Object obj = ((DefaultMutableTreeNode)value).getUserObject(); + if (obj instanceof Component){ + return (Component)((DefaultMutableTreeNode)value).getUserObject(); + } + return super.getTreeCellEditorComponent(tree, value, sel, + expanded, leaf, row); + } + + public boolean shouldSelectCell(EventObject anEvent) { + //return super.shouldSelectCell(anEvent); + return true; + } + } +} diff --git a/test/jdk/tools/launcher/JliLaunchTest.java b/test/jdk/tools/launcher/JliLaunchTest.java new file mode 100644 --- /dev/null +++ b/test/jdk/tools/launcher/JliLaunchTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, 2020, 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. + * + */ + +import java.util.Map; +import jdk.test.lib.Utils; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class JliLaunchTest { + public static void main(String[] args) throws IOException { + Path launcher = Paths.get(System.getProperty("test.nativepath"), + "JliLaunchTest" + (Platform.isWindows() ? ".exe" : "")); + System.out.println("Launcher = " + launcher + (Files.exists(launcher) ? " (exists)" : " (not exists)")); + ProcessBuilder pb = new ProcessBuilder(launcher.toString(), "-version"); + Map env = pb.environment(); + // On windows, the DLL should be in JDK/bin, else in JDK/lib. + String libdir = Paths.get(Utils.TEST_JDK).resolve(Platform.isWindows() ? "bin" : "jre/lib/jli") + .toAbsolutePath().toString(); + String pathEnvVar = Platform.sharedLibraryPathVariableName(); + env.compute(pathEnvVar, (k, v) -> (v == null) ? libdir : libdir + File.pathSeparator + v); + + OutputAnalyzer outputf = new OutputAnalyzer(pb.start()); + outputf.shouldHaveExitValue(0); + + if (Platform.isOSX()) { + Path javaHome = Paths.get(Utils.TEST_JDK); + if (javaHome.getFileName().toString().equals("Home")) { + // To exercise this test path you need to make sure the JDK under test is + // the MacOS bundle and not the simple jdk image. This can currently be + // achieved by running something like this (from the build output dir): + // $ JDK_IMAGE_DIR=$PWD/images/j2sdk-bundle/jdk1.8.0.jdk/Contents/Home + // $ jtreg -jdk:$JDK_IMAGE_DIR $TESTROOT/jdk/tools/launcher/JliLaunchTest.sh + System.out.println("MacOS bundle distribution detected, also testing Contents/MacOS/libjli.dylib"); + String macosDir = javaHome.getParent().resolve("MacOS").toString(); + ProcessBuilder pb2 = new ProcessBuilder(launcher.toString(), "-version"); + env = pb2.environment(); + env.compute(pathEnvVar, (k, v) -> (v == null) ? macosDir : macosDir + File.pathSeparator + v); + + OutputAnalyzer output2 = new OutputAnalyzer(pb2.start()); + output2.shouldHaveExitValue(0); + } else { + System.out.println("Not a MacOS bundle distribution, not testing Contents/MacOS/libjli.dylib"); + } + } + } +} diff --git a/test/jdk/tools/launcher/JliLaunchTest.sh b/test/jdk/tools/launcher/JliLaunchTest.sh new file mode 100644 --- /dev/null +++ b/test/jdk/tools/launcher/JliLaunchTest.sh @@ -0,0 +1,33 @@ +#!/bin/bash -xe + +# @test JliLaunchTest.sh +# @bug 8238225 +# @library /lib +# @build JliLaunchTest +# @run shell JliLaunchTest.sh + +OS=`uname -s` +if [ "${OS}" != "Darwin" ]; then + echo "This is a MacOSX only test" + exit 0; +fi + +gcc_cmd=`which gcc` +if [ "x$gcc_cmd" == "x" ]; then + echo "WARNING: gcc not found. Cannot execute test." 2>&1 + exit 0; +fi + +JDK_TOPDIR="${TESTROOT}/.." + +$gcc_cmd -o ${TESTCLASSES}/JliLaunchTest \ + -I${JDK_TOPDIR}/src/share/bin \ + -I${JDK_TOPDIR}/src/share/javavm/export \ + -I${JDK_TOPDIR}/src/macosx/javavm/export \ + -I${JDK_TOPDIR}/src/solaris/bin \ + -L${TESTJAVA}/jre/lib/jli -ljli \ + ${TESTSRC}/exeJliLaunchTest.c + +${TESTJAVA}/bin/java -Dtest.jdk=${TESTJAVA} \ + -Dtest.nativepath=${TESTCLASSES} \ + -cp ${TESTCLASSPATH} JliLaunchTest diff --git a/test/jdk/tools/launcher/exeJliLaunchTest.c b/test/jdk/tools/launcher/exeJliLaunchTest.c new file mode 100644 --- /dev/null +++ b/test/jdk/tools/launcher/exeJliLaunchTest.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + + +/* + * This file contains the main entry point into the launcher code + * this is the only file which will be repeatedly compiled by other + * tools. The rest of the files will be linked in. + */ + +#include "java.h" + +int +main(int argc, char **argv) +{ + return JLI_Launch(argc, argv, + 0, NULL, + 0, NULL, + "1", "0", + *argv, *argv, + 0, 0, 0, 0); +} diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -351,6 +351,21 @@ } /* + * Returns name of system variable containing paths to shared native libraries. + */ + public static String sharedLibraryPathVariableName() { + if (isWindows()) { + return "PATH"; + } else if (isOSX()) { + return "DYLD_LIBRARY_PATH"; + } else if (isAix()) { + return "LIBPATH"; + } else { + return "LD_LIBRARY_PATH"; + } + } + + /* * This should match the #if condition in ClassListParser::load_class_from_source(). */ public static boolean areCustomLoadersSupportedForCDS() { diff --git a/test/sun/net/www/protocol/http/NULLTargetInfoTest.java b/test/sun/net/www/protocol/http/NULLTargetInfoTest.java new file mode 100644 --- /dev/null +++ b/test/sun/net/www/protocol/http/NULLTargetInfoTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, 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 8151788 + * @summary NullPointerException from ntlm.Client.type3 + * @run main NULLTargetInfoTest + */ +import com.sun.security.ntlm.Client; + +public class NULLTargetInfoTest { + + public static void main(String[] args) throws Exception { + Client c = new Client(null, "host", "user", "domain", "pass".toCharArray()); + c.type1(); + // this input does have the 0x800000 bit(NTLMSSP_NEGOTIATE_TARGET_INFO) set + // but after offset 40 all eight bytes are all zero which means there is no + // security buffer for target info. + byte[] type2 = hex( + "4E 54 4C 4D 53 53 50 00 02 00 00 00 00 00 00 00" + + "00 00 00 00 05 82 89 00 0B 87 81 B6 2D 6E 8B C1" + + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"); + byte[] nonce = new byte[10]; + c.type3(type2, nonce); + } + + private static byte[] hex(String str) { + str = str.replaceAll("\\s", ""); + byte[] response = new byte[str.length() / 2]; + int index = 0; + for (int i = 0; i < str.length(); i += 2) { + response[index++] = Integer.valueOf(str.substring(i, i + 2), 16).byteValue(); + } + return response; + } +} diff --git a/test/sun/security/krb5/auto/ReferralsTest.java b/test/sun/security/krb5/auto/ReferralsTest.java --- a/test/sun/security/krb5/auto/ReferralsTest.java +++ b/test/sun/security/krb5/auto/ReferralsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Red Hat, Inc. + * Copyright (c) 2019, 2020, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,15 +37,19 @@ import java.util.Set; import javax.security.auth.kerberos.KerberosTicket; import javax.security.auth.Subject; +import javax.security.auth.login.LoginException; import org.ietf.jgss.GSSName; import sun.security.jgss.GSSUtil; +import sun.security.krb5.Config; import sun.security.krb5.PrincipalName; public class ReferralsTest { private static final boolean DEBUG = true; private static final String krbConfigName = "krb5-localkdc.conf"; + private static final String krbConfigNameNoCanonicalize = + "krb5-localkdc-nocanonicalize.conf"; private static final String realmKDC1 = "RABBIT.HOLE"; private static final String realmKDC2 = "DEV.RABBIT.HOLE"; private static final char[] password = "123qwe@Z".toCharArray(); @@ -99,6 +103,7 @@ testDelegation(); testImpersonation(); testDelegationWithReferrals(); + testNoCanonicalize(); } finally { cleanup(); } @@ -138,14 +143,20 @@ kdc2.setOption(KDC.Option.ALLOW_S4U2PROXY, mapKDC2); KDC.saveConfig(krbConfigName, kdc1, kdc2, - "forwardable=true"); + "forwardable=true", "canonicalize=true"); + KDC.saveConfig(krbConfigNameNoCanonicalize, kdc1, kdc2, + "forwardable=true"); System.setProperty("java.security.krb5.conf", krbConfigName); } private static void cleanup() { - File f = new File(krbConfigName); - if (f.exists()) { - f.delete(); + String[] configFiles = new String[]{krbConfigName, + krbConfigNameNoCanonicalize}; + for (String configFile : configFiles) { + File f = new File(configFile); + if (f.exists()) { + f.delete(); + } } } @@ -324,4 +335,23 @@ throw new Exception("Unexpected initiator or acceptor names"); } } + + /* + * The client tries to get a TGT (AS protocol) as in testSubjectCredentials + * but without the canonicalize setting in krb5.conf. The KDC + * must not return a referral but a failure because the client + * is not in the local database. + */ + private static void testNoCanonicalize() throws Exception { + System.setProperty("java.security.krb5.conf", + krbConfigNameNoCanonicalize); + Config.refresh(); + try { + Context.fromUserPass(new Subject(), + clientKDC1Name, password, false); + throw new Exception("should not succeed"); + } catch (LoginException e) { + // expected + } + } } diff --git a/test/sun/security/mscapi/SmallPrimeExponentP.java b/test/sun/security/mscapi/SmallPrimeExponentP.java --- a/test/sun/security/mscapi/SmallPrimeExponentP.java +++ b/test/sun/security/mscapi/SmallPrimeExponentP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -21,6 +21,16 @@ * questions. */ + /* + * @test + * @bug 8023546 8151834 + * @summary Test prime exponent (p) lengths 63 and 65 bytes with SunMSCAPI. + * The seed 76 has the fastest test execution now (only 5 rounds) and is + * hard-coded in run tag. This number might change if algorithms for + * RSA key pair generation or BigInteger prime searching gets updated. + * @requires os.family == "windows" + * @run main SmallPrimeExponentP 76 + */ import sun.security.tools.keytool.CertAndKeyGen; import sun.security.x509.X500Name; @@ -28,47 +38,63 @@ import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateCrtKey; +import java.util.Random; -/* - * @test - * @bug 8023546 - * @summary sun/security/mscapi/ShortRSAKey1024.sh fails intermittently - * @requires os.family == "windows" - */ public class SmallPrimeExponentP { public static void main(String argv[]) throws Exception { - String osName = System.getProperty("os.name"); - if (!osName.startsWith("Windows")) { - System.out.println("Not windows"); - return; - } + long seed = Long.parseLong(argv[0]); + System.out.println("Seed for SecureRandom = " + seed + "L"); + KeyStore ks = KeyStore.getInstance("Windows-MY"); ks.load(null, null); + CertAndKeyGen ckg = new CertAndKeyGen("RSA", "SHA1withRSA"); - ckg.setRandom(new SecureRandom()); - boolean see63 = false, see65 = false; + ckg.setRandom(new MySecureRandom(seed)); + + boolean see63 = false; + boolean see65 = false; while (!see63 || !see65) { ckg.generate(1024); RSAPrivateCrtKey k = (RSAPrivateCrtKey) ckg.getPrivateKey(); + int len = k.getPrimeExponentP().toByteArray().length; + System.out.println("Length of P = " + len); if (len == 63 || len == 65) { if (len == 63) { - if (see63) continue; - else see63 = true; + if (see63) { + continue; + } else { + see63 = true; + } } if (len == 65) { - if (see65) continue; - else see65 = true; + if (see65) { + continue; + } else { + see65 = true; + } } - System.err.print(len); ks.setKeyEntry("anything", k, null, new X509Certificate[]{ - ckg.getSelfCertificate(new X500Name("CN=Me"), 1000) + ckg.getSelfCertificate(new X500Name("CN=Me"), 1000) }); } - System.err.print('.'); } ks.store(null, null); } + + static class MySecureRandom extends SecureRandom { + + final Random random; + + public MySecureRandom(long seed) { + random = new Random(seed); + } + + @Override + public void nextBytes(byte[] bytes) { + random.nextBytes(bytes); + } + } }