# HG changeset patch # User duke # Date 1499286359 -7200 # Node ID 8750872276b8219821f336ac174ead917f5599c4 # Parent a4ee110842fb074b79b8165b3612b17807d32547# Parent 1f6bd8d46bd5006e663df3879c4037b54bbeaad5 Merge diff -r a4ee110842fb -r 8750872276b8 .hgtags-top-repo --- a/.hgtags-top-repo Mon Nov 07 16:08:18 2016 +0000 +++ b/.hgtags-top-repo Wed Jul 05 22:25:59 2017 +0200 @@ -385,3 +385,4 @@ a5815c6098a241d3a1df64d22b84b3524e4a77df jdk-9+140 f64afae7f1a5608e438585bbf0bc23785e69cba0 jdk-9+141 2b3e5caafe3594ea507c37675c4d3086f415dc64 jdk-9+142 +1fc62b1c629fb80fdaa639d3b59452a184f0d705 jdk-9+143 diff -r a4ee110842fb -r 8750872276b8 common/autoconf/flags.m4 --- a/common/autoconf/flags.m4 Mon Nov 07 16:08:18 2016 +0000 +++ b/common/autoconf/flags.m4 Wed Jul 05 22:25:59 2017 +0200 @@ -280,7 +280,7 @@ else # Default works for linux, might work on other platforms as well. SHARED_LIBRARY_FLAGS='-shared' - SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN[$]1' + SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN[$]1' SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=[$]1' @@ -305,7 +305,7 @@ # Default works for linux, might work on other platforms as well. PICFLAG='-fPIC' SHARED_LIBRARY_FLAGS='-shared' - SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN[$]1' + SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN[$]1' SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=[$]1' @@ -315,7 +315,7 @@ C_FLAG_REORDER='-xF' CXX_FLAG_REORDER='-xF' SHARED_LIBRARY_FLAGS="-G" - SET_EXECUTABLE_ORIGIN='-R\$$$$ORIGIN[$]1' + SET_EXECUTABLE_ORIGIN='-R\$$ORIGIN[$]1' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-h [$]1' SET_SHARED_LIBRARY_MAPFILE='-M[$]1' diff -r a4ee110842fb -r 8750872276b8 common/autoconf/generated-configure.sh --- a/common/autoconf/generated-configure.sh Mon Nov 07 16:08:18 2016 +0000 +++ b/common/autoconf/generated-configure.sh Wed Jul 05 22:25:59 2017 +0200 @@ -5093,7 +5093,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1478079760 +DATE_WHEN_GENERATED=1478524503 ############################################################################### # @@ -49070,7 +49070,7 @@ else # Default works for linux, might work on other platforms as well. SHARED_LIBRARY_FLAGS='-shared' - SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN$1' + SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN$1' SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-soname=$1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=$1' @@ -49095,7 +49095,7 @@ # Default works for linux, might work on other platforms as well. PICFLAG='-fPIC' SHARED_LIBRARY_FLAGS='-shared' - SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN$1' + SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN$1' SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-soname=$1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=$1' @@ -49105,7 +49105,7 @@ C_FLAG_REORDER='-xF' CXX_FLAG_REORDER='-xF' SHARED_LIBRARY_FLAGS="-G" - SET_EXECUTABLE_ORIGIN='-R\$$$$ORIGIN$1' + SET_EXECUTABLE_ORIGIN='-R\$$ORIGIN$1' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-h $1' SET_SHARED_LIBRARY_MAPFILE='-M$1' diff -r a4ee110842fb -r 8750872276b8 common/autoconf/spec.gmk.in --- a/common/autoconf/spec.gmk.in Mon Nov 07 16:08:18 2016 +0000 +++ b/common/autoconf/spec.gmk.in Wed Jul 05 22:25:59 2017 +0200 @@ -788,6 +788,7 @@ SYMBOLS_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(SYMBOLS_IMAGE_SUBDIR) # Interim image +INTERIM_JMODS_DIR := $(SUPPORT_OUTPUTDIR)/interim-jmods INTERIM_IMAGE_DIR := $(SUPPORT_OUTPUTDIR)/interim-image # Docs image diff -r a4ee110842fb -r 8750872276b8 corba/.hgtags --- a/corba/.hgtags Mon Nov 07 16:08:18 2016 +0000 +++ b/corba/.hgtags Wed Jul 05 22:25:59 2017 +0200 @@ -385,3 +385,4 @@ 9f3fc931bc230f44f2a58d75f7f6360af98bb113 jdk-9+140 b32f998da32b488ec7c4e9dbb3c750841b48e74d jdk-9+141 408c9c621938ca028e20bced0459f815de47eba8 jdk-9+142 +6211236ef15ec796806357608b1dd1b70c258ece jdk-9+143 diff -r a4ee110842fb -r 8750872276b8 hotspot/.hgtags --- a/hotspot/.hgtags Mon Nov 07 16:08:18 2016 +0000 +++ b/hotspot/.hgtags Wed Jul 05 22:25:59 2017 +0200 @@ -545,3 +545,4 @@ fec31089c2ef5a12dd64f401b0bf2e00f56ee0d0 jdk-9+140 160a00bc6ed0af1fdf8418fc65e6bddbbc0c536d jdk-9+141 7b48d63dfd6b8e2657288de3d7b1f153dee02d7e jdk-9+142 +d87d5d430c42342f0320ca7f5cbe0cbd1f9d62ba jdk-9+143 diff -r a4ee110842fb -r 8750872276b8 hotspot/make/symbols/symbols-unix --- a/hotspot/make/symbols/symbols-unix Mon Nov 07 16:08:18 2016 +0000 +++ b/hotspot/make/symbols/symbols-unix Wed Jul 05 22:25:59 2017 +0200 @@ -125,7 +125,6 @@ JVM_GetProtectionDomain JVM_GetSimpleBinaryName JVM_GetStackAccessControlContext -JVM_GetStackTraceElements JVM_GetSystemPackage JVM_GetSystemPackages JVM_GetTemporaryDirectory @@ -135,6 +134,8 @@ JVM_HoldsLock JVM_IHashCode JVM_InitProperties +JVM_InitStackTraceElement +JVM_InitStackTraceElementArray JVM_InternString JVM_Interrupt JVM_InvokeMethod @@ -178,7 +179,6 @@ JVM_StopThread JVM_SupportsCX8 JVM_SuspendThread -JVM_ToStackTraceElement JVM_TotalMemory JVM_UnloadLibrary JVM_WaitForReferencePendingList diff -r a4ee110842fb -r 8750872276b8 hotspot/src/share/vm/classfile/javaClasses.cpp --- a/hotspot/src/share/vm/classfile/javaClasses.cpp Mon Nov 07 16:08:18 2016 +0000 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Wed Jul 05 22:25:59 2017 +0200 @@ -2175,6 +2175,14 @@ const char* str = holder->external_name(); oop classname = StringTable::intern((char*) str, CHECK); java_lang_StackTraceElement::set_declaringClass(element(), classname); + java_lang_StackTraceElement::set_declaringClassObject(element(), holder->java_mirror()); + + oop loader = holder->class_loader(); + if (loader != NULL) { + oop loader_name = java_lang_ClassLoader::name(loader); + if (loader_name != NULL) + java_lang_StackTraceElement::set_classLoaderName(element(), loader_name); + } // The method can be NULL if the requested class version is gone Symbol* sym = !method.is_null() ? method->name() : holder->constants()->symbol_at(cpref); @@ -3433,6 +3441,7 @@ bool java_lang_ClassLoader::offsets_computed = false; int java_lang_ClassLoader::_loader_data_offset = -1; int java_lang_ClassLoader::parallelCapable_offset = -1; +int java_lang_ClassLoader::name_offset = -1; int java_lang_ClassLoader::unnamedModule_offset = -1; ClassLoaderData** java_lang_ClassLoader::loader_data_addr(oop loader) { @@ -3453,6 +3462,9 @@ compute_optional_offset(parallelCapable_offset, k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); + compute_offset(name_offset, + k1, vmSymbols::name_name(), vmSymbols::string_signature()); + compute_offset(unnamedModule_offset, k1, vmSymbols::unnamedModule_name(), vmSymbols::module_signature()); @@ -3464,6 +3476,11 @@ return loader->obj_field(parent_offset); } +oop java_lang_ClassLoader::name(oop loader) { + assert(is_instance(loader), "loader must be oop"); + return loader->obj_field(name_offset); +} + bool java_lang_ClassLoader::isAncestor(oop loader, oop cl) { assert(is_instance(loader), "loader must be oop"); assert(cl == NULL || is_instance(cl), "cl argument must be oop"); @@ -3619,12 +3636,14 @@ int java_lang_System::static_out_offset; int java_lang_System::static_err_offset; int java_lang_System::static_security_offset; -int java_lang_StackTraceElement::declaringClass_offset; int java_lang_StackTraceElement::methodName_offset; int java_lang_StackTraceElement::fileName_offset; int java_lang_StackTraceElement::lineNumber_offset; int java_lang_StackTraceElement::moduleName_offset; int java_lang_StackTraceElement::moduleVersion_offset; +int java_lang_StackTraceElement::classLoaderName_offset; +int java_lang_StackTraceElement::declaringClass_offset; +int java_lang_StackTraceElement::classOrLoaderModuleClassName_offset; int java_lang_StackFrameInfo::_declaringClass_offset; int java_lang_StackFrameInfo::_memberName_offset; int java_lang_StackFrameInfo::_bci_offset; @@ -3669,6 +3688,14 @@ element->obj_field_put(moduleVersion_offset, value); } +void java_lang_StackTraceElement::set_classLoaderName(oop element, oop value) { + element->obj_field_put(classLoaderName_offset, value); +} + +void java_lang_StackTraceElement::set_declaringClassObject(oop element, oop value) { + element->obj_field_put(classOrLoaderModuleClassName_offset, value); +} + // Support for java_lang_StackFrameInfo void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) { element->obj_field_put(_declaringClass_offset, value); @@ -3784,6 +3811,8 @@ java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x; // java_lang_StackTraceElement + java_lang_StackTraceElement::classOrLoaderModuleClassName_offset= java_lang_StackTraceElement::hc_classOrLoaderModuleClassName_offset* x + header; + java_lang_StackTraceElement::classLoaderName_offset = java_lang_StackTraceElement::hc_classLoaderName_offset * x + header; java_lang_StackTraceElement::moduleName_offset = java_lang_StackTraceElement::hc_moduleName_offset * x + header; java_lang_StackTraceElement::moduleVersion_offset = java_lang_StackTraceElement::hc_moduleVersion_offset * x + header; java_lang_StackTraceElement::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset * x + header; @@ -3985,10 +4014,14 @@ // java.lang.StackTraceElement - CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClass, "Ljava/lang/String;"); - CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, methodName, "Ljava/lang/String;"); - CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, fileName, "Ljava/lang/String;"); - CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, lineNumber, "I"); + CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, classOrLoaderModuleClassName, "Ljava/lang/Object;"); + CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, classLoaderName, "Ljava/lang/String;"); + CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, moduleName, "Ljava/lang/String;"); + CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, moduleVersion, "Ljava/lang/String;"); + CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClass, "Ljava/lang/String;"); + CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, methodName, "Ljava/lang/String;"); + CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, fileName, "Ljava/lang/String;"); + CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, lineNumber, "I"); // java.lang.ref.Reference diff -r a4ee110842fb -r 8750872276b8 hotspot/src/share/vm/classfile/javaClasses.hpp --- a/hotspot/src/share/vm/classfile/javaClasses.hpp Mon Nov 07 16:08:18 2016 +0000 +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Wed Jul 05 22:25:59 2017 +0200 @@ -1225,6 +1225,7 @@ static bool offsets_computed; static int parent_offset; static int parallelCapable_offset; + static int name_offset; static int unnamedModule_offset; public: @@ -1234,6 +1235,7 @@ static ClassLoaderData* loader_data(oop loader); static oop parent(oop loader); + static oop name(oop loader); static bool isAncestor(oop loader, oop cl); // Support for parallelCapable field @@ -1291,14 +1293,18 @@ class java_lang_StackTraceElement: AllStatic { private: enum { - hc_moduleName_offset = 0, - hc_moduleVersion_offset = 1, - hc_declaringClass_offset = 2, - hc_methodName_offset = 3, - hc_fileName_offset = 4, - hc_lineNumber_offset = 5 + hc_classOrLoaderModuleClassName_offset = 0, + hc_classLoaderName_offset = 1, + hc_moduleName_offset = 2, + hc_moduleVersion_offset = 3, + hc_declaringClass_offset = 4, + hc_methodName_offset = 5, + hc_fileName_offset = 6, + hc_lineNumber_offset = 7 }; + static int classOrLoaderModuleClassName_offset; + static int classLoaderName_offset; static int moduleName_offset; static int moduleVersion_offset; static int declaringClass_offset; @@ -1307,12 +1313,14 @@ static int lineNumber_offset; // Setters + static void set_classLoaderName(oop element, oop value); static void set_moduleName(oop element, oop value); static void set_moduleVersion(oop element, oop value); static void set_declaringClass(oop element, oop value); static void set_methodName(oop element, oop value); static void set_fileName(oop element, oop value); static void set_lineNumber(oop element, int value); + static void set_declaringClassObject(oop element, oop value); public: // Create an instance of StackTraceElement diff -r a4ee110842fb -r 8750872276b8 hotspot/src/share/vm/prims/jvm.cpp --- a/hotspot/src/share/vm/prims/jvm.cpp Mon Nov 07 16:08:18 2016 +0000 +++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Jul 05 22:25:59 2017 +0200 @@ -503,16 +503,27 @@ JVM_END -JVM_ENTRY(void, JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray stackTrace)) - JVMWrapper("JVM_GetStackTraceElements"); +// java.lang.StackTraceElement ////////////////////////////////////////////// + + +JVM_ENTRY(void, JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable)) + JVMWrapper("JVM_InitStackTraceElementArray"); Handle exception(THREAD, JNIHandles::resolve(throwable)); - objArrayOop st = objArrayOop(JNIHandles::resolve(stackTrace)); + objArrayOop st = objArrayOop(JNIHandles::resolve(elements)); objArrayHandle stack_trace(THREAD, st); // Fill in the allocated stack trace java_lang_Throwable::get_stack_trace_elements(exception, stack_trace, CHECK); JVM_END +JVM_ENTRY(void, JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo)) + JVMWrapper("JVM_InitStackTraceElement"); + Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(stackFrameInfo)); + Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(element)); + java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD); +JVM_END + + // java.lang.StackWalker ////////////////////////////////////////////////////// @@ -566,13 +577,6 @@ start_index, frames_array_h, THREAD); JVM_END -JVM_ENTRY(void, JVM_ToStackTraceElement(JNIEnv *env, jobject frame, jobject stack)) - JVMWrapper("JVM_ToStackTraceElement"); - Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(frame)); - Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(stack)); - java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD); -JVM_END - // java.lang.Object /////////////////////////////////////////////// diff -r a4ee110842fb -r 8750872276b8 hotspot/src/share/vm/prims/jvm.h --- a/hotspot/src/share/vm/prims/jvm.h Mon Nov 07 16:08:18 2016 +0000 +++ b/hotspot/src/share/vm/prims/jvm.h Wed Jul 05 22:25:59 2017 +0200 @@ -189,8 +189,14 @@ JNIEXPORT void JNICALL JVM_FillInStackTrace(JNIEnv *env, jobject throwable); +/* + * java.lang.StackTraceElement + */ JNIEXPORT void JNICALL -JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements); +JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable); + +JNIEXPORT void JNICALL +JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo); /* * java.lang.StackWalker @@ -212,9 +218,6 @@ jint frame_count, jint start_index, jobjectArray frames); -JNIEXPORT void JNICALL -JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement); - /* * java.lang.Thread */ diff -r a4ee110842fb -r 8750872276b8 jaxp/.hgtags --- a/jaxp/.hgtags Mon Nov 07 16:08:18 2016 +0000 +++ b/jaxp/.hgtags Wed Jul 05 22:25:59 2017 +0200 @@ -385,3 +385,4 @@ 8d100cb9b04819b5bd09f33c7fd5b8628d1a456f jdk-9+140 037c095ba0c345edbeaaab52fda913a76c3930c0 jdk-9+141 bdafa0cc34a97a2f8db4847a4efd34b407943591 jdk-9+142 +ce81d03ad7320dca3d673374c1a33bc0efd9136a jdk-9+143 diff -r a4ee110842fb -r 8750872276b8 jaxws/.hgtags --- a/jaxws/.hgtags Mon Nov 07 16:08:18 2016 +0000 +++ b/jaxws/.hgtags Wed Jul 05 22:25:59 2017 +0200 @@ -388,3 +388,4 @@ 9004617323fe99cbe4fad48f373cb2ed4fc50aa6 jdk-9+140 b2c18f755228d1d19a86cd7d5fa1abb6b1495dfb jdk-9+141 59101416d90160cfcb4f45dfbccaec15e2c27a29 jdk-9+142 +1c988e708a06257119d54d8a57e99e3b0f37ff18 jdk-9+143 diff -r a4ee110842fb -r 8750872276b8 jdk/.hgtags --- a/jdk/.hgtags Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/.hgtags Wed Jul 05 22:25:59 2017 +0200 @@ -385,3 +385,4 @@ e93b7ea559759f036c9f69fd2ddaf47bb4e98385 jdk-9+140 8d752af5f61d41f226adf2cda72a20faa9ad620a jdk-9+141 6ce43dd8e954b452f330dd7a412df5107f7e1923 jdk-9+142 +8dbc8594f9d5149bf1c22221272284609408227a jdk-9+143 diff -r a4ee110842fb -r 8750872276b8 jdk/make/GenerateClasslist.gmk --- a/jdk/make/GenerateClasslist.gmk Mon Nov 07 16:08:18 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -# -# 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. 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. -# - -################################################################################ -# Generate classlist -################################################################################ - -default: all - -include $(SPEC) -include MakeBase.gmk -include Tools.gmk -include JarArchive.gmk - -################################################################################ -# Create a jar with our generator class. Using a jar is intentional since it -# will load more classes - -$(eval $(call SetupJarArchive, CLASSLIST_JAR, \ - SRCS := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \ - INCLUDES := build/tools/classlist, \ - JAR := $(SUPPORT_OUTPUTDIR)/classlist.jar, \ -)) - -TARGETS += $(CLASSLIST_JAR) - -################################################################################ - -CLASSLIST_FILE := $(SUPPORT_OUTPUTDIR)/classlist/classlist - -JLI_TRACE_FILE := $(SUPPORT_OUTPUTDIR)/classlist/jli_trace.out - -# If an external buildjdk has been supplied, we don't build a separate interim -# image, so just use the external build jdk instead. -ifeq ($(EXTERNAL_BUILDJDK), true) - INTERIM_IMAGE_DIR := $(BUILD_JDK) -endif - -$(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR) - $(call MakeDir, $(@D)) - $(call LogInfo, Generating lib/classlist) - $(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \ - -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \ - -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \ - build.tools.classlist.HelloClasslist \ - $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE) - -TARGETS += $(CLASSLIST_FILE) - -################################################################################ - -all: $(TARGETS) diff -r a4ee110842fb -r 8750872276b8 jdk/make/mapfiles/libjava/mapfile-vers --- a/jdk/make/mapfiles/libjava/mapfile-vers Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/make/mapfiles/libjava/mapfile-vers Wed Jul 05 22:25:59 2017 +0200 @@ -140,7 +140,6 @@ Java_java_lang_Double_doubleToRawLongBits; Java_java_lang_Float_intBitsToFloat; Java_java_lang_Float_floatToRawIntBits; - Java_java_lang_StackFrameInfo_toStackTraceElement0; Java_java_lang_StackStreamFactory_checkStackWalkModes; Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk; Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames; @@ -215,6 +214,8 @@ Java_java_lang_SecurityManager_currentLoadedClass0; Java_java_lang_SecurityManager_getClassContext; Java_java_lang_Shutdown_halt0; + Java_java_lang_StackTraceElement_initStackTraceElement; + Java_java_lang_StackTraceElement_initStackTraceElements; Java_java_lang_String_intern; Java_java_lang_StringCoding_err; Java_java_lang_StringUTF16_isBigEndian; @@ -227,7 +228,6 @@ Java_java_lang_System_setOut0; Java_java_lang_Thread_registerNatives; Java_java_lang_Throwable_fillInStackTrace; - Java_java_lang_Throwable_getStackTraceElements; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2; diff -r a4ee110842fb -r 8750872276b8 jdk/make/mapfiles/libjava/reorder-sparc --- a/jdk/make/mapfiles/libjava/reorder-sparc Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/make/mapfiles/libjava/reorder-sparc Wed Jul 05 22:25:59 2017 +0200 @@ -78,7 +78,7 @@ text: .text%JNU_GetEnv; text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_lang_reflect_Array_newArray; -text: .text%Java_java_lang_Throwable_getStackTraceElements; +text: .text%Java_java_lang_StackTraceElement_initStackTraceElements; text: .text%throwFileNotFoundException; text: .text%JNU_NotifyAll; # Test LoadFrame diff -r a4ee110842fb -r 8750872276b8 jdk/make/mapfiles/libjava/reorder-sparcv9 --- a/jdk/make/mapfiles/libjava/reorder-sparcv9 Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/make/mapfiles/libjava/reorder-sparcv9 Wed Jul 05 22:25:59 2017 +0200 @@ -74,7 +74,7 @@ text: .text%JNU_GetEnv; text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_lang_reflect_Array_newArray; -text: .text%Java_java_lang_Throwable_getStackTraceElements; +text: .text%Java_java_lang_StackTraceElement_initStackTraceElements; text: .text%throwFileNotFoundException: OUTPUTDIR/io_util.o; text: .text%JNU_NotifyAll; # Test LoadFrame diff -r a4ee110842fb -r 8750872276b8 jdk/make/mapfiles/libjava/reorder-x86 --- a/jdk/make/mapfiles/libjava/reorder-x86 Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/make/mapfiles/libjava/reorder-x86 Wed Jul 05 22:25:59 2017 +0200 @@ -78,7 +78,7 @@ text: .text%Java_sun_reflect_NativeMethodAccessorImpl_invoke0; text: .text%Java_java_io_FileInputStream_available; text: .text%Java_java_lang_reflect_Array_newArray; -text: .text%Java_java_lang_Throwable_getStackTraceElements; +text: .text%Java_java_lang_StackTraceElement_initStackTraceElements; text: .text%Java_java_lang_System_identityHashCode; text: .text%JNU_NotifyAll; # Test LoadFrame diff -r a4ee110842fb -r 8750872276b8 jdk/make/rmic/Rmic-java.rmi.gmk --- a/jdk/make/rmic/Rmic-java.rmi.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/make/rmic/Rmic-java.rmi.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -33,7 +33,7 @@ # $(eval $(call SetupRMICompilation,RMI_12, \ - CLASSES := sun.rmi.server.Activation$$$$ActivationSystemImpl \ + CLASSES := sun.rmi.server.Activation$$ActivationSystemImpl \ java.rmi.activation.ActivationGroup, \ CLASSES_DIR := $(CLASSES_DIR)/java.rmi, \ STUB_CLASSES_DIR := $(STUB_CLASSES_DIR)/java.rmi, \ diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/io/File.java --- a/jdk/src/java.base/share/classes/java/io/File.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/io/File.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -1907,16 +1907,10 @@ throws IOException { long n = random.nextLong(); - if (n == Long.MIN_VALUE) { - n = 0; // corner case - } else { - n = Math.abs(n); - } // Use only the file name from the supplied prefix prefix = (new File(prefix)).getName(); - - String name = prefix + Long.toString(n) + suffix; + String name = prefix + Long.toUnsignedString(n) + suffix; File f = new File(dir, name); if (!name.equals(f.getName()) || f.isInvalid()) { if (System.getSecurityManager() != null) diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/lang/Class.java --- a/jdk/src/java.base/share/classes/java/lang/Class.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/lang/Class.java Wed Jul 05 22:25:59 2017 +0200 @@ -485,7 +485,7 @@ * can be replaced by * *
{@code
-     * clazz.getConstructor().newInstance()
+     * clazz.getDeclaredConstructor().newInstance()
      * }
* * The latter sequence of calls is inferred to be able to throw diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/lang/ClassLoader.java --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Wed Jul 05 22:25:59 2017 +0200 @@ -222,6 +222,9 @@ // must be added *after* it. private final ClassLoader parent; + // class loader name + private final String name; + // the unnamed module for this ClassLoader private final Module unnamedModule; @@ -331,6 +334,14 @@ } private static Void checkCreateClassLoader() { + return checkCreateClassLoader(null); + } + + private static Void checkCreateClassLoader(String name) { + if (name != null && name.isEmpty()) { + throw new IllegalArgumentException("name must be non-empty or null"); + } + SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkCreateClassLoader(); @@ -338,7 +349,8 @@ return null; } - private ClassLoader(Void unused, ClassLoader parent) { + private ClassLoader(Void unused, String name, ClassLoader parent) { + this.name = name; this.parent = parent; this.unnamedModule = SharedSecrets.getJavaLangReflectModuleAccess() @@ -356,6 +368,27 @@ } /** + * Creates a new class loader of the specified name and using the + * specified parent class loader for delegation. + * + * @param name class loader name; or {@code null} if not named + * @param parent the parent class loader + * + * @throws IllegalArgumentException if the given name is empty. + * + * @throws SecurityException + * If a security manager exists and its + * {@link SecurityManager#checkCreateClassLoader()} + * method doesn't allow creation of a new class loader. + * + * @since 9 + */ + protected ClassLoader(String name, ClassLoader parent) { + this(checkCreateClassLoader(name), name, parent); + } + + + /** * Creates a new class loader using the specified parent class loader for * delegation. * @@ -375,9 +408,10 @@ * @since 1.2 */ protected ClassLoader(ClassLoader parent) { - this(checkCreateClassLoader(), parent); + this(checkCreateClassLoader(), null, parent); } + /** * Creates a new class loader using the ClassLoader returned by * the method {@link #getSystemClassLoader() @@ -394,7 +428,31 @@ * of a new class loader. */ protected ClassLoader() { - this(checkCreateClassLoader(), getSystemClassLoader()); + this(checkCreateClassLoader(), null, getSystemClassLoader()); + } + + + /** + * Returns the name of this class loader or {@code null} if + * this class loader is not named. + * + * @apiNote This method is non-final for compatibility. If this + * method is overridden, this method must return the same name + * as specified when this class loader was instantiated. + * + * @return name of this class loader; or {@code null} if + * this class loader is not named. + * + * @since 9 + */ + public String getName() { + return name; + } + + // package-private used by StackTraceElement to avoid + // calling the overrideable getName method + final String name() { + return name; } // -- Class -- @@ -1628,6 +1686,9 @@ * platform classes are visible to * the platform class loader. * + * @implNote The name of the builtin platform class loader is + * {@code "platform"}. + * * @return The platform {@code ClassLoader}. * * @throws SecurityException @@ -1681,7 +1742,8 @@ * this method during startup should take care not to cache the return * value until the system is fully initialized. * - *

The class path used by the built-in system class loader is determined + *

The name of the built-in system class loader is {@code "app"}. + * The class path used by the built-in system class loader is determined * by the system property "{@code java.class.path}" during early * initialization of the VM. If the system property is not defined, * or its value is an empty string, then there is no class path diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java --- a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java Wed Jul 05 22:25:59 2017 +0200 @@ -112,11 +112,6 @@ return toStackTraceElement().toString(); } - /** - * Fill in the fields of the given StackTraceElement - */ - private native void toStackTraceElement0(StackTraceElement ste); - @Override public StackTraceElement toStackTraceElement() { StackTraceElement s = ste; @@ -124,9 +119,7 @@ synchronized (this) { s = ste; if (s == null) { - s = new StackTraceElement(); - toStackTraceElement0(s); - ste = s; + ste = s = StackTraceElement.of(this); } } } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/lang/StackTraceElement.java --- a/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java Wed Jul 05 22:25:59 2017 +0200 @@ -25,7 +25,18 @@ package java.lang; +import jdk.internal.loader.BuiltinClassLoader; +import jdk.internal.misc.SharedSecrets; +import jdk.internal.misc.VM; +import jdk.internal.module.ModuleHashes; + +import java.lang.module.ModuleDescriptor.Version; +import java.lang.reflect.Layer; +import java.lang.reflect.Module; +import java.util.HashSet; import java.util.Objects; +import java.util.Optional; +import java.util.Set; /** * An element in a stack trace, as returned by {@link @@ -40,7 +51,15 @@ * @author Josh Bloch */ public final class StackTraceElement implements java.io.Serializable { - // Normally initialized by VM (public constructor added in 1.5) + // This field is set to the compacted String representation used + // by StackTraceElement::toString and stored in serial form. + // + // This field is of Object type. VM initially sets this field to + // the Class object of the declaring class to build the compacted string. + private Object classOrLoaderModuleClassName; + + // Normally initialized by VM + private String classLoaderName; private String moduleName; private String moduleVersion; private String declaringClass; @@ -72,19 +91,22 @@ */ public StackTraceElement(String declaringClass, String methodName, String fileName, int lineNumber) { - this(null, null, declaringClass, methodName, fileName, lineNumber); + this(null, null, null, declaringClass, methodName, fileName, lineNumber); } /** * Creates a stack trace element representing the specified execution * point. * + * @param classLoaderName the class loader name if the class loader of + * the class containing the execution point represented by + * the stack trace is named; otherwise {@code null} * @param moduleName the module name if the class containing the * execution point represented by the stack trace is in a named - * module; can be {@code null} + * module; otherwise {@code null} * @param moduleVersion the module version if the class containing the * execution point represented by the stack trace is in a named - * module that has a version; can be {@code null} + * module that has a version; otherwise {@code null} * @param declaringClass the fully qualified name of the class containing * the execution point represented by the stack trace element * @param methodName the name of the method containing the execution point @@ -97,26 +119,30 @@ * a negative number if this information is unavailable. A value * of -2 indicates that the method containing the execution point * is a native method + * * @throws NullPointerException if {@code declaringClass} is {@code null} * or {@code methodName} is {@code null} + * * @since 9 */ - public StackTraceElement(String moduleName, String moduleVersion, + public StackTraceElement(String classLoaderName, + String moduleName, String moduleVersion, String declaringClass, String methodName, String fileName, int lineNumber) { - this.moduleName = moduleName; - this.moduleVersion = moduleVersion; - this.declaringClass = Objects.requireNonNull(declaringClass, "Declaring class is null"); - this.methodName = Objects.requireNonNull(methodName, "Method name is null"); - this.fileName = fileName; - this.lineNumber = lineNumber; + this.classLoaderName = classLoaderName; + this.moduleName = moduleName; + this.moduleVersion = moduleVersion; + this.declaringClass = Objects.requireNonNull(declaringClass, "Declaring class is null"); + this.methodName = Objects.requireNonNull(methodName, "Method name is null"); + this.fileName = fileName; + this.lineNumber = lineNumber; } - - /** - * Creates an empty stack frame element to be filled in by Throwable. + /* + * Private constructor for the factory methods to create StackTraceElement + * for Throwable and StackFrameInfo */ - StackTraceElement() { } + private StackTraceElement() {} /** * Returns the name of the source file containing the execution point @@ -178,6 +204,21 @@ } /** + * Returns the name of the class loader of the class containing the + * execution point represented by this stack trace element. + * + * @return the name of the class loader of the class containing the execution + * point represented by this stack trace element; {@code null} + * if the class loader is not named. + * + * @since 9 + * @see java.lang.ClassLoader#getName() + */ + public String getClassLoaderName() { + return classLoaderName; + } + + /** * Returns the fully qualified name of the class containing the * execution point represented by this stack trace element. * @@ -220,38 +261,83 @@ * examples may be regarded as typical: *

- * If the execution point is not in a named module, {@code "my.module@9.0/"} - * will be omitted from the above. + * + *

The first example shows a stack trace element consisting of + * three elements, each separated by {@code "/"} followed with + * the source file name and the line number of the source line + * containing the execution point. + * + * The first element "{@code com.foo.loader}" is + * the name of the class loader. The second element "{@code foo@9.0}" + * is the module name and version. The third element is the method + * containing the execution point; "{@code com.foo.Main"}" is the + * fully-qualified class name and "{@code run}" is the name of the method. + * "{@code Main.java}" is the source file name and "{@code 101}" is + * the line number. + * + *

If a class is defined in an unnamed module + * then the second element is omitted as shown in + * "{@code com.foo.loader//com.foo.bar.App.run(App.java:12)}". + * + * If the class loader is a + * built-in class loader or is not named then the first element + * and its following {@code "/"} are omitted as shown in + * "{@code acme@2.1/org.acme.Lib.test(Lib.java:80)}". + * If the first element is omitted and the module is an unnamed module, + * the second element and its following {@code "/"} are also omitted + * as shown in "{@code MyClass.mash(MyClass.java:9)}". * * @see Throwable#printStackTrace() */ public String toString() { - String mid = ""; - if (moduleName != null) { - mid = moduleName; - if (moduleVersion != null) - mid += "@" + moduleVersion; - mid += "/"; + String s = buildLoaderModuleClassName(); + if (s == null) { + // all elements will be included + s = ""; + if (classLoaderName != null && !classLoaderName.isEmpty()) { + s += classLoaderName + "/"; + } + if (moduleName != null && !moduleName.isEmpty()) { + s += moduleName; + + if (moduleVersion != null && !moduleVersion.isEmpty()) { + s += "@" + moduleVersion; + } + } + s = s.isEmpty() ? declaringClass : s + "/" + declaringClass; } - return getClassName() + "." + methodName + "(" + mid + + + return s + "." + methodName + "(" + (isNativeMethod() ? "Native Method)" : (fileName != null && lineNumber >= 0 ? fileName + ":" + lineNumber + ")" : @@ -264,12 +350,14 @@ * point as this instance. Two stack trace elements {@code a} and * {@code b} are equal if and only if: *

{@code
-     *     equals(a.getFileName(), b.getFileName()) &&
-     *     a.getLineNumber() == b.getLineNumber()) &&
+     *     equals(a.getClassLoaderName(), b.getClassLoaderName()) &&
      *     equals(a.getModuleName(), b.getModuleName()) &&
      *     equals(a.getModuleVersion(), b.getModuleVersion()) &&
      *     equals(a.getClassName(), b.getClassName()) &&
      *     equals(a.getMethodName(), b.getMethodName())
+     *     equals(a.getFileName(), b.getFileName()) &&
+     *     a.getLineNumber() == b.getLineNumber()
+     *
      * }
* where {@code equals} has the semantics of {@link * java.util.Objects#equals(Object, Object) Objects.equals}. @@ -285,9 +373,10 @@ if (!(obj instanceof StackTraceElement)) return false; StackTraceElement e = (StackTraceElement)obj; - return e.declaringClass.equals(declaringClass) && + return Objects.equals(classLoaderName, e.classLoaderName) && Objects.equals(moduleName, e.moduleName) && Objects.equals(moduleVersion, e.moduleVersion) && + e.declaringClass.equals(declaringClass) && e.lineNumber == lineNumber && Objects.equals(methodName, e.methodName) && Objects.equals(fileName, e.fileName); @@ -298,6 +387,7 @@ */ public int hashCode() { int result = 31*declaringClass.hashCode() + methodName.hashCode(); + result = 31*result + Objects.hashCode(classLoaderName); result = 31*result + Objects.hashCode(moduleName); result = 31*result + Objects.hashCode(moduleVersion); result = 31*result + Objects.hashCode(fileName); @@ -305,5 +395,157 @@ return result; } + + /** + * Build the compacted String representation to be returned by + * toString method from the declaring Class object. + */ + synchronized String buildLoaderModuleClassName() { + if (classOrLoaderModuleClassName == null) + return null; + + if (classOrLoaderModuleClassName instanceof Class) { + Class cls = (Class)classOrLoaderModuleClassName; + classOrLoaderModuleClassName = toLoaderModuleClassName(cls); + } + return (String)classOrLoaderModuleClassName; + } + + /** + * Returns // string + * representation of the given class. + *

+ * If the module is a non-upgradeable JDK module then omit + * its version string. + *

+ * If the loader has no name, or if the loader is one of the built-in + * loaders (`boot`, `platform`, or `app`) then drop the first element + * (`/`). + *

+ * If the first element has been dropped and the module is unnamed + * then drop the second element (`/`). + *

+ * If the first element is not dropped and the module is unnamed + * then drop ``. + */ + private static String toLoaderModuleClassName(Class cls) { + ClassLoader loader = cls.getClassLoader0(); + Module m = cls.getModule(); + + // First element - class loader name + // Call package-private ClassLoader::name method + String s = ""; + if (loader != null && loader.name() != null && + !(loader instanceof BuiltinClassLoader)) { + s = loader.name() + "/"; + } + + // Second element - module name and version + if (m != null && m.isNamed()) { + s += m.getName(); + // Include version if it is a user module or upgradeable module + // + // If it is JDK non-upgradeable module which is recorded + // in the hashes in java.base, omit the version. + if (!isHashedInJavaBase(m)) { + Optional ov = m.getDescriptor().version(); + if (ov.isPresent()) { + String version = "@" + ov.get().toString(); + s += version; + } + } + } + + // fully-qualified class name + return s.isEmpty() ? cls.getName() : s + "/" + cls.getName(); + } + + /** + * Returns true if the module is hashed with java.base. + *

+ * This method returns false when running on the exploded image + * since JDK modules are not hashed. They have no Version attribute + * and so "@" part will be omitted anyway. + */ + private static boolean isHashedInJavaBase(Module m) { + // return true if module system is not initialized as the code + // must be in java.base + if (!VM.isModuleSystemInited()) + return true; + + return Layer.boot() == m.getLayer() && HashedModules.contains(m); + } + + /* + * Finds JDK non-upgradeable modules, i.e. the modules that are + * included in the hashes in java.base. + */ + private static class HashedModules { + static Set HASHED_MODULES = hashedModules(); + + static Set hashedModules() { + Module javaBase = Layer.boot().findModule("java.base").get(); + Optional ohashes = + SharedSecrets.getJavaLangModuleAccess() + .hashes(javaBase.getDescriptor()); + + if (ohashes.isPresent()) { + Set names = new HashSet<>(ohashes.get().names()); + names.add("java.base"); + return names; + } + + return Set.of(); + } + + static boolean contains(Module m) { + return HASHED_MODULES.contains(m.getName()); + } + } + + + /* + * Returns an array of StackTraceElements of the given depth + * filled from the backtrace of a given Throwable. + */ + static StackTraceElement[] of(Throwable x, int depth) { + StackTraceElement[] stackTrace = new StackTraceElement[depth]; + for (int i = 0; i < depth; i++) { + stackTrace[i] = new StackTraceElement(); + } + + // VM to fill in StackTraceElement + initStackTraceElements(stackTrace, x); + + // ensure the proper StackTraceElement initialization + for (StackTraceElement ste : stackTrace) { + ste.buildLoaderModuleClassName(); + } + return stackTrace; + } + + /* + * Returns a StackTraceElement from a given StackFrameInfo. + */ + static StackTraceElement of(StackFrameInfo sfi) { + StackTraceElement ste = new StackTraceElement(); + initStackTraceElement(ste, sfi); + + ste.buildLoaderModuleClassName(); + return ste; + } + + /* + * Sets the given stack trace elements with the backtrace + * of the given Throwable. + */ + private static native void initStackTraceElements(StackTraceElement[] elements, + Throwable x); + /* + * Sets the given stack trace element with the given StackFrameInfo + */ + private static native void initStackTraceElement(StackTraceElement element, + StackFrameInfo sfi); + private static final long serialVersionUID = 6992337162326171013L; } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/lang/Throwable.java --- a/jdk/src/java.base/share/classes/java/lang/Throwable.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/lang/Throwable.java Wed Jul 05 22:25:59 2017 +0200 @@ -24,7 +24,6 @@ */ package java.lang; -import jdk.internal.misc.VM; import java.io.*; import java.util.*; @@ -826,11 +825,7 @@ // backtrace if this is the first call to this method if (stackTrace == UNASSIGNED_STACK || (stackTrace == null && backtrace != null) /* Out of protocol state */) { - stackTrace = new StackTraceElement[depth]; - for (int i = 0; i < depth; i++) { - stackTrace[i] = new StackTraceElement(); - } - getStackTraceElements(stackTrace); + stackTrace = StackTraceElement.of(this, depth); } else if (stackTrace == null) { return UNASSIGNED_STACK; } @@ -882,13 +877,6 @@ } /** - * Gets the stack trace elements. - * @param elements - * @throws IndexOutOfBoundsException if {@code elements.length != depth } - */ - private native void getStackTraceElements(StackTraceElement[] elements); - - /** * Reads a {@code Throwable} from a stream, enforcing * well-formedness constraints on fields. Null entries and * self-pointers are not allowed in the list of {@code diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/net/URLClassLoader.java --- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java Wed Jul 05 22:25:59 2017 +0200 @@ -110,19 +110,19 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls); + this.ucp = new URLClassPath(urls); this.acc = AccessController.getContext(); } - URLClassLoader(URL[] urls, ClassLoader parent, + URLClassLoader(String name, URL[] urls, ClassLoader parent, AccessControlContext acc) { - super(parent); + super(name, parent); // this is to make the stack depth consistent with 1.1 SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls); + this.ucp = new URLClassPath(urls); this.acc = acc; } @@ -154,7 +154,7 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls); + this.ucp = new URLClassPath(urls); this.acc = AccessController.getContext(); } @@ -165,7 +165,7 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls); + this.ucp = new URLClassPath(urls); this.acc = acc; } @@ -198,8 +198,76 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls, factory); - acc = AccessController.getContext(); + this.ucp = new URLClassPath(urls, factory); + this.acc = AccessController.getContext(); + } + + + /** + * Constructs a new named {@code URLClassLoader} for the specified URLs. + * The URLs will be searched in the order specified for classes + * and resources after first searching in the specified parent class loader. + * Any URL that ends with a '/' is assumed to refer to a directory. + * Otherwise, the URL is assumed to refer to a JAR file which will be + * downloaded and opened as needed. + * + * @param name class loader name; or {@code null} if not named + * @param urls the URLs from which to load classes and resources + * @param parent the parent class loader for delegation + * + * @throws IllegalArgumentException if the given name is empty. + * @throws NullPointerException if {@code urls} is {@code null}. + * + * @throws SecurityException if a security manager exists and its + * {@link SecurityManager#checkCreateClassLoader()} method doesn't + * allow creation of a class loader. + * + * @since 9 + */ + public URLClassLoader(String name, + URL[] urls, + ClassLoader parent) { + super(name, parent); + // this is to make the stack depth consistent with 1.1 + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkCreateClassLoader(); + } + this.ucp = new URLClassPath(urls); + this.acc = AccessController.getContext(); + } + + /** + * Constructs a new named {@code URLClassLoader} for the specified URLs, + * parent class loader, and URLStreamHandlerFactory. + * The parent argument will be used as the parent class loader for delegation. + * The factory argument will be used as the stream handler factory to + * obtain protocol handlers when creating new jar URLs. + * + * @param name class loader name; or {@code null} if not named + * @param urls the URLs from which to load classes and resources + * @param parent the parent class loader for delegation + * @param factory the URLStreamHandlerFactory to use when creating URLs + * + * @throws IllegalArgumentException if the given name is empty. + * @throws NullPointerException if {@code urls} is {@code null}. + * + * @throws SecurityException if a security manager exists and its + * {@code checkCreateClassLoader} method doesn't allow + * creation of a class loader. + * + * @since 9 + */ + public URLClassLoader(String name, URL[] urls, ClassLoader parent, + URLStreamHandlerFactory factory) { + super(name, parent); + // this is to make the stack depth consistent with 1.1 + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkCreateClassLoader(); + } + this.ucp = new URLClassPath(urls, factory); + this.acc = AccessController.getContext(); } /* A map (used as a set) to keep track of closeable local resources @@ -735,7 +803,7 @@ URLClassLoader ucl = AccessController.doPrivileged( new PrivilegedAction<>() { public URLClassLoader run() { - return new FactoryURLClassLoader(urls, parent, acc); + return new FactoryURLClassLoader(null, urls, parent, acc); } }); return ucl; @@ -785,9 +853,9 @@ ClassLoader.registerAsParallelCapable(); } - FactoryURLClassLoader(URL[] urls, ClassLoader parent, + FactoryURLClassLoader(String name, URL[] urls, ClassLoader parent, AccessControlContext acc) { - super(urls, parent, acc); + super(name, urls, parent, acc); } FactoryURLClassLoader(URL[] urls, AccessControlContext acc) { diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java --- a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -55,8 +55,8 @@ private static final SecureRandom random = new SecureRandom(); private static Path generatePath(String prefix, String suffix, Path dir) { long n = random.nextLong(); - n = (n == Long.MIN_VALUE) ? 0 : Math.abs(n); - Path name = dir.getFileSystem().getPath(prefix + Long.toString(n) + suffix); + String s = prefix + Long.toUnsignedString(n) + suffix; + Path name = dir.getFileSystem().getPath(s); // the generated name should be a simple file name if (name.getParent() != null) throw new IllegalArgumentException("Invalid prefix or suffix"); diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/security/SecureClassLoader.java --- a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java Wed Jul 05 22:25:59 2017 +0200 @@ -25,8 +25,6 @@ package java.security; -import java.net.URL; -import java.util.ArrayList; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -114,6 +112,30 @@ } /** + * Creates a new {@code SecureClassLoader} of the specified name and + * using the specified parent class loader for delegation. + * + * @param name class loader name; or {@code null} if not named + * @param parent the parent class loader + * + * @throws IllegalArgumentException if the given name is empty. + * + * @throws SecurityException if a security manager exists and its + * {@link SecurityManager#checkCreateClassLoader()} method + * doesn't allow creation of a class loader. + * + * @since 9 + */ + protected SecureClassLoader(String name, ClassLoader parent) { + super(name, parent); + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkCreateClassLoader(); + } + initialized = true; + } + + /** * Converts an array of bytes into an instance of class Class, * with an optional CodeSource. Before the * class can be used it must be resolved. diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/util/ImmutableCollections.java --- a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java Wed Jul 05 22:25:59 2017 +0200 @@ -53,7 +53,8 @@ */ static final int SALT; static { - SALT = new Random().nextInt(); + long nt = System.nanoTime(); + SALT = (int)((nt >>> 32) ^ nt); } /** No instances. */ @@ -63,7 +64,7 @@ * The reciprocal of load factor. Given a number of elements * to store, multiply by this factor to get the table size. */ - static final double EXPAND_FACTOR = 2.0; + static final int EXPAND_FACTOR = 2; static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); } @@ -84,7 +85,14 @@ } static final class List0 extends AbstractImmutableList { - List0() { } + private static final List0 INSTANCE = new List0<>(); + + @SuppressWarnings("unchecked") + static List0 instance() { + return (List0) INSTANCE; + } + + private List0() { } @Override public int size() { @@ -214,7 +222,14 @@ } static final class Set0 extends AbstractImmutableSet { - Set0() { } + private static final Set0 INSTANCE = new Set0<>(); + + @SuppressWarnings("unchecked") + static Set0 instance() { + return (Set0) INSTANCE; + } + + private Set0() { } @Override public int size() { @@ -351,7 +366,7 @@ SetN(E... input) { size = input.length; // implicit nullcheck of input - elements = (E[])new Object[(int)Math.ceil(EXPAND_FACTOR * input.length)]; + elements = (E[])new Object[EXPAND_FACTOR * input.length]; for (int i = 0; i < input.length; i++) { E e = Objects.requireNonNull(input[i]); int idx = probe(e); @@ -450,7 +465,14 @@ } static final class Map0 extends AbstractImmutableMap { - Map0() { } + private static final Map0 INSTANCE = new Map0<>(); + + @SuppressWarnings("unchecked") + static Map0 instance() { + return (Map0) INSTANCE; + } + + private Map0() { } @Override public Set> entrySet() { @@ -529,7 +551,7 @@ } size = input.length >> 1; - int len = (int)Math.ceil(EXPAND_FACTOR * input.length); + int len = EXPAND_FACTOR * input.length; len = (len + 1) & ~1; // ensure table is even length table = new Object[len]; @@ -789,7 +811,7 @@ return Set.of(array); case IMM_MAP: if (array.length == 0) { - return new ImmutableCollections.Map0<>(); + return ImmutableCollections.Map0.instance(); } else if (array.length == 2) { return new ImmutableCollections.Map1<>(array[0], array[1]); } else { diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/util/List.java --- a/jdk/src/java.base/share/classes/java/util/List.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/util/List.java Wed Jul 05 22:25:59 2017 +0200 @@ -786,7 +786,7 @@ * @since 9 */ static List of() { - return new ImmutableCollections.List0<>(); + return ImmutableCollections.List0.instance(); } /** @@ -1030,7 +1030,7 @@ Objects.requireNonNull(elements); switch (elements.length) { case 0: - return new ImmutableCollections.List0<>(); + return ImmutableCollections.List0.instance(); case 1: return new ImmutableCollections.List1<>(elements[0]); case 2: diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/util/Map.java --- a/jdk/src/java.base/share/classes/java/util/Map.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/util/Map.java Wed Jul 05 22:25:59 2017 +0200 @@ -1286,7 +1286,7 @@ * @since 9 */ static Map of() { - return new ImmutableCollections.Map0<>(); + return ImmutableCollections.Map0.instance(); } /** @@ -1604,7 +1604,7 @@ static Map ofEntries(Entry... entries) { Objects.requireNonNull(entries); if (entries.length == 0) { - return new ImmutableCollections.Map0<>(); + return ImmutableCollections.Map0.instance(); } else if (entries.length == 1) { return new ImmutableCollections.Map1<>(entries[0].getKey(), entries[0].getValue()); diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/java/util/Set.java --- a/jdk/src/java.base/share/classes/java/util/Set.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/java/util/Set.java Wed Jul 05 22:25:59 2017 +0200 @@ -448,7 +448,7 @@ * @since 9 */ static Set of() { - return new ImmutableCollections.Set0<>(); + return ImmutableCollections.Set0.instance(); } /** @@ -692,7 +692,7 @@ Objects.requireNonNull(elements); switch (elements.length) { case 0: - return new ImmutableCollections.Set0<>(); + return ImmutableCollections.Set0.instance(); case 1: return new ImmutableCollections.Set1<>(elements[0]); case 2: diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java --- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Wed Jul 05 22:25:59 2017 +0200 @@ -145,9 +145,9 @@ /** * Create a new instance. */ - BuiltinClassLoader(BuiltinClassLoader parent, URLClassPath ucp) { + BuiltinClassLoader(String name, BuiltinClassLoader parent, URLClassPath ucp) { // ensure getParent() returns null when the parent is the boot loader - super(parent == null || parent == ClassLoaders.bootLoader() ? null : parent); + super(name, parent == null || parent == ClassLoaders.bootLoader() ? null : parent); this.parent = parent; this.ucp = ucp; diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java --- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Wed Jul 05 22:25:59 2017 +0200 @@ -118,7 +118,7 @@ */ private static class BootClassLoader extends BuiltinClassLoader { BootClassLoader(URLClassPath bcp) { - super(null, bcp); + super(null, null, bcp); } @Override @@ -138,7 +138,7 @@ } PlatformClassLoader(BootClassLoader parent) { - super(parent, null); + super("platform", parent, null); } /** @@ -165,7 +165,7 @@ final URLClassPath ucp; AppClassLoader(PlatformClassLoader parent, URLClassPath ucp) { - super(parent, ucp); + super("app", parent, ucp); this.ucp = ucp; } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java --- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Wed Jul 05 22:25:59 2017 +0200 @@ -253,20 +253,20 @@ } private static String toSourceString(char c) { - StringBuilder sb = new StringBuilder(); - sb.append("'"); + StringBuilder sb = new StringBuilder(4); + sb.append('\''); if (c == '\'') sb.append("\\'"); else sb.append(c); - sb.append("'"); - return sb.toString(); + return sb.append('\'') + .toString(); } private static String toSourceString(long ell) { - return (Math.abs(ell) <= Integer.MAX_VALUE) ? - String.valueOf(ell) : - (String.valueOf(ell) + "L"); + String str = String.valueOf(ell); + return (ell < Integer.MIN_VALUE || ell > Integer.MAX_VALUE) + ? (str + 'L') : str; } /** @@ -278,10 +278,7 @@ sb.append('"'); // Escape embedded quote characters, if present, but don't do // anything more heroic. - if (s.indexOf('"') != -1) { - s = s.replace("\"", "\\\""); - } - sb.append(s); + sb.append(s.replace("\"", "\\\"")); sb.append('"'); return sb.toString(); } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java Wed Jul 05 22:25:59 2017 +0200 @@ -1715,12 +1715,17 @@ synchronized void fatal(byte description, String diagnostic) throws SSLException { - fatal(description, diagnostic, null); + fatal(description, diagnostic, null, false); } synchronized void fatal(byte description, Throwable cause) throws SSLException { - fatal(description, null, cause); + fatal(description, null, cause, false); + } + + synchronized void fatal(byte description, String diagnostic, + Throwable cause) throws SSLException { + fatal(description, diagnostic, cause, false); } /* @@ -1732,12 +1737,12 @@ * levels which then call here. This code needs to determine * if one of the lower levels has already started the process. * - * We won't worry about Error's, if we have one of those, + * We won't worry about Errors, if we have one of those, * we're in worse trouble. Note: the networking code doesn't * deal with Errors either. */ synchronized void fatal(byte description, String diagnostic, - Throwable cause) throws SSLException { + Throwable cause, boolean recvFatalAlert) throws SSLException { /* * If we have no further information, make a general-purpose @@ -1798,10 +1803,11 @@ } /* - * If we haven't even started handshaking yet, no need - * to generate the fatal close alert. + * If we haven't even started handshaking yet, or we are the + * recipient of a fatal alert, no need to generate a fatal close + * alert. */ - if (oldState != cs_START) { + if (oldState != cs_START && !recvFatalAlert) { sendAlert(Alerts.alert_fatal, description); } @@ -1841,10 +1847,6 @@ byte level = fragment.get(); byte description = fragment.get(); - if (description == -1) { // check for short message - fatal(Alerts.alert_illegal_parameter, "Short alert message"); - } - if (debug != null && (Debug.isOn("record") || Debug.isOn("handshake"))) { synchronized (System.out) { @@ -1862,7 +1864,9 @@ } if (level == Alerts.alert_warning) { - if (description == Alerts.alert_close_notify) { + if (description == -1) { // check for short message + fatal(Alerts.alert_illegal_parameter, "Short alert message"); + } else if (description == Alerts.alert_close_notify) { if (connectionState == cs_HANDSHAKE) { fatal(Alerts.alert_unexpected_message, "Received close_notify during handshake"); @@ -1885,10 +1889,14 @@ } else { // fatal or unknown level String reason = "Received fatal alert: " + Alerts.alertDescription(description); - if (closeReason == null) { - closeReason = Alerts.getSSLException(description, reason); - } - fatal(Alerts.alert_unexpected_message, reason); + + // The inbound and outbound queues will be closed as part of + // the call to fatal. The handhaker to needs to be set to null + // so subsequent calls to getHandshakeStatus will return + // NOT_HANDSHAKING. + handshaker = null; + Throwable cause = Alerts.getSSLException(description, reason); + fatal(description, null, cause, true); } } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/native/include/jvm.h --- a/jdk/src/java.base/share/native/include/jvm.h Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/native/include/jvm.h Wed Jul 05 22:25:59 2017 +0200 @@ -165,14 +165,24 @@ JNIEXPORT jboolean JNICALL JVM_IsSupportedJNIVersion(jint version); +JNIEXPORT jobjectArray JNICALL +JVM_GetVmArguments(JNIEnv *env); + + /* * java.lang.Throwable */ JNIEXPORT void JNICALL JVM_FillInStackTrace(JNIEnv *env, jobject throwable); +/* + * java.lang.StackTraceElement + */ JNIEXPORT void JNICALL -JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements); +JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable); + +JNIEXPORT void JNICALL +JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo); /* * java.lang.StackWalker @@ -194,12 +204,6 @@ jint frame_count, jint start_index, jobjectArray frames); -JNIEXPORT void JNICALL -JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement); - -JNIEXPORT jobjectArray JNICALL -JVM_GetVmArguments(JNIEnv *env); - /* * java.lang.Thread */ diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/native/libjava/StackFrameInfo.c --- a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c Mon Nov 07 16:08:18 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 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. 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. - */ - -/* - * Implementation of class StackFrameInfo - */ - -#include -#include - -#include "jni.h" -#include "jvm.h" - -#include "java_lang_StackFrameInfo.h" - - -/* - * Class: java_lang_StackFrameInfo - * Method: toStackTraceElement0 - * Signature: (Ljava/lang/StackTraceElement;)V - */ -JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_toStackTraceElement0 - (JNIEnv *env, jobject stackframeinfo, jobject stacktraceinfo) { - JVM_ToStackTraceElement(env, stackframeinfo, stacktraceinfo); -} diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/native/libjava/StackTraceElement.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/native/libjava/StackTraceElement.c Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,43 @@ +/* + * 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. 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. + */ + +#include +#include + +#include "jni.h" +#include "jvm.h" + +#include "java_lang_StackTraceElement.h" + +JNIEXPORT void JNICALL Java_java_lang_StackTraceElement_initStackTraceElement + (JNIEnv *env, jobject dummy, jobject element, jobject stackframeinfo) { + JVM_InitStackTraceElement(env, element, stackframeinfo); +} + +JNIEXPORT void JNICALL Java_java_lang_StackTraceElement_initStackTraceElements + (JNIEnv *env, jobject dummy, jobjectArray elements, jobject throwable) +{ + JVM_InitStackTraceElementArray(env, elements, throwable); +} diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.base/share/native/libjava/Throwable.c --- a/jdk/src/java.base/share/native/libjava/Throwable.c Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.base/share/native/libjava/Throwable.c Wed Jul 05 22:25:59 2017 +0200 @@ -49,10 +49,3 @@ JVM_FillInStackTrace(env, throwable); return throwable; } - -JNIEXPORT void JNICALL -Java_java_lang_Throwable_getStackTraceElements(JNIEnv *env, - jobject throwable, jobjectArray elements) -{ - JVM_GetStackTraceElements(env, throwable, elements); -} diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java --- a/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java Wed Jul 05 22:25:59 2017 +0200 @@ -74,8 +74,13 @@ this.fGraphicsStatesInt = this.fGraphicsStates.asIntBuffer(); this.fGraphicsStatesFloat = this.fGraphicsStates.asFloatBuffer(); this.fGraphicsStatesLong = this.fGraphicsStates.asLongBuffer(); - this.fGraphicsStatesObject = new Object[6]; // clip coordinates + clip types + texture paint image + stroke dash - // array + font + font paint + this.fGraphicsStatesObject = new Object[8]; // clip coordinates + + // clip types + + // texture paint image + + // stroke dash array + + // font + font paint + + // linear/radial gradient color + + // linear/radial gradient fractions // NOTE: All access to the DrawingQueue comes through this OSXSurfaceData instance. Therefore // every instance method of OSXSurfaceData that accesses the fDrawingQueue is synchronized. @@ -292,10 +297,10 @@ @Native static final int kHintsFractionalMetricsIndex = 46; @Native static final int kHintsRenderingIndex = 47; @Native static final int kHintsInterpolationIndex = 48; - // live resizing info - @Native static final int kCanDrawDuringLiveResizeIndex = 49; + //gradient info + @Native static final int kRadiusIndex = 49; - @Native static final int kSizeOfParameters = kCanDrawDuringLiveResizeIndex + 1; + @Native static final int kSizeOfParameters = kRadiusIndex + 1; // for objectParameters @Native static final int kClipCoordinatesIndex = 0; @@ -304,6 +309,8 @@ @Native static final int kStrokeDashArrayIndex = 3; @Native static final int kFontIndex = 4; @Native static final int kFontPaintIndex = 5; + @Native static final int kColorArrayIndex = 6; + @Native static final int kFractionsArrayIndex = 7; // possible state changes @Native static final int kBoundsChangedBit = 1 << 0; @@ -329,6 +336,8 @@ @Native static final int kColorSystem = 1; @Native static final int kColorGradient = 2; @Native static final int kColorTexture = 3; + @Native static final int kColorLinearGradient = 4; + @Native static final int kColorRadialGradient = 5; // possible gradient color states @Native static final int kColorNonCyclic = 0; @@ -522,6 +531,28 @@ int lastPaintIndex = 0; BufferedImage texturePaintImage = null; + void setGradientViaRasterPath(SunGraphics2D sg2d) { + if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) { + PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints()); + WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height)); + ColorModel cm = context.getColorModel(); + texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); + + this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture); + this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth()); + this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight()); + this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX()); + this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY()); + this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f); + this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f); + this.fGraphicsStatesObject[kTextureImageIndex] = OSXOffScreenSurfaceData.createNewSurface(texturePaintImage); + + this.fChangeFlag = (this.fChangeFlag | kColorChangedBit); + } else { + this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit); + } + } + void setupPaint(SunGraphics2D sg2d, int x, int y, int w, int h) { if (sg2d.paint instanceof SystemColor) { SystemColor color = (SystemColor) sg2d.paint; @@ -567,6 +598,75 @@ } else { this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit); } + } else if (sg2d.paint instanceof LinearGradientPaint) { + LinearGradientPaint color = (LinearGradientPaint) sg2d.paint; + if (color.getCycleMethod() == LinearGradientPaint.CycleMethod.NO_CYCLE) { + if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorLinearGradient) || (lastPaint != sg2d.paint)) { + + this.fGraphicsStatesInt.put(kColorStateIndex, kColorLinearGradient); + int numColor = color.getColors().length; + int colorArray[] = new int[numColor]; + for (int i = 0; i < numColor; i++) { + colorArray[i] = color.getColors()[i].getRGB(); + } + this.fGraphicsStatesObject[kColorArrayIndex] = colorArray; + + int numFractions = color.getFractions().length; + float fractionArray[] = new float[numFractions]; + for (int i = 0; i < numFractions; i++) { + fractionArray[i] = color.getFractions()[i]; + } + this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions(); + + Point2D p = color.getStartPoint(); + this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX()); + this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY()); + p = color.getEndPoint(); + this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX()); + this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY()); + + this.fChangeFlag = (this.fChangeFlag | kColorChangedBit); + } else { + this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit); + } + } else { + setGradientViaRasterPath(sg2d); + } + } else if (sg2d.paint instanceof RadialGradientPaint) { + RadialGradientPaint color = (RadialGradientPaint) sg2d.paint; + if (color.getCycleMethod() == RadialGradientPaint.CycleMethod.NO_CYCLE) { + if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorRadialGradient) || (lastPaint != sg2d.paint)) { + + this.fGraphicsStatesInt.put(kColorStateIndex, kColorRadialGradient); + int numColor = color.getColors().length; + int colorArray[] = new int[numColor]; + for (int i = 0; i < numColor; i++) { + colorArray[i] = color.getColors()[i].getRGB(); + } + this.fGraphicsStatesObject[kColorArrayIndex] = colorArray; + + int numStops = color.getFractions().length; + float stopsArray[] = new float[numStops]; + for (int i = 0; i < numStops; i++) { + stopsArray[i] = color.getFractions()[i]; + } + this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions(); + + Point2D p = color.getFocusPoint(); + this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX()); + this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY()); + p = color.getCenterPoint(); + this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX()); + this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY()); + this.fGraphicsStatesFloat.put(kRadiusIndex, color.getRadius()); + + this.fChangeFlag = (this.fChangeFlag | kColorChangedBit); + } else { + this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit); + } + } else { + setGradientViaRasterPath(sg2d); + } } else if (sg2d.paint instanceof TexturePaint) { if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint)) { TexturePaint color = (TexturePaint) sg2d.paint; @@ -587,27 +687,7 @@ this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit); } } else { - if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) { - PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints()); - WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height)); - ColorModel cm = context.getColorModel(); - texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); - - this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture); - this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth()); - this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight()); - this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX()); - this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY()); - this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f); - this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f); - this.fGraphicsStatesObject[kTextureImageIndex] = sun.awt.image.BufImgSurfaceData.createData(texturePaintImage); - - context.dispose(); - - this.fChangeFlag = (this.fChangeFlag | kColorChangedBit); - } else { - this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit); - } + setGradientViaRasterPath(sg2d); } lastPaint = sg2d.paint; } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Wed Jul 05 22:25:59 2017 +0200 @@ -178,12 +178,6 @@ return; } - // See if this has an NSPrintInfo in it. - NSPrintInfo nsPrintInfo = (NSPrintInfo)attributes.get(NSPrintInfo.class); - if (nsPrintInfo != null) { - fNSPrintInfo = nsPrintInfo.getValue(); - } - PageRanges pageRangesAttr = (PageRanges)attributes.get(PageRanges.class); if (isSupportedValue(pageRangesAttr, attributes)) { SunPageSelection rangeSelect = (SunPageSelection)attributes.get(SunPageSelection.class); @@ -563,8 +557,11 @@ @Override protected void finalize() { - if (fNSPrintInfo != -1) { - dispose(fNSPrintInfo); + synchronized (fNSPrintInfoLock) { + if (fNSPrintInfo != -1) { + dispose(fNSPrintInfo); + } + fNSPrintInfo = -1; } } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java Mon Nov 07 16:08:18 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2011, 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. 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.lwawt.macosx; - - -import java.io.*; -import javax.print.attribute.*; - -@SuppressWarnings("serial") // JDK implementation class -public final class NSPrintInfo implements PrintJobAttribute, PrintRequestAttribute, Serializable, Cloneable { - - private long fNSPrintInfo; - - public NSPrintInfo(long nsPrintInfo) { - fNSPrintInfo = nsPrintInfo; - } - - public long getValue() { - return fNSPrintInfo; - } - - public boolean equals(Object object) { - return (object != null && object instanceof NSPrintInfo && fNSPrintInfo == ((NSPrintInfo)object).fNSPrintInfo); - } - - public int hashCode() { - return (int)fNSPrintInfo; - } - - public String toString() { - return "" + fNSPrintInfo; - } - - public Class getCategory() { - return NSPrintInfo.class; - } - - public String getName() { - return "nsPrintInfo"; - } -} diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.h --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.h Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.h Wed Jul 05 22:25:59 2017 +0200 @@ -44,6 +44,8 @@ SD_Fill, SD_EOFill, SD_Shade, + SD_LinearGradient, + SD_RadialGradient, SD_Pattern, SD_Image, SD_Text, @@ -65,6 +67,17 @@ }; typedef struct _stateShadingInfo StateShadingInfo; +struct _stateGradientInfo +{ + CGPoint start; + CGPoint end; + CGFloat radius; + CGFloat* colordata; + CGFloat* fractionsdata; + jint fractionsLength; +}; +typedef struct _stateGradientInfo StateGradientInfo; + struct _statePatternInfo { CGFloat tx; @@ -122,6 +135,7 @@ // its callees. StateShadingInfo* shadingInfo; // tracks shading and its parameters + StateGradientInfo* gradientInfo; // tracks gradient and its parameters StatePatternInfo* patternInfo; // tracks pattern and its parameters StateGraphicsInfo graphicsStateInfo; // tracks other graphics state diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m Wed Jul 05 22:25:59 2017 +0200 @@ -268,9 +268,105 @@ free(info); } +static inline void contextQuartzLinearGradientPath(QuartzSDOps* qsdo) +{ + +PRINT(" contextQuartzLinearGradientPath"); + + CGContextRef cgRef = qsdo->cgRef; + StateGradientInfo *gradientInfo = qsdo->gradientInfo; + + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + size_t num_locations = gradientInfo->fractionsLength; + CGFloat *locations = (CGFloat *) malloc(sizeof(CGFloat) * num_locations); + int i = 0; + size_t component_size = num_locations * 4; + CGFloat components[component_size]; + CGGradientRef gradient = NULL; + + for (int i = 0; i < num_locations; i++) { + locations[i] = gradientInfo->fractionsdata[i]; +//fprintf(stderr, "locations[%d] %f\n", i, locations[i]); + } + for (i = 0; i < component_size; i++) { + components[i] = gradientInfo->colordata[i]; +//fprintf(stderr, "components[%d] %f, gradientInfo->colordata[%d] %f\n", +// i, components[i], i, gradientInfo->colordata[i]); + } + CGContextSaveGState(cgRef); + gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations); +//fprintf(stderr, "gradientInfo->start.x %f, gradientInfo->start.y %f\n", +// gradientInfo->start.x, gradientInfo->start.y); +//fprintf(stderr, "gradientInfo->end.x %f, gradientInfo->end.y %f\n", +// gradientInfo->end.x, gradientInfo->end.y); + if (qsdo->isEvenOddFill) { + CGContextEOClip(cgRef); + } else { + CGContextClip(cgRef); + } + CGContextDrawLinearGradient(cgRef, gradient, gradientInfo->start, gradientInfo->end, kCGGradientDrawsAfterEndLocation); + + CGContextRestoreGState(cgRef); + CGColorSpaceRelease(colorspace); + CGGradientRelease(gradient); + free(locations); + free(gradientInfo->colordata); + free(gradientInfo->fractionsdata); +} + +static inline void contextQuartzRadialGradientPath(QuartzSDOps* qsdo) +{ + +PRINT(" contextQuartzRadialGradientPath"); + + CGContextRef cgRef = qsdo->cgRef; + StateGradientInfo *gradientInfo = qsdo->gradientInfo; + + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + size_t num_locations = gradientInfo->fractionsLength; + CGFloat *locations = (CGFloat *) malloc(sizeof(CGFloat) * num_locations); + int i = 0; + size_t component_size = num_locations * 4; + CGFloat components[component_size]; + CGGradientRef gradient = NULL; + CGFloat startRadius = gradientInfo->radius; + CGFloat endRadius = gradientInfo->radius; + + for (int i = 0; i < num_locations; i++) { + locations[i] = gradientInfo->fractionsdata[i]; +//fprintf(stderr, "locations[%d] %f\n", i, locations[i]); + } + for (i = 0; i < component_size; i++) { + components[i] = gradientInfo->colordata[i]; +//fprintf(stderr, "components[%d] %f, gradientInfo->colordata[%d] %f\n", +// i, components[i], i, gradientInfo->colordata[i]); + } + CGContextSaveGState(cgRef); + gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations); +//fprintf(stderr, "gradientInfo->start.x %f, gradientInfo->start.y %f\n", +// gradientInfo->start.x, gradientInfo->start.y); +//fprintf(stderr, "gradientInfo->end.x %f, gradientInfo->end.y %f\n", +// gradientInfo->end.x, gradientInfo->end.y); + if (qsdo->isEvenOddFill) { + CGContextEOClip(cgRef); + } else { + CGContextClip(cgRef); + } +//fprintf(stderr, "gradientInfo->startRadius %f, gradientInfo->endRadius %f\n",startRadius,endRadius); + CGContextDrawRadialGradient(cgRef, gradient, gradientInfo->start, 0, gradientInfo->end, endRadius, kCGGradientDrawsAfterEndLocation); + + CGContextRestoreGState(cgRef); + CGColorSpaceRelease(colorspace); + CGGradientRelease(gradient); + free(locations); + free(gradientInfo->colordata); + free(gradientInfo->fractionsdata); +} + static inline void contextGradientPath(QuartzSDOps* qsdo) { PRINT(" ContextGradientPath") + CGContextRef cgRef = qsdo->cgRef; StateShadingInfo* shadingInfo = qsdo->shadingInfo; @@ -827,6 +923,81 @@ qsdo->renderType = renderType; } +void setupGradient(JNIEnv *env, QuartzSDOps* qsdo, jfloat* javaFloatGraphicsStates) +{ + static const CGFloat kColorConversionMultiplier = 1.0f/255.0f; + qsdo->gradientInfo = (StateGradientInfo*)malloc(sizeof(StateGradientInfo)); + if (qsdo->gradientInfo == NULL) + { + [JNFException raise:env as:kOutOfMemoryError reason:"Failed to malloc memory for gradient paint"]; + } + + qsdo->graphicsStateInfo.simpleStroke = NO; + qsdo->graphicsStateInfo.simpleColor = NO; + + qsdo->gradientInfo->start.x = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColorx1Index]; + qsdo->gradientInfo->start.y = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColory1Index]; + qsdo->gradientInfo->end.x = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColorx2Index]; + qsdo->gradientInfo->end.y = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColory2Index]; + + jobject colorArray = ((*env)->GetObjectArrayElement(env, qsdo->javaGraphicsStatesObjects, sun_java2d_OSXSurfaceData_kColorArrayIndex)); + if (colorArray != NULL) + { + jint length = (*env)->GetArrayLength(env, colorArray); +//fprintf(stderr, "length %d\n", length); + + jint* jcolorData = (jint*)(*env)->GetPrimitiveArrayCritical(env, colorArray, NULL); + CGFloat* colors= (CGFloat*)calloc(0, sizeof(CGFloat)*length); + if (jcolorData != NULL) + { + jint i; + for (i=0; iReleasePrimitiveArrayCritical(env, colorArray, jcolorData, 0); + qsdo->gradientInfo->colordata = (CGFloat*)calloc(0, sizeof(CGFloat)*4*length); + for (int i = 0; i < length; i++) + { + jint c1 = colors[i]; +//fprintf(stderr, "c1 %x\n", c1); + qsdo->gradientInfo->colordata[i*4] = ((c1>>16)&0xff)*kColorConversionMultiplier; +//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4, qsdo->gradientInfo->colordata[i*4]); + + qsdo->gradientInfo->colordata[i*4+1] = ((c1>>8)&0xff)*kColorConversionMultiplier; +//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+1, qsdo->gradientInfo->colordata[i*4+1]); + + qsdo->gradientInfo->colordata[i*4+2] = ((c1>>0)&0xff)*kColorConversionMultiplier; +//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+2, qsdo->gradientInfo->colordata[i*4+2]); + + qsdo->gradientInfo->colordata[i*4+3] = ((c1>>24)&0xff)*kColorConversionMultiplier; +//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+3, qsdo->gradientInfo->colordata[i*4+3]); + } + free(colors); + } + jobject fractionsArray = ((*env)->GetObjectArrayElement(env, qsdo->javaGraphicsStatesObjects, sun_java2d_OSXSurfaceData_kFractionsArrayIndex)); + if (fractionsArray != NULL) + { + jint length = (*env)->GetArrayLength(env, fractionsArray); +//fprintf(stderr, "fractions length %d\n", length); + qsdo->gradientInfo->fractionsLength = length; + + jfloat* jfractionsData = (jfloat*)(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL); + if (jfractionsData != NULL) + { + qsdo->gradientInfo->fractionsdata = (CGFloat *)malloc(sizeof(CGFloat) *length); + jint i; + for (i=0; igradientInfo->fractionsdata[i] = jfractionsData[i]; +//fprintf(stderr, "jfrationsData[%d] %f, qsdo->gradientInfo->fractionsdata[%d] = %f\n", i, jfractionsData[i], i, qsdo->gradientInfo->fractionsdata[i]); + } + (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, jfractionsData, 0); + } + } +} + SDRenderType SetUpPaint(JNIEnv *env, QuartzSDOps *qsdo, SDRenderType renderType) { CGContextRef cgRef = qsdo->cgRef; @@ -898,6 +1069,21 @@ break; } + case sun_java2d_OSXSurfaceData_kColorLinearGradient: + { + renderType = SD_LinearGradient; + setupGradient(env, qsdo, javaFloatGraphicsStates); + break; + } + + case sun_java2d_OSXSurfaceData_kColorRadialGradient: + { + renderType = SD_RadialGradient; + setupGradient(env, qsdo, javaFloatGraphicsStates); + qsdo->gradientInfo->radius = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kRadiusIndex]; + break; + } + case sun_java2d_OSXSurfaceData_kColorTexture: { qsdo->patternInfo = (StatePatternInfo*)malloc(sizeof(StatePatternInfo)); @@ -1076,11 +1262,24 @@ } break; + case SD_LinearGradient: + if (CGContextIsPathEmpty(qsdo->cgRef) == 0) + { + contextQuartzLinearGradientPath(qsdo); + } + break; + + case SD_RadialGradient: + if (CGContextIsPathEmpty(qsdo->cgRef) == 0) + { + contextQuartzRadialGradientPath(qsdo); + } + break; + case SD_Pattern: if (CGContextIsPathEmpty(qsdo->cgRef) == 0) { - //TODO:BG - //contextTexturePath(env, qsdo); + contextTexturePath(env, qsdo); } break; @@ -1111,4 +1310,8 @@ gradientPaintReleaseFunction(qsdo->shadingInfo); qsdo->shadingInfo = NULL; } + if (qsdo->gradientInfo != NULL) { + gradientPaintReleaseFunction(qsdo->gradientInfo); + qsdo->gradientInfo = NULL; + } } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/imageio/package.html --- a/jdk/src/java.desktop/share/classes/javax/imageio/package.html Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/package.html Wed Jul 05 22:25:59 2017 +0200 @@ -2,7 +2,7 @@ + + BMP + yes + yes + none + + BMP metadata format + + + + GIF + yes + yes + + GIF plug-in notes + + GIF metadata format + JPEG @@ -76,14 +95,15 @@ PNG metadata format - + - BMP + TIFF yes yes - none - - BMP metadata format + + TIFF plug-in notes + + TIFF metadata format @@ -94,16 +114,6 @@ WBMP metadata format - - - GIF - yes - yes - - GIF plug-in notes - - GIF metadata format -
diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java Wed Jul 05 22:25:59 2017 +0200 @@ -55,9 +55,7 @@ * * @see #TAG_GPS_VERSION_ID */ - public static final String GPS_VERSION_2_2 = - new String(new byte[] { '2', '2', '0', '0' }, - StandardCharsets.US_ASCII); + public static final String GPS_VERSION_2_2 = "2200"; /** * A tag indicating the North or South latitude (type ASCII, count = 2). diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java Wed Jul 05 22:25:59 2017 +0200 @@ -71,9 +71,7 @@ * * @see #TAG_EXIF_VERSION */ - public static final String EXIF_VERSION_2_1 = - new String(new byte[] { '0', '2', '1', '0' }, - StandardCharsets.US_ASCII); + public static final String EXIF_VERSION_2_1 = "0210"; /** * A value to be used with the "ExifVersion" tag to indicate Exif version @@ -82,9 +80,7 @@ * * @see #TAG_EXIF_VERSION */ - public static final String EXIF_VERSION_2_2 = - new String(new byte[] { '0', '2', '2', '0' }, - StandardCharsets.US_ASCII); + public static final String EXIF_VERSION_2_2 = "0220"; /** * A tag indicating the FlashPix version number (type UNDEFINED, diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java Wed Jul 05 22:25:59 2017 +0200 @@ -261,7 +261,7 @@ * @see TIFFDirectory * @see TIFFTag */ -public class TIFFField implements Cloneable { +public final class TIFFField implements Cloneable { private static final String[] typeNames = { null, diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java Wed Jul 05 22:25:59 2017 +0200 @@ -48,7 +48,7 @@ * * @since 9 */ -public class TIFFImageReadParam extends ImageReadParam { +public final class TIFFImageReadParam extends ImageReadParam { private List allowedTagSets = new ArrayList(4); diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/swing/JRootPane.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JRootPane.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JRootPane.java Wed Jul 05 22:25:59 2017 +0200 @@ -320,28 +320,6 @@ * a UI-specific action like pressing the Enter key occurs. */ protected JButton defaultButton; - /** - * As of Java 2 platform v1.3 this unusable field is no longer used. - * To override the default button you should replace the Action - * in the JRootPane's ActionMap. Please refer to - * the key bindings specification for further details. - * - * @deprecated As of Java 2 platform v1.3. - * @see #defaultButton - */ - @Deprecated - protected DefaultAction defaultPressAction; - /** - * As of Java 2 platform v1.3 this unusable field is no longer used. - * To override the default button you should replace the Action - * in the JRootPane's ActionMap. Please refer to - * the key bindings specification for further details. - * - * @deprecated As of Java 2 platform v1.3. - * @see #defaultButton - */ - @Deprecated - protected DefaultAction defaultReleaseAction; /** * Whether or not true double buffering should be used. This is typically @@ -829,35 +807,6 @@ } } - @SuppressWarnings("serial") - static class DefaultAction extends AbstractAction { - JButton owner; - JRootPane root; - boolean press; - DefaultAction(JRootPane root, boolean press) { - this.root = root; - this.press = press; - } - public void setOwner(JButton owner) { - this.owner = owner; - } - public void actionPerformed(ActionEvent e) { - if (owner != null && SwingUtilities.getRootPane(owner) == root) { - ButtonModel model = owner.getModel(); - if (press) { - model.setArmed(true); - model.setPressed(true); - } else { - model.setPressed(false); - } - } - } - public boolean isEnabled() { - return owner.getModel().isEnabled(); - } - } - - /** * Overridden to enforce the position of the glass component as * the zero child. diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java Wed Jul 05 22:25:59 2017 +0200 @@ -739,7 +739,7 @@ /** * The instance of {@code MetalBumps}. */ - protected MetalBumps bumps = new MetalBumps( 10, 10, + private MetalBumps bumps = new MetalBumps( 10, 10, MetalLookAndFeel.getControlHighlight(), MetalLookAndFeel.getControlDarkShadow(), UIManager.getColor("ToolBar.background")); diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java Wed Jul 05 22:25:59 2017 +0200 @@ -923,7 +923,7 @@ * @param fc a {@code JFileChooser} * @return a new instance of {@code DirectoryComboBoxRenderer} */ - protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) { + private DefaultListCellRenderer createDirectoryComboBoxRenderer(JFileChooser fc) { return new DirectoryComboBoxRenderer(); } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java Wed Jul 05 22:25:59 2017 +0200 @@ -62,7 +62,7 @@ /** * The metal bumps. */ - protected MetalBumps bumps; + private MetalBumps bumps; /** * The increase button. diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java --- a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java Wed Jul 05 22:25:59 2017 +0200 @@ -30,6 +30,9 @@ import java.awt.Toolkit; import java.io.*; import java.io.FileNotFoundException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; import java.util.*; import java.util.concurrent.Callable; @@ -243,7 +246,8 @@ if (file instanceof ShellFolder) { return (ShellFolder)file; } - if (!file.exists()) { + + if (!Files.exists(file.toPath(), LinkOption.NOFOLLOW_LINKS)) { throw new FileNotFoundException(); } return shellFolderManager.createShellFolder(file); diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/sun/font/NullFontScaler.java --- a/jdk/src/java.desktop/share/classes/sun/font/NullFontScaler.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/sun/font/NullFontScaler.java Wed Jul 05 22:25:59 2017 +0200 @@ -36,8 +36,8 @@ boolean supportsCJK, int filesize) {} StrikeMetrics getFontMetrics(long pScalerContext) { - return new StrikeMetrics(0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, - 0xf0,0xf0,0xf0,0xf0); + return new StrikeMetrics(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f); } float getGlyphAdvance(long pScalerContext, int glyphCode) { @@ -71,7 +71,7 @@ return getNullScalerContext(); } - void invalidateScalerContext(long ppScalerContext) { + void invalidateScalerContext(long pScalerContext) { //nothing to do } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.desktop/share/classes/sun/swing/plaf/GTKKeybindings.java --- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/GTKKeybindings.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/GTKKeybindings.java Wed Jul 05 22:25:59 2017 +0200 @@ -219,6 +219,38 @@ "KP_UP", "selectPrevious" }), + "Desktop.ancestorInputMap", + new UIDefaults.LazyInputMap(new Object[] { + "ctrl F5", "restore", + "ctrl F4", "close", + "ctrl F7", "move", + "ctrl F8", "resize", + "RIGHT", "right", + "KP_RIGHT", "right", + "shift RIGHT", "shrinkRight", + "shift KP_RIGHT", "shrinkRight", + "LEFT", "left", + "KP_LEFT", "left", + "shift LEFT", "shrinkLeft", + "shift KP_LEFT", "shrinkLeft", + "UP", "up", + "KP_UP", "up", + "shift UP", "shrinkUp", + "shift KP_UP", "shrinkUp", + "DOWN", "down", + "KP_DOWN", "down", + "shift DOWN", "shrinkDown", + "shift KP_DOWN", "shrinkDown", + "ESCAPE", "escape", + "ctrl F9", "minimize", + "ctrl F10", "maximize", + "ctrl F6", "selectNextFrame", + "ctrl TAB", "selectNextFrame", + "ctrl alt F6", "selectNextFrame", + "shift ctrl alt F6", "selectPreviousFrame", + "ctrl F12", "navigateNext", + "shift ctrl F12", "navigatePrevious" + }), "EditorPane.focusInputMap", multilineInputMap, "FileChooser.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[]{ diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java --- a/jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java Wed Jul 05 22:25:59 2017 +0200 @@ -58,7 +58,8 @@ getString(cd, FILE_NAME), getInt(cd, LINE_NUMBER)); } else { - return new StackTraceElement(getString(cd, MODULE_NAME), + return new StackTraceElement(getString(cd, CLASS_LOADER_NAME), + getString(cd, MODULE_NAME), getString(cd, MODULE_VERSION), getString(cd, CLASS_NAME), getString(cd, METHOD_NAME), @@ -76,13 +77,14 @@ // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH // stackTraceElementItemNames! final Object[] stackTraceElementItemValues = { + ste.getClassLoaderName(), + ste.getModuleName(), + ste.getModuleVersion(), ste.getClassName(), ste.getMethodName(), ste.getFileName(), ste.getLineNumber(), ste.isNativeMethod(), - ste.getModuleName(), - ste.getModuleVersion(), }; try { return new CompositeDataSupport(stackTraceElementCompositeType, @@ -95,25 +97,29 @@ } // Attribute names - private static final String CLASS_NAME = "className"; - private static final String METHOD_NAME = "methodName"; - private static final String FILE_NAME = "fileName"; - private static final String LINE_NUMBER = "lineNumber"; - private static final String NATIVE_METHOD = "nativeMethod"; - private static final String MODULE_NAME = "moduleName"; - private static final String MODULE_VERSION = "moduleVersion"; + private static final String CLASS_LOADER_NAME = "classLoaderName"; + private static final String MODULE_NAME = "moduleName"; + private static final String MODULE_VERSION = "moduleVersion"; + private static final String CLASS_NAME = "className"; + private static final String METHOD_NAME = "methodName"; + private static final String FILE_NAME = "fileName"; + private static final String LINE_NUMBER = "lineNumber"; + private static final String NATIVE_METHOD = "nativeMethod"; + private static final String[] stackTraceElementItemNames = { + CLASS_LOADER_NAME, + MODULE_NAME, + MODULE_VERSION, CLASS_NAME, METHOD_NAME, FILE_NAME, LINE_NUMBER, NATIVE_METHOD, - MODULE_NAME, - MODULE_VERSION, }; private static final String[] stackTraceElementV9ItemNames = { + CLASS_LOADER_NAME, MODULE_NAME, MODULE_VERSION, }; diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java Wed Jul 05 22:25:59 2017 +0200 @@ -102,6 +102,11 @@ AccessController.doPrivileged((PrivilegedAction) () -> Long.getLong("sun.rmi.transport.tcp.threadKeepAliveTime", 60000)); + /** enable multiplexing protocol */ + private static final boolean enableMultiplexProtocol = // default false + AccessController.doPrivileged((PrivilegedAction) () -> + Boolean.getBoolean("sun.rmi.transport.tcp.enableMultiplexProtocol")); + /** thread pool for connection handlers */ private static final ExecutorService connectionThreadPool = new ThreadPoolExecutor(0, maxConnectionThreads, @@ -796,6 +801,19 @@ break; case TransportConstants.MultiplexProtocol: + + if (!enableMultiplexProtocol) { + if (tcpLog.isLoggable(Log.VERBOSE)) { + tcpLog.log(Log.VERBOSE, "(port " + port + + ") rejecting multiplex protocol"); + } + + // If MultiplexProtocol is disabled, send NACK immediately. + out.writeByte(TransportConstants.ProtocolNack); + out.flush(); + break; + } + if (tcpLog.isLoggable(Log.VERBOSE)) { tcpLog.log(Log.VERBOSE, "(port " + port + ") accepting multiplex protocol"); diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.sql/share/classes/java/sql/CallableStatement.java --- a/jdk/src/java.sql/share/classes/java/sql/CallableStatement.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.sql/share/classes/java/sql/CallableStatement.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -295,7 +295,7 @@ * or getBigDecimal(String parameterName) * @see #setBigDecimal */ - @Deprecated + @Deprecated(since="1.2") BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException; diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.sql/share/classes/java/sql/Date.java --- a/jdk/src/java.sql/share/classes/java/sql/Date.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.sql/share/classes/java/sql/Date.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -58,7 +58,7 @@ * @param day 1 to 31 * @deprecated instead use the constructor Date(long date) */ - @Deprecated + @Deprecated(since="1.2") public Date(int year, int month, int day) { super(year, month, day); } @@ -199,7 +199,7 @@ * @exception java.lang.IllegalArgumentException if this method is invoked * @see #setHours */ - @Deprecated + @Deprecated(since="1.2") public int getHours() { throw new java.lang.IllegalArgumentException(); } @@ -212,7 +212,7 @@ * @exception java.lang.IllegalArgumentException if this method is invoked * @see #setMinutes */ - @Deprecated + @Deprecated(since="1.2") public int getMinutes() { throw new java.lang.IllegalArgumentException(); } @@ -225,7 +225,7 @@ * @exception java.lang.IllegalArgumentException if this method is invoked * @see #setSeconds */ - @Deprecated + @Deprecated(since="1.2") public int getSeconds() { throw new java.lang.IllegalArgumentException(); } @@ -238,7 +238,7 @@ * @exception java.lang.IllegalArgumentException if this method is invoked * @see #getHours */ - @Deprecated + @Deprecated(since="1.2") public void setHours(int i) { throw new java.lang.IllegalArgumentException(); } @@ -251,7 +251,7 @@ * @exception java.lang.IllegalArgumentException if this method is invoked * @see #getMinutes */ - @Deprecated + @Deprecated(since="1.2") public void setMinutes(int i) { throw new java.lang.IllegalArgumentException(); } @@ -264,7 +264,7 @@ * @exception java.lang.IllegalArgumentException if this method is invoked * @see #getSeconds */ - @Deprecated + @Deprecated(since="1.2") public void setSeconds(int i) { throw new java.lang.IllegalArgumentException(); } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.sql/share/classes/java/sql/DriverManager.java --- a/jdk/src/java.sql/share/classes/java/sql/DriverManager.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.sql/share/classes/java/sql/DriverManager.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -515,7 +515,7 @@ * @see SecurityManager#checkPermission * @see #getLogStream */ - @Deprecated + @Deprecated(since="1.2") public static void setLogStream(java.io.PrintStream out) { SecurityManager sec = System.getSecurityManager(); @@ -538,7 +538,7 @@ * @deprecated Use {@code getLogWriter} * @see #setLogStream */ - @Deprecated + @Deprecated(since="1.2") public static java.io.PrintStream getLogStream() { return logStream; } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.sql/share/classes/java/sql/PreparedStatement.java --- a/jdk/src/java.sql/share/classes/java/sql/PreparedStatement.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.sql/share/classes/java/sql/PreparedStatement.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -344,7 +344,7 @@ * this method * @deprecated Use {@code setCharacterStream} */ - @Deprecated + @Deprecated(since="1.2") void setUnicodeStream(int parameterIndex, java.io.InputStream x, int length) throws SQLException; diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.sql/share/classes/java/sql/ResultSet.java --- a/jdk/src/java.sql/share/classes/java/sql/ResultSet.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.sql/share/classes/java/sql/ResultSet.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -358,7 +358,7 @@ * @deprecated Use {@code getBigDecimal(int columnIndex)} * or {@code getBigDecimal(String columnLabel)} */ - @Deprecated + @Deprecated(since="1.2") BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException; /** @@ -478,7 +478,7 @@ * @deprecated use getCharacterStream in place of * getUnicodeStream */ - @Deprecated + @Deprecated(since="1.2") java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException; /** @@ -646,7 +646,7 @@ * @deprecated Use {@code getBigDecimal(int columnIndex)} * or {@code getBigDecimal(String columnLabel)} */ - @Deprecated + @Deprecated(since="1.2") BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException; /** @@ -764,7 +764,7 @@ * this method * @deprecated use getCharacterStream instead */ - @Deprecated + @Deprecated(since="1.2") java.io.InputStream getUnicodeStream(String columnLabel) throws SQLException; /** diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.sql/share/classes/java/sql/Time.java --- a/jdk/src/java.sql/share/classes/java/sql/Time.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.sql/share/classes/java/sql/Time.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -60,7 +60,7 @@ * @deprecated Use the constructor that takes a milliseconds value * in place of this constructor */ - @Deprecated + @Deprecated(since="1.2") public Time(int hour, int minute, int second) { super(70, 0, 1, hour, minute, second); } @@ -146,7 +146,7 @@ * method is invoked * @see #setYear */ - @Deprecated + @Deprecated(since="1.2") public int getYear() { throw new java.lang.IllegalArgumentException(); } @@ -160,7 +160,7 @@ * method is invoked * @see #setMonth */ - @Deprecated + @Deprecated(since="1.2") public int getMonth() { throw new java.lang.IllegalArgumentException(); } @@ -173,7 +173,7 @@ * @exception java.lang.IllegalArgumentException if this * method is invoked */ - @Deprecated + @Deprecated(since="1.2") public int getDay() { throw new java.lang.IllegalArgumentException(); } @@ -187,7 +187,7 @@ * method is invoked * @see #setDate */ - @Deprecated + @Deprecated(since="1.2") public int getDate() { throw new java.lang.IllegalArgumentException(); } @@ -201,7 +201,7 @@ * method is invoked * @see #getYear */ - @Deprecated + @Deprecated(since="1.2") public void setYear(int i) { throw new java.lang.IllegalArgumentException(); } @@ -215,7 +215,7 @@ * method is invoked * @see #getMonth */ - @Deprecated + @Deprecated(since="1.2") public void setMonth(int i) { throw new java.lang.IllegalArgumentException(); } @@ -229,7 +229,7 @@ * method is invoked * @see #getDate */ - @Deprecated + @Deprecated(since="1.2") public void setDate(int i) { throw new java.lang.IllegalArgumentException(); } diff -r a4ee110842fb -r 8750872276b8 jdk/src/java.sql/share/classes/java/sql/Timestamp.java --- a/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -88,7 +88,7 @@ * @deprecated instead use the constructor {@code Timestamp(long millis)} * @exception IllegalArgumentException if the nano argument is out of bounds */ - @Deprecated + @Deprecated(since="1.2") public Timestamp(int year, int month, int date, int hour, int minute, int second, int nano) { super(year, month, date, hour, minute, second); diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.editpad/share/classes/jdk/editpad/EditPad.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.editpad/share/classes/jdk/editpad/EditPad.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,149 @@ +/* + * 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 + * 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 jdk.editpad; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.function.Consumer; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +/** + * A minimal Swing editor as a fallback when the user does not specify an + * external editor. + */ +class EditPad implements Runnable { + + private static final String L10N_RB_NAME = "jdk.editpad.resources.l10n"; + private ResourceBundle rb = null; + private final String windowLabel; + private final Consumer errorHandler; + private final String initialText; + private final Runnable closeMark; + private final Consumer saveHandler; + + /** + * Create an Edit Pad minimal editor. + * + * @param windowLabel the label string for the Edit Pad window + * @param errorHandler a handler for unexpected errors + * @param initialText the source to load in the Edit Pad + * @param closeMark a Runnable that is run when Edit Pad closes + * @param saveHandler a handler for changed source (sent the full source) + */ + EditPad(String windowLabel, Consumer errorHandler, String initialText, + Runnable closeMark, Consumer saveHandler) { + this.windowLabel = windowLabel; + this.errorHandler = errorHandler; + this.initialText = initialText; + this.closeMark = closeMark; + this.saveHandler = saveHandler; + } + + @Override + public void run() { + JFrame jframe = new JFrame(windowLabel == null + ? getResourceString("editpad.name") + : windowLabel); + Runnable closer = () -> { + jframe.setVisible(false); + jframe.dispose(); + closeMark.run(); + }; + jframe.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + closer.run(); + } + }); + jframe.setLocationRelativeTo(null); + jframe.setLayout(new BorderLayout()); + JTextArea textArea = new JTextArea(initialText); + textArea.setFont(new Font("monospaced", Font.PLAIN, 13)); + jframe.add(new JScrollPane(textArea), BorderLayout.CENTER); + jframe.add(buttons(closer, textArea), BorderLayout.SOUTH); + + jframe.setSize(800, 600); + jframe.setVisible(true); + } + + private JPanel buttons(Runnable closer, JTextArea textArea) { + FlowLayout flow = new FlowLayout(); + flow.setHgap(35); + JPanel buttons = new JPanel(flow); + addButton(buttons, "editpad.cancel", KeyEvent.VK_C, e -> { + closer.run(); + }); + addButton(buttons, "editpad.accept", KeyEvent.VK_A, e -> { + saveHandler.accept(textArea.getText()); + }); + addButton(buttons, "editpad.exit", KeyEvent.VK_X, e -> { + saveHandler.accept(textArea.getText()); + closer.run(); + }); + return buttons; + } + + private void addButton(JPanel buttons, String rkey, int mnemonic, ActionListener action) { + JButton but = new JButton(getResourceString(rkey)); + but.setMnemonic(mnemonic); + buttons.add(but); + but.addActionListener(action); + } + + private String getResourceString(String key) { + if (rb == null) { + try { + rb = ResourceBundle.getBundle(L10N_RB_NAME); + } catch (MissingResourceException mre) { + error("Cannot find ResourceBundle: %s", L10N_RB_NAME); + return ""; + } + } + String s; + try { + s = rb.getString(key); + } catch (MissingResourceException mre) { + error("Missing resource: %s in %s", key, L10N_RB_NAME); + return ""; + } + return s; + } + + private void error(String fmt, Object... args) { + errorHandler.accept(String.format(fmt, args)); + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.editpad/share/classes/jdk/editpad/EditPadProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.editpad/share/classes/jdk/editpad/EditPadProvider.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,72 @@ +/* + * 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. 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 jdk.editpad; + +import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; +import javax.swing.SwingUtilities; +import jdk.internal.editor.spi.BuildInEditorProvider; + +/** + * Defines the provider of an Edit Pad implementation. + * + * @author Robert Field + */ +public class EditPadProvider implements BuildInEditorProvider { + + /** + * @return the rank of a provider, greater is better. + */ + @Override + public int rank() { + return 5; + } + + /** + * Create an Edit Pad minimal editor. + * + * @param windowLabel the label string for the Edit Pad window, or null, + * for default window label + * @param initialText the source to load in the Edit Pad + * @param saveHandler a handler for changed source (can be sent the full source) + * @param errorHandler a handler for unexpected errors + */ + @Override + public void edit(String windowLabel, String initialText, + Consumer saveHandler, Consumer errorHandler) { + CountDownLatch closeLock = new CountDownLatch(1); + SwingUtilities.invokeLater( + new EditPad(windowLabel, errorHandler, initialText, closeLock::countDown, saveHandler)); + do { + try { + closeLock.await(); + break; + } catch (InterruptedException ex) { + // ignore and loop + } + } while (true); + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.editpad/share/classes/jdk/editpad/resources/l10n.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.editpad/share/classes/jdk/editpad/resources/l10n.properties Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,29 @@ +# +# 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. 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. +# + +editpad.name = Edit Pad +editpad.cancel = Cancel +editpad.accept = Accept +editpad.exit = Exit diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.editpad/share/classes/module-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.editpad/share/classes/module-info.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,34 @@ +/* + * 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. 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. + */ + +/** + * Implementation of the edit pad service. + */ +module jdk.editpad { + requires jdk.internal.ed; + requires java.desktop; + provides jdk.internal.editor.spi.BuildInEditorProvider + with jdk.editpad.EditPadProvider; +} diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.internal.ed/share/classes/jdk/internal/editor/external/ExternalEditor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.ed/share/classes/jdk/internal/editor/external/ExternalEditor.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,192 @@ +/* + * 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 + * 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 jdk.internal.editor.external; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.ClosedWatchServiceException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.util.Arrays; +import java.util.Scanner; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; +import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; +import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; + +/** + * Wrapper for controlling an external editor. + */ +public class ExternalEditor { + private final Consumer errorHandler; + private final Consumer saveHandler; + private final boolean wait; + + private final Runnable suspendInteractiveInput; + private final Runnable resumeInteractiveInput; + private final Runnable promptForNewLineToEndWait; + + private WatchService watcher; + private Thread watchedThread; + private Path dir; + private Path tmpfile; + + /** + * Launch an external editor. + * + * @param cmd the command to launch (with parameters) + * @param initialText initial text in the editor buffer + * @param errorHandler handler for error messages + * @param saveHandler handler sent the buffer contents on save + * @param suspendInteractiveInput a callback to suspend caller (shell) input + * @param resumeInteractiveInput a callback to resume caller input + * @param wait true, if editor process termination cannot be used to + * determine when done + * @param promptForNewLineToEndWait a callback to prompt for newline if + * wait==true + */ + public static void edit(String[] cmd, String initialText, + Consumer errorHandler, + Consumer saveHandler, + Runnable suspendInteractiveInput, + Runnable resumeInteractiveInput, + boolean wait, + Runnable promptForNewLineToEndWait) { + ExternalEditor ed = new ExternalEditor(errorHandler, saveHandler, suspendInteractiveInput, + resumeInteractiveInput, wait, promptForNewLineToEndWait); + ed.edit(cmd, initialText); + } + + ExternalEditor(Consumer errorHandler, + Consumer saveHandler, + Runnable suspendInteractiveInput, + Runnable resumeInteractiveInput, + boolean wait, + Runnable promptForNewLineToEndWait) { + this.errorHandler = errorHandler; + this.saveHandler = saveHandler; + this.wait = wait; + this.suspendInteractiveInput = suspendInteractiveInput; + this.resumeInteractiveInput = resumeInteractiveInput; + this.promptForNewLineToEndWait = promptForNewLineToEndWait; + } + + private void edit(String[] cmd, String initialText) { + try { + setupWatch(initialText); + launch(cmd); + } catch (IOException ex) { + errorHandler.accept(ex.getMessage()); + } + } + + /** + * Creates a WatchService and registers the given directory + */ + private void setupWatch(String initialText) throws IOException { + this.watcher = FileSystems.getDefault().newWatchService(); + this.dir = Files.createTempDirectory("extedit"); + this.tmpfile = Files.createTempFile(dir, null, ".java"); + Files.write(tmpfile, initialText.getBytes(Charset.forName("UTF-8"))); + dir.register(watcher, + ENTRY_CREATE, + ENTRY_DELETE, + ENTRY_MODIFY); + watchedThread = new Thread(() -> { + for (;;) { + WatchKey key; + try { + key = watcher.take(); + } catch (ClosedWatchServiceException ex) { + // The watch service has been closed, we are done + break; + } catch (InterruptedException ex) { + // tolerate an interrupt + continue; + } + + if (!key.pollEvents().isEmpty()) { + saveFile(); + } + + boolean valid = key.reset(); + if (!valid) { + // The watch service has been closed, we are done + break; + } + } + }); + watchedThread.start(); + } + + private void launch(String[] cmd) throws IOException { + String[] params = Arrays.copyOf(cmd, cmd.length + 1); + params[cmd.length] = tmpfile.toString(); + ProcessBuilder pb = new ProcessBuilder(params); + pb = pb.inheritIO(); + + try { + suspendInteractiveInput.run(); + Process process = pb.start(); + // wait to exit edit mode in one of these ways... + if (wait) { + // -wait option -- ignore process exit, wait for carriage-return + Scanner scanner = new Scanner(System.in); + promptForNewLineToEndWait.run(); + scanner.nextLine(); + } else { + // wait for process to exit + process.waitFor(); + } + } catch (IOException ex) { + errorHandler.accept("process IO failure: " + ex.getMessage()); + } catch (InterruptedException ex) { + errorHandler.accept("process interrupt: " + ex.getMessage()); + } finally { + try { + watcher.close(); + watchedThread.join(); //so that saveFile() is finished. + saveFile(); + } catch (InterruptedException ex) { + errorHandler.accept("process interrupt: " + ex.getMessage()); + } finally { + resumeInteractiveInput.run(); + } + } + } + + private void saveFile() { + try { + saveHandler.accept(Files.lines(tmpfile).collect(Collectors.joining("\n", "", "\n"))); + } catch (IOException ex) { + errorHandler.accept("Failure in read edit file: " + ex.getMessage()); + } + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.internal.ed/share/classes/jdk/internal/editor/spi/BuildInEditorProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.ed/share/classes/jdk/internal/editor/spi/BuildInEditorProvider.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,51 @@ +/* + * 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. 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 jdk.internal.editor.spi; + +import java.util.function.Consumer; + +/** + * Defines the provider of a built-in editor. + */ +public interface BuildInEditorProvider { + + /** + * @return the rank of a provider, greater is better. + */ + int rank(); + + /** + * Create a simple built-in editor. + * + * @param windowLabel the label string for the Edit Pad window, or null, + * for default window label + * @param initialText the source to load in the Edit Pad + * @param saveHandler a handler for changed source (can be sent the full source) + * @param errorHandler a handler for unexpected errors + */ + void edit(String windowLabel, String initialText, + Consumer saveHandler, Consumer errorHandler); +} diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.internal.ed/share/classes/module-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.ed/share/classes/module-info.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,34 @@ +/* + * 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. 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. + */ + +/** + * Internal editor support for JDK tools. Includes the Service Provider + * Interface to built-in editors. + */ +module jdk.internal.ed { + + exports jdk.internal.editor.spi to jdk.editpad, jdk.jshell, jdk.scripting.nashorn.shell; + exports jdk.internal.editor.external to jdk.jshell, jdk.scripting.nashorn.shell; +} diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java Wed Jul 05 22:25:59 2017 +0200 @@ -359,9 +359,9 @@ if (name.endsWith(".class") && !name.endsWith("module-info.class")) { try { byte[] bytes = reader.getResource(location); - ClassReader cr =new ClassReader(bytes); + ClassReader cr = new ClassReader(bytes); ClassNode cn = new ClassNode(); - cr.accept(cn, ClassReader.EXPAND_FRAMES); + cr.accept(cn, 0); } catch (Exception ex) { log.println("Error(s) in Class: " + name); } diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Wed Jul 05 22:25:59 2017 +0200 @@ -33,7 +33,6 @@ import java.lang.module.ModuleReference; import java.lang.module.ResolutionException; import java.lang.module.ResolvedModule; -import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.nio.ByteOrder; import java.nio.file.Files; @@ -41,6 +40,7 @@ import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import jdk.tools.jlink.internal.TaskHelper.BadArgs; import static jdk.tools.jlink.internal.TaskHelper.JLINK_BUNDLE; @@ -62,20 +62,8 @@ public class JlinkTask { static final boolean DEBUG = Boolean.getBoolean("jlink.debug"); - private static void fail(Class type, - String format, - Object... args) throws T { - String msg = new Formatter().format(format, args).toString(); - try { - T t = type.getConstructor(String.class).newInstance(msg); - throw t; - } catch (InstantiationException | - InvocationTargetException | - NoSuchMethodException | - IllegalAccessException e) { - throw new InternalError("Unable to create an instance of " + type, e); - } - } + // jlink API ignores by default. Remove when signing is implemented. + static final boolean IGNORE_SIGNING_DEFAULT = true; private static final TaskHelper taskHelper = new TaskHelper(JLINK_BUNDLE); @@ -143,7 +131,10 @@ }, "--save-opts"), new Option(false, (task, opt, arg) -> { task.options.fullVersion = true; - }, true, "--full-version"),}; + }, true, "--full-version"), + new Option(false, (task, opt, arg) -> { + task.options.ignoreSigning = true; + }, true, "--ignore-signing-information"),}; private static final String PROGNAME = "jlink"; private final OptionsValues options = new OptionsValues(); @@ -160,7 +151,8 @@ /** * Result codes. */ - static final int EXIT_OK = 0, // Completed with no errors. + static final int + EXIT_OK = 0, // Completed with no errors. EXIT_ERROR = 1, // Completed but reported errors. EXIT_CMDERR = 2, // Bad command-line arguments EXIT_SYSERR = 3, // System error or resource exhaustion. @@ -171,12 +163,13 @@ String saveoptsfile; boolean version; boolean fullVersion; - List modulePath = new ArrayList<>(); - Set limitMods = new HashSet<>(); - Set addMods = new HashSet<>(); + final List modulePath = new ArrayList<>(); + final Set limitMods = new HashSet<>(); + final Set addMods = new HashSet<>(); Path output; Path packagedModulesPath; ByteOrder endian = ByteOrder.nativeOrder(); + boolean ignoreSigning = false; } int run(String[] args) { @@ -199,7 +192,7 @@ return EXIT_OK; } if (taskHelper.getExistingImage() == null) { - if (options.modulePath == null || options.modulePath.isEmpty()) { + if (options.modulePath.isEmpty()) { throw taskHelper.newBadArgs("err.modulepath.must.be.specified").showUsage(true); } createImage(); @@ -248,20 +241,25 @@ plugins = plugins == null ? new PluginsConfiguration() : plugins; if (config.getModulepaths().isEmpty()) { - throw new Exception("Empty module paths"); + throw new IllegalArgumentException("Empty module paths"); } ModuleFinder finder = newModuleFinder(config.getModulepaths(), config.getLimitmods(), config.getModules()); + if (config.getModules().isEmpty()) { + throw new IllegalArgumentException("No modules to add"); + } + // First create the image provider - ImageProvider imageProvider - = createImageProvider(finder, - checkAddMods(config.getModules()), - config.getLimitmods(), - config.getByteOrder(), - null); + ImageProvider imageProvider = + createImageProvider(finder, + config.getModules(), + config.getLimitmods(), + config.getByteOrder(), + null, + IGNORE_SIGNING_DEFAULT); // Then create the Plugin Stack ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins); @@ -299,19 +297,17 @@ } ModuleFinder finder = newModuleFinder(options.modulePath, options.limitMods, options.addMods); - try { - options.addMods = checkAddMods(options.addMods); - } catch (IllegalArgumentException ex) { + if (options.addMods.isEmpty()) { throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules") .showUsage(true); } // First create the image provider - ImageProvider imageProvider - = createImageProvider(finder, + ImageProvider imageProvider = createImageProvider(finder, options.addMods, options.limitMods, options.endian, - options.packagedModulesPath); + options.packagedModulesPath, + options.ignoreSigning); // Then create the Plugin Stack ImagePluginStack stack = ImagePluginConfiguration. @@ -321,13 +317,6 @@ stack.operate(imageProvider); } - private static Set checkAddMods(Set addMods) { - if (addMods.isEmpty()) { - throw new IllegalArgumentException("no modules to add"); - } - return addMods; - } - /** * Returns a module finder to find the observable modules specified in * the --module-path and --limit-modules options @@ -343,7 +332,7 @@ return finder; } - /** + /* * Returns a module finder of the given module path that limits * the observable modules to those in the transitive closure of * the modules specified in {@code limitMods} plus other modules @@ -376,7 +365,8 @@ Set addMods, Set limitMods, ByteOrder order, - Path retainModulesPath) + Path retainModulesPath, + boolean ignoreSigning) throws IOException { if (addMods.isEmpty()) { @@ -390,10 +380,10 @@ Map mods = cf.modules().stream() .collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation)); - return new ImageHelper(cf, mods, order, retainModulesPath); + return new ImageHelper(cf, mods, order, retainModulesPath, ignoreSigning); } - /** + /* * Returns a ModuleFinder that limits observability to the given root * modules, their transitive dependences, plus a set of other modules. */ @@ -477,36 +467,57 @@ } private static class ImageHelper implements ImageProvider { - - final Set archives; final ByteOrder order; final Path packagedModulesPath; + final boolean ignoreSigning; + final Set archives; ImageHelper(Configuration cf, Map modsPaths, ByteOrder order, - Path packagedModulesPath) throws IOException { - archives = modsPaths.entrySet().stream() + Path packagedModulesPath, + boolean ignoreSigning) throws IOException { + this.order = order; + this.packagedModulesPath = packagedModulesPath; + this.ignoreSigning = ignoreSigning; + this.archives = modsPaths.entrySet().stream() .map(e -> newArchive(e.getKey(), e.getValue())) .collect(Collectors.toSet()); - this.order = order; - this.packagedModulesPath = packagedModulesPath; } private Archive newArchive(String module, Path path) { if (path.toString().endsWith(".jmod")) { return new JmodArchive(module, path); } else if (path.toString().endsWith(".jar")) { - return new ModularJarArchive(module, path); + ModularJarArchive modularJarArchive = new ModularJarArchive(module, path); + + Stream signatures = modularJarArchive.entries().filter((entry) -> { + String name = entry.name().toUpperCase(Locale.ENGLISH); + + return name.startsWith("META-INF/") && name.indexOf('/', 9) == -1 && ( + name.endsWith(".SF") || + name.endsWith(".DSA") || + name.endsWith(".RSA") || + name.endsWith(".EC") || + name.startsWith("META-INF/SIG-") + ); + }); + + if (signatures.count() != 0) { + if (ignoreSigning) { + System.err.println(taskHelper.getMessage("warn.signing", path)); + } else { + throw new IllegalArgumentException(taskHelper.getMessage("err.signing", path)); + } + } + + return modularJarArchive; } else if (Files.isDirectory(path)) { return new DirArchive(path); } else { - fail(RuntimeException.class, - "Selected module %s (%s) not in jmod or modular jar format", - module, - path); + throw new IllegalArgumentException( + taskHelper.getMessage("err.not.modular.format", module, path)); } - return null; } @Override diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Wed Jul 05 22:25:59 2017 +0200 @@ -212,7 +212,7 @@ mainOptions.add(new PlugOption(true, (task, opt, arg) -> { Path path = Paths.get(arg); if (!Files.exists(path) || !Files.isDirectory(path)) { - throw newBadArgs("err.existing.image.must.exist"); + throw newBadArgs("err.image.must.exist"); } existingImage = path.toAbsolutePath(); }, true, POST_PROCESS)); diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Wed Jul 05 22:25:59 2017 +0200 @@ -62,6 +62,9 @@ main.opt.save-opts=\ \ --save-opts Save jlink options in the given file +main.opt.ignore-signing-information=\ +\ --ignore-signing-information Ignore signing information in modular JARs + main.msg.bug=\ An exception has occurred in jlink. \ Please file a bug at the Java Bug Database (http://bugreport.java.com/bugreport/) \ @@ -88,7 +91,7 @@ err.mods.must.be.specified:no modules specified to {0} err.path.not.found=path not found: {0} err.path.not.valid=invalid path: {0} -err.existing.image.must.exist=existing image doesn't exists or is not a directory +err.image.must.exist=image does not exist or is not a directory err.existing.image.invalid=existing image is not valid err.file.not.found=cannot find file: {0} err.file.error=cannot access file: {0} @@ -104,5 +107,9 @@ err.config.defaults=property {0} is missing from configuration err.config.defaults.value=wrong value in defaults property: {0} err.bom.generation=bom file generation failed: {0} -warn.invalid.arg=Invalid classname or pathname not exist: {0} +err.not.modular.format=selected module {0} ({1}) not in jmod or modular JAR format +err.signing=signed modular JAR {0} is currently not supported,\ +\ use --ignore-signing-information to suppress error +warn.signing=signed modular JAR {0} is currently not supported +warn.invalid.arg=invalid classname or pathname not exist: {0} warn.split.package=package {0} defined in {1} {2} diff -r a4ee110842fb -r 8750872276b8 jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Wed Jul 05 22:25:59 2017 +0200 @@ -47,6 +47,7 @@ import java.lang.module.ResolvedModule; import java.net.URI; import java.nio.file.FileSystems; +import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -633,7 +634,8 @@ void processSection(JmodOutputStream out, Section section, Path top) throws IOException { - Files.walkFileTree(top, new SimpleFileVisitor() { + Files.walkFileTree(top, Set.of(FileVisitOption.FOLLOW_LINKS), + Integer.MAX_VALUE, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException diff -r a4ee110842fb -r 8750872276b8 jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/ProblemList.txt Wed Jul 05 22:25:59 2017 +0200 @@ -184,6 +184,8 @@ java/nio/file/WatchService/MayFlies.java 7158947 solaris-all Solaris 11 java/nio/file/WatchService/LotsOfEvents.java 7158947 solaris-all Solaris 11 +sun/nio/cs/OLD/TestIBMDB.java 8167525 generic-all + ############################################################################ # jdk_rmi @@ -217,6 +219,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 javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java 8168881 generic-all diff -r a4ee110842fb -r 8750872276b8 jdk/test/com/sun/jndi/dns/Parser.java --- a/jdk/test/com/sun/jndi/dns/Parser.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/com/sun/jndi/dns/Parser.java Wed Jul 05 22:25:59 2017 +0200 @@ -26,6 +26,7 @@ * @bug 8035105 * @summary DNS resource record parsing * @modules jdk.naming.dns/com.sun.jndi.dns + * @compile --add-modules jdk.naming.dns Parser.java */ import com.sun.jndi.dns.ResourceRecord; diff -r a4ee110842fb -r 8750872276b8 jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java --- a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java Wed Jul 05 22:25:59 2017 +0200 @@ -28,7 +28,7 @@ * @modules jdk.naming.rmi/com.sun.jndi.rmi.registry java.rmi/sun.rmi.registry * java.rmi/sun.rmi.server java.rmi/sun.rmi.transport java.rmi/sun.rmi.transport.tcp * @library ../../../../../../java/rmi/testlibrary - * @build TestLibrary + * @compile --add-modules jdk.naming.rmi ContextWithNullProperties.java * @run main ContextWithNullProperties */ diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/awt/FileDialog/8017487/bug8017487.java --- a/jdk/test/java/awt/FileDialog/8017487/bug8017487.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/awt/FileDialog/8017487/bug8017487.java Wed Jul 05 22:25:59 2017 +0200 @@ -22,7 +22,7 @@ */ /* @test - @bug 8017487 + @bug 8017487 8167988 @summary filechooser in Windows-Libraries folder: columns are mixed up @author Semyon Sadetsky @modules java.desktop/sun.awt.shell diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/awt/TrayIcon/DragEventSource/DragEventSource.java --- a/jdk/test/java/awt/TrayIcon/DragEventSource/DragEventSource.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/awt/TrayIcon/DragEventSource/DragEventSource.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -23,8 +23,8 @@ /* @test - @bug 6565779 - @library ../../../regtesthelpers + @bug 6565779 8168292 + @library ../../regtesthelpers @compile DragEventSource.java @summary Exception if source of some event is TrayIcon @author Andrei Dmitriev: area=awt.tray @@ -38,9 +38,19 @@ * instance as source. */ -import java.awt.*; -import java.awt.event.*; -import java.awt.image.*; +import java.awt.Button; +import java.awt.Dialog; +import java.awt.FileDialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Image; +import java.awt.Panel; +import java.awt.SystemTray; +import java.awt.TextArea; +import java.awt.TrayIcon; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; public class DragEventSource { @@ -81,11 +91,10 @@ String[] instructions = { - "Use see a Frame with a button in it.", - "Press the button. FileDialog should appear.", - "Drag the mouse from the Tray icon to FileDialog ", - "using left mouse button.", - "If exception happens, the test fails.", + "Click 'Open file dialog' button. FileDialog should appear.", + "Using left mouse button,", + "Drag the mouse from the Tray icon to FileDialog.", + "If exception is thrown, the test fails.", "Otherwise, pass." }; diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java --- a/jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -21,12 +21,19 @@ * questions. */ -/* @bug 8166897 +/* @test + @key headful + @bug 8166897 @summary Some font overlap in the Optionpane dialog. @run main ChangeWindowResizabiltyTest */ -import java.awt.*; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Robot; public class ChangeWindowResizabiltyTest { public static void main(String[] args) throws Exception { diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/awt/print/PrinterJob/LinearGradientPrintingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/LinearGradientPrintingTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,233 @@ +/* + * 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 8162796 + * @summary Verifies if LinearGradientPaint is printed in osx + * @run main/manual LinearGradientPrintingTest + */ +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; + +public class LinearGradientPrintingTest extends Component implements Printable { + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + private static JFrame f = null; + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + //createUI(); + doTest(LinearGradientPrintingTest::createUI); + } + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(120000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("LinearGradientPaint did not print"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + public static void createUI() { + f = new JFrame("LinearGradient Printing Test"); + f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + final LinearGradientPrintingTest gpt = new LinearGradientPrintingTest(); + Container c = f.getContentPane(); + c.add(BorderLayout.CENTER, gpt); + + final JButton print = new JButton("Print"); + print.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + PrinterJob job = PrinterJob.getPrinterJob(); + job.setPrintable(gpt); + final boolean doPrint = job.printDialog(); + if (doPrint) { + try { + job.print(); + } catch (PrinterException ex) { + throw new RuntimeException(ex); + } + } + } + }); + c.add(print, BorderLayout.SOUTH); + + f.pack(); + f.setVisible(true); + } + + public Dimension getPreferredSize() { + return new Dimension(500,500); + } + + public void paint(Graphics g) { + doPaint((Graphics2D)g); + } + + public int print( Graphics graphics, PageFormat format, int index ) { + Graphics2D g2d = (Graphics2D)graphics; + g2d.translate(format.getImageableX(), format.getImageableY()); + doPaint(g2d); + return index == 0 ? PAGE_EXISTS : NO_SUCH_PAGE; + } + + static final float DIM = 100; + public void doPaint(Graphics2D g2d) { + + g2d.translate(DIM*0.2, DIM*0.2); + Shape s = new Rectangle2D.Float(0, 0, DIM*2, DIM*2); + Point2D.Double p1 = new Point2D.Double(0.0, 0.0); + Point2D.Double p2 = new Point2D.Double(DIM/2.0, DIM/2.0); + + // LinearGradientPaint + //g2d.translate(DIM*2.2, 0); + Color colors[] = { Color.red, Color.blue} ; + float fractions[] = { 0.0f, 1.0f }; + + LinearGradientPaint lgp = + new LinearGradientPaint(p1, p2, fractions, colors, + LinearGradientPaint.CycleMethod.NO_CYCLE); + g2d.setPaint(lgp); + g2d.fill(s); + + g2d.translate(DIM*2.2, 0); + Color colors1[] = { Color.red, Color.blue, Color.green, Color.white} ; + float fractions1[] = { 0.0f, 0.3f, 0.6f, 1.0f }; + + LinearGradientPaint lgp1 = + new LinearGradientPaint(p1, p2, fractions1, colors1, + LinearGradientPaint.CycleMethod.REFLECT); + g2d.setPaint(lgp1); + g2d.fill(s); + + g2d.translate(-DIM*2.2, DIM*2.2); + Color colors2[] = { Color.red, Color.blue, Color.green, Color.white} ; + float fractions2[] = { 0.0f, 0.3f, 0.6f, 1.0f }; + + LinearGradientPaint lgp2 = + new LinearGradientPaint(p1, p2, fractions2, colors2, + LinearGradientPaint.CycleMethod.REPEAT); + g2d.setPaint(lgp2); + g2d.fill(s); + } + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " A LinearGradientPaint graphics will be shown on console.\n" + + " The same graphics is sent to printer.\n" + + " Please verify if LinearGradientPaint shading is printed.\n" + + " If none is printed, press FAIL else press PASS"; + + final JDialog dialog = new JDialog(); + dialog.setTitle("printSelectionTest"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + final JButton passButton = new JButton("PASS"); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + f.dispose(); + dialog.dispose(); + pass(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + f.dispose(); + dialog.dispose(); + fail(); + }); + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + + dialog.pack(); + dialog.setVisible(true); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.out.println("main dialog closing"); + testGeneratedInterrupt = false; + mainThread.interrupt(); + } + }); + } + +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/awt/print/PrinterJob/RadialGradientPrintingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/RadialGradientPrintingTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,234 @@ +/* + * 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 8162796 + * @summary Verifies if RadialGradientPaint is printed in osx + * @run main/manual RadialGradientPrintingTest + */ +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RadialGradientPaint; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import static java.awt.print.Printable.NO_SUCH_PAGE; +import static java.awt.print.Printable.PAGE_EXISTS; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; + +public class RadialGradientPrintingTest extends Component implements Printable { + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + private static JFrame f = null; + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + //createUI(); + doTest(RadialGradientPrintingTest::createUI); + } + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(120000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("LinearGradientPaint did not print"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + public static void createUI() { + f = new JFrame("RadialGradient Printing Test"); + f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + final RadialGradientPrintingTest gpt = new RadialGradientPrintingTest(); + Container c = f.getContentPane(); + c.add(BorderLayout.CENTER, gpt); + + final JButton print = new JButton("Print"); + print.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + PrinterJob job = PrinterJob.getPrinterJob(); + job.setPrintable(gpt); + final boolean doPrint = job.printDialog(); + if (doPrint) { + try { + job.print(); + } catch (PrinterException ex) { + throw new RuntimeException(ex); + } + } + } + }); + c.add(print, BorderLayout.SOUTH); + + f.pack(); + f.setVisible(true); + } + + public Dimension getPreferredSize() { + return new Dimension(500,500); + } + + public void paint(Graphics g) { + doPaint((Graphics2D)g); + } + + public int print( Graphics graphics, PageFormat format, int index ) { + Graphics2D g2d = (Graphics2D)graphics; + g2d.translate(format.getImageableX(), format.getImageableY()); + doPaint(g2d); + return index == 0 ? PAGE_EXISTS : NO_SUCH_PAGE; + } + + static final float DIM = 100; + public void doPaint(Graphics2D g2d) { + + g2d.translate(DIM*0.2, DIM*0.2); + Shape s = new Rectangle2D.Float(0, 0, DIM*2, DIM*2); + + // RadialGradientPaint + Point2D centre = new Point2D.Float(DIM/2.0f, DIM/2.0f); + float radius = DIM/2.0f; + Point2D focus = new Point2D.Float(DIM/3.0f, DIM/3.0f); + float stops[] = {0.0f, 1.0f}; + Color colors[] = { Color.red, Color.white} ; + + RadialGradientPaint rgp = + new RadialGradientPaint(centre, radius, focus, stops, colors, + RadialGradientPaint.CycleMethod.NO_CYCLE); + g2d.setPaint(rgp); + g2d.fill(s); + + g2d.translate(DIM*2.2, 0); + Color colors1[] = { Color.red, Color.blue, Color.green} ; + float stops1[] = {0.0f, 0.5f, 1.0f}; + RadialGradientPaint rgp1 = + new RadialGradientPaint(centre, radius, focus, stops1, colors1, + RadialGradientPaint.CycleMethod.REFLECT); + g2d.setPaint(rgp1); + g2d.fill(s); + + g2d.translate(-DIM*2.2, DIM*2.2); + Color colors2[] = { Color.red, Color.blue, Color.green, Color.white} ; + float stops2[] = {0.0f, 0.3f, 0.6f, 1.0f}; + RadialGradientPaint rgp2 = + new RadialGradientPaint(centre, radius, focus, stops2, colors2, + RadialGradientPaint.CycleMethod.REPEAT); + g2d.setPaint(rgp2); + g2d.fill(s); + + } + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " A RadialGradientPaint graphics will be shown on console.\n" + + " The same graphics is sent to printer.\n" + + " Please verify if RadialGradientPaint shading is printed.\n" + + " If none is printed, press FAIL else press PASS"; + + final JDialog dialog = new JDialog(); + dialog.setTitle("printSelectionTest"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + final JButton passButton = new JButton("PASS"); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + f.dispose(); + dialog.dispose(); + pass(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + f.dispose(); + dialog.dispose(); + fail(); + }); + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + + dialog.pack(); + dialog.setVisible(true); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.out.println("main dialog closing"); + testGeneratedInterrupt = false; + mainThread.interrupt(); + } + }); + } + +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java --- a/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -40,7 +40,7 @@ import java.util.Set; import java.util.concurrent.atomic.LongAdder; -import javax.lang.model.SourceVersion; +import javax.net.ssl.SSLEngineResult; import org.testng.Assert; import org.testng.annotations.Test; @@ -82,8 +82,8 @@ Object[][] patterns = new Object[][]{ {"java.util.Hashtable"}, {"java.util.Hash*"}, - {"javax.lang.model.*"}, - {"javax.lang.**"}, + {"javax.net.ssl.*"}, + {"javax.net.**"}, {"*"}, {"maxarray=47"}, {"maxdepth=5"}, @@ -543,20 +543,20 @@ static Object genTestObjectWildcard(String pattern, boolean allowed) { if (pattern.endsWith(".**")) { // package hierarchy wildcard - if (pattern.startsWith("javax.lang.")) { - return SourceVersion.RELEASE_5; + if (pattern.startsWith("javax.net.")) { + return SSLEngineResult.Status.BUFFER_OVERFLOW; } if (pattern.startsWith("java.")) { return 4; } if (pattern.startsWith("javax.")) { - return SourceVersion.RELEASE_6; + return SSLEngineResult.Status.BUFFER_UNDERFLOW; } return otherObject; } else if (pattern.endsWith(".*")) { // package wildcard - if (pattern.startsWith("javax.lang.model")) { - return SourceVersion.RELEASE_6; + if (pattern.startsWith("javax.net.ssl")) { + return SSLEngineResult.Status.BUFFER_UNDERFLOW; } } else { // class wildcard diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/ClassLoader/platformClassLoader/DefinePlatformClass.java --- a/jdk/test/java/lang/ClassLoader/platformClassLoader/DefinePlatformClass.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/lang/ClassLoader/platformClassLoader/DefinePlatformClass.java Wed Jul 05 22:25:59 2017 +0200 @@ -24,8 +24,9 @@ /* * @test * @summary Test java.* class defined by the platform class loader - * @build jdk.zipfs/java.fake.Fake * @modules jdk.zipfs/java.fake + * @build jdk.zipfs/java.fake.Fake + * @compile --add-modules jdk.zipfs DefinePlatformClass.java * @run main DefinePlatformClass */ diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/StackTraceElement/PublicConstructor.java --- a/jdk/test/java/lang/StackTraceElement/PublicConstructor.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/lang/StackTraceElement/PublicConstructor.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 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 @@ -23,43 +23,74 @@ /* * @test - * @bug 4712607 + * @bug 4712607 6479237 * @summary Basic test for StackTraceElementPublic constructor * @author Josh Bloch */ -import java.util.*; +import java.lang.module.ModuleDescriptor; +import java.lang.reflect.Module; public class PublicConstructor { - public static void main(String args[]) { + public static void main(String... args) { + testConstructor(); + testConstructorWithModule(); + } + + static void testConstructor() { StackTraceElement ste = new StackTraceElement("com.acme.Widget", - "frobnicate", "Widget.java", 42); + "frobnicate", + "Widget.java", 42); if (!(ste.getClassName().equals("com.acme.Widget") && - ste.getFileName().equals("Widget.java") && - ste.getMethodName().equals("frobnicate") && - ste.getLineNumber() == 42)) + ste.getFileName().equals("Widget.java") && + ste.getMethodName().equals("frobnicate") && + ste.getLineNumber() == 42)) throw new RuntimeException("1"); + if (ste.isNativeMethod()) throw new RuntimeException("2"); - StackTraceElement ste2 - = new StackTraceElement("jdk.module", - "9.0", - "com.acme.Widget", - "frobnicate", - "Widget.java", - 42); - if (!(ste2.getClassName().equals("com.acme.Widget") && - ste2.getModuleName().equals("jdk.module") && - ste2.getModuleVersion().equals("9.0") && - ste2.getFileName().equals("Widget.java") && - ste2.getMethodName().equals("frobnicate") && - ste2.getLineNumber() == 42)) + + assertEquals(ste.toString(), + "com.acme.Widget.frobnicate(Widget.java:42)"); + + StackTraceElement ste1 = new StackTraceElement("com.acme.Widget", + "frobnicate", + "Widget.java", + -2); + if (!ste1.isNativeMethod()) throw new RuntimeException("3"); - if (ste2.isNativeMethod()) + + assertEquals(ste1.toString(), + "com.acme.Widget.frobnicate(Native Method)"); + } + + static void testConstructorWithModule() { + StackTraceElement ste = new StackTraceElement("app", + "jdk.module", + "9.0", + "com.acme.Widget", + "frobnicate", + "Widget.java", + 42); + if (!(ste.getClassName().equals("com.acme.Widget") && + ste.getModuleName().equals("jdk.module") && + ste.getModuleVersion().equals("9.0") && + ste.getClassLoaderName().equals("app") && + ste.getFileName().equals("Widget.java") && + ste.getMethodName().equals("frobnicate") && + ste.getLineNumber() == 42)) + throw new RuntimeException("3"); + + if (ste.isNativeMethod()) throw new RuntimeException("4"); - StackTraceElement ste3 = new StackTraceElement("com.acme.Widget", - "frobnicate", "Widget.java", -2); - if (!ste3.isNativeMethod()) - throw new RuntimeException("5"); + + assertEquals(ste.toString(), + "app/jdk.module@9.0/com.acme.Widget.frobnicate(Widget.java:42)"); + } + + static void assertEquals(String s, String expected) { + if (!s.equals(expected)) { + throw new RuntimeException("Expected: " + expected + " but found: " + s); + } } } diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/StackTraceElement/SerialTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/StackTraceElement/SerialTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,264 @@ +/* + * 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 6479237 + * @summary Test the format of StackTraceElement::toString and its serial form + * @modules java.logging + * java.xml.bind + * @run main SerialTest + */ + +import javax.xml.bind.JAXBElement; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.logging.Logger; + +public class SerialTest { + private static final Path SER_DIR = Paths.get("sers"); + private static final String JAVA_BASE = "java.base"; + private static final String JAVA_LOGGING = "java.logging"; + private static final String JAVA_XML_BIND = "java.xml.bind"; + + private static boolean isImage; + + public static void main(String... args) throws Exception { + Files.createDirectories(SER_DIR); + + // detect if exploded image build + Path home = Paths.get(System.getProperty("java.home")); + isImage = Files.exists(home.resolve("lib").resolve("modules")); + + // test stack trace from built-in loaders + try { + Logger.getLogger(null); + } catch (NullPointerException e) { + Arrays.stream(e.getStackTrace()) + .filter(ste -> ste.getClassName().startsWith("java.util.logging.") || + ste.getClassName().equals("SerialTest")) + .forEach(SerialTest::test); + } + + // test stack trace with upgradeable module + try { + new JAXBElement(null, null, null); + } catch (IllegalArgumentException e) { + Arrays.stream(e.getStackTrace()) + .filter(ste -> ste.getModuleName() != null) + .forEach(SerialTest::test); + } + + // test stack trace with class loader name from other class loader + Loader loader = new Loader("myloader"); + Class cls = Class.forName("SerialTest", true, loader); + Method method = cls.getMethod("throwException"); + StackTraceElement ste = (StackTraceElement)method.invoke(null); + test(ste, loader); + + // verify the class loader name and in the stack trace + if (!cls.getClassLoader().getName().equals("myloader.hacked")) { + throw new RuntimeException("Unexpected loader name: " + + cls.getClassLoader().getName()); + } + if (!ste.getClassLoaderName().equals("myloader")) { + throw new RuntimeException("Unexpected loader name: " + + ste.getClassLoaderName()); + } + } + + private static void test(StackTraceElement ste) { + test(ste, null); + } + + private static void test(StackTraceElement ste, ClassLoader loader) { + try { + SerialTest serialTest = new SerialTest(ste); + StackTraceElement ste2 = serialTest.serialize().deserialize(); + System.out.println(ste2); + // verify StackTraceElement::toString returns the same string + if (!ste.equals(ste2) || !ste.toString().equals(ste2.toString())) { + throw new RuntimeException(ste + " != " + ste2); + } + + String mn = ste.getModuleName(); + if (mn != null) { + switch (mn) { + case JAVA_BASE: + case JAVA_LOGGING: + checkNamedModule(ste, loader, false); + break; + case JAVA_XML_BIND: + // for exploded build, no version is shown + checkNamedModule(ste, loader, isImage); + break; + default: // ignore + } + } else { + checkUnnamedModule(ste, loader); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static void checkUnnamedModule(StackTraceElement ste, ClassLoader loader) { + String mn = ste.getModuleName(); + String s = ste.toString(); + int i = s.indexOf('/'); + + if (mn != null) { + throw new RuntimeException("expected null but got " + mn); + } + + if (loader != null) { + // Expect //.(:) + if (i <= 0) { + throw new RuntimeException("loader name missing: " + s); + } + if (!getLoaderName(loader).equals(s.substring(0, i))) { + throw new RuntimeException("unexpected loader name: " + s); + } + int j = s.substring(i+1).indexOf('/'); + if (j != 0) { + throw new RuntimeException("unexpected element for unnamed module: " + s); + } + } + } + + /* + * Loader::getName is overridden to return some other name + */ + private static String getLoaderName(ClassLoader loader) { + if (loader == null) + return ""; + + if (loader instanceof Loader) { + return ((Loader) loader).name; + } else { + return loader.getName(); + } + } + + private static void checkNamedModule(StackTraceElement ste, + ClassLoader loader, + boolean showVersion) { + String loaderName = getLoaderName(loader); + String mn = ste.getModuleName(); + String s = ste.toString(); + int i = s.indexOf('/'); + + if (mn == null) { + throw new RuntimeException("expected module name: " + s); + } + + if (i <= 0) { + throw new RuntimeException("module name missing: " + s); + } + + // Expect /.(:) + if (!loaderName.isEmpty()) { + throw new IllegalArgumentException(loaderName); + } + + // : name@version + int j = s.indexOf('@'); + if ((showVersion && j <= 0) || (!showVersion && j >= 0)) { + throw new RuntimeException("unexpected version: " + s); + } + + String name = j < 0 ? s.substring(0, i) : s.substring(0, j); + if (!name.equals(mn)) { + throw new RuntimeException("unexpected module name: " + s); + } + } + + private final Path ser; + private final StackTraceElement ste; + SerialTest(StackTraceElement ste) throws IOException { + this.ser = Files.createTempFile(SER_DIR, "SerialTest", ".ser"); + this.ste = ste; + } + + private StackTraceElement deserialize() throws IOException { + try (InputStream in = Files.newInputStream(ser); + BufferedInputStream bis = new BufferedInputStream(in); + ObjectInputStream ois = new ObjectInputStream(bis)) { + return (StackTraceElement)ois.readObject(); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + private SerialTest serialize() throws IOException { + try (OutputStream out = Files.newOutputStream(ser); + BufferedOutputStream bos = new BufferedOutputStream(out); + ObjectOutputStream oos = new ObjectOutputStream(bos)) { + oos.writeObject(ste); + } + return this; + } + + + public static StackTraceElement throwException() { + try { + Integer.parseInt(null); + } catch (NumberFormatException e) { + return Arrays.stream(e.getStackTrace()) + .filter(ste -> ste.getMethodName().equals("throwException")) + .findFirst().get(); + } + return null; + } + + public static class Loader extends URLClassLoader { + final String name; + Loader(String name) throws MalformedURLException { + super(name, new URL[] { testClassesURL() } , null); + this.name = name; + } + + private static URL testClassesURL() throws MalformedURLException { + Path path = Paths.get(System.getProperty("test.classes")); + return path.toUri().toURL(); + } + + public String getName() { + return name + ".hacked"; + } + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/StackTraceElement/WithClassLoaderName.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/StackTraceElement/WithClassLoaderName.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,121 @@ +/* + * 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 6479237 + * @summary Basic test StackTraceElement with class loader names + * @library lib /lib/testlibrary + * @build m1/* WithClassLoaderName + * @run main/othervm m1/com.app.Main + * @run main/othervm WithClassLoaderName + */ + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.app.Utils; + +public class WithClassLoaderName { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final String SRC_FILENAME = "WithClassLoaderName.java"; + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path CLASSES_DIR = Paths.get("classes"); + private static final String THROW_EXCEPTION_CLASS = "p.ThrowException"; + + public static void main(String... args) throws Exception { + /* + * Test the following frames both have the same class loader name "app" + * com.app.Test::test + * WithClassLoaderName::test + */ + Utils.verify(WithClassLoaderName.class, "app", "main", SRC_FILENAME); + + /* + * Test StackTraceElement for a class loaded by a named URLClassLoader + */ + compile(); + testURLClassLoader("myloader"); + + // loader name same as application class loader + testURLClassLoader("app"); + } + + private static void compile() throws Exception { + boolean rc = CompilerUtils.compile(SRC_DIR, CLASSES_DIR); + if (!rc) { + throw new RuntimeException("compilation fails"); + } + } + + public static void testURLClassLoader(String loaderName) throws Exception { + System.err.println("---- test URLClassLoader name: " + loaderName); + + URL[] urls = new URL[] { CLASSES_DIR.toUri().toURL() }; + ClassLoader parent = ClassLoader.getSystemClassLoader(); + URLClassLoader loader = new URLClassLoader(loaderName, urls, parent); + + Class c = Class.forName(THROW_EXCEPTION_CLASS, true, loader); + Method method = c.getMethod("throwError"); + try { + // invoke p.ThrowException::throwError + method.invoke(null); + } catch (InvocationTargetException x) { + Throwable e = x.getCause(); + e.printStackTrace(); + + StackTraceElement[] stes = e.getStackTrace(); + StackWalker.StackFrame[] frames = new StackWalker.StackFrame[] { + Utils.makeStackFrame(c, "throwError", "ThrowException.java"), + Utils.makeStackFrame(WithClassLoaderName.class, "testURLClassLoader", + SRC_FILENAME), + Utils.makeStackFrame(WithClassLoaderName.class, "main", SRC_FILENAME), + }; + + // p.ThrowException.throwError + Utils.checkFrame(loaderName, frames[0], stes[0]); + // skip reflection frames + int i = 1; + while (i < stes.length) { + String cn = stes[i].getClassName(); + if (!cn.startsWith("java.lang.reflect.") && + !cn.startsWith("jdk.internal.reflect.")) + break; + i++; + } + // WithClassLoaderName.testURLClassLoader + Utils.checkFrame("app", frames[1], stes[i]); + + // WithClassLoaderName.main + Utils.checkFrame("app", frames[2], stes[i+1]); + + } + } + +} + diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/StackTraceElement/lib/m1/com/app/Main.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/StackTraceElement/lib/m1/com/app/Main.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package com.app; + +import java.lang.StackWalker.StackFrame; + +public class Main { + public static void main(String... args) throws Exception { + StackFrame frame = Utils.makeStackFrame(Main.class, "main", "Main.java"); + Utils.checkFrame("app", frame, caller()); + } + + private static StackTraceElement caller() { + StackTraceElement[] stes = Thread.currentThread().getStackTrace(); + return stes[2]; + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/StackTraceElement/lib/m1/com/app/Utils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/StackTraceElement/lib/m1/com/app/Utils.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,136 @@ +/* + * 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. + */ + +package com.app; + +import java.lang.StackWalker.StackFrame; +import java.lang.module.ModuleDescriptor; +import java.lang.reflect.Module; +import java.util.Objects; + +public class Utils { + public static void verify(Class caller, String loaderName, + String methodname, String filename) { + StackTraceElement[] stes = Thread.currentThread().getStackTrace(); + StackWalker.StackFrame[] frames = new StackFrame[] { + makeStackFrame(Utils.class, "verify", "Utils.java"), + makeStackFrame(caller, methodname, filename) + }; + + checkFrame("app", frames[0], stes[1]); + checkFrame(loaderName, frames[1], stes[2]); + } + + public static StackFrame makeStackFrame(Class c, String methodname, String filename) { + return new StackFrame() { + @Override + public String getClassName() { + return c.getName(); + } + @Override + public String getMethodName() { + return methodname; + } + @Override + public Class getDeclaringClass() { + return c; + } + @Override + public int getByteCodeIndex() { + return 0; + } + @Override + public String getFileName() { + return filename; + } + + @Override + public int getLineNumber() { + return 0; + } + @Override + public boolean isNativeMethod() { + return false; + } + @Override + public StackTraceElement toStackTraceElement() { + return null; + } + + private String getClassLoaderName(Class c) { + ClassLoader loader = c.getClassLoader(); + String name = ""; + if (loader == null) { + name = "boot"; + } else if (loader.getName() != null) { + name = loader.getName(); + } + return name; + } + + @Override + public String toString() { + String mid = getClassLoaderName(c); + Module module = c.getModule(); + if (module.isNamed()) { + ModuleDescriptor md = module.getDescriptor(); + mid = md.name(); + if (md.version().isPresent()) + mid += "@" + md.version().get().toString(); + mid += "/"; + } + String fileName = getFileName(); + int lineNumber = getLineNumber(); + String sourceinfo = "Unknown Source"; + if (isNativeMethod()) { + sourceinfo = "Native Method"; + } else if (fileName != null && lineNumber >= 0) { + sourceinfo = fileName + ":" + lineNumber; + } + return String.format("%s/%s.%s(%s)", mid, getClassName(), getMethodName(), + sourceinfo); + + } + }; + } + + public static void checkFrame(String loaderName, StackFrame frame, + StackTraceElement ste) { + System.err.println("checking " + ste.toString() + " expected: " + frame.toString()); + Class c = frame.getDeclaringClass(); + Module module = c.getModule(); + assertEquals(ste.getModuleName(), module.getName(), "module name"); + assertEquals(ste.getClassLoaderName(), loaderName, "class loader name"); + assertEquals(ste.getClassLoaderName(), c.getClassLoader().getName(), + "class loader name"); + assertEquals(ste.getClassName(), c.getName(), "class name"); + assertEquals(ste.getMethodName(), frame.getMethodName(), "method name"); + assertEquals(ste.getFileName(), frame.getFileName(), "file name"); + + } + private static void assertEquals(String actual, String expected, String msg) { + if (!Objects.equals(actual, expected)) + throw new AssertionError("Actual: " + actual + " Excepted: " + + expected + " mismatched " + msg); + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/StackTraceElement/lib/m1/module-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/StackTraceElement/lib/m1/module-info.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,26 @@ +/* + * 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. + */ + +module m1 { + exports com.app; +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/StackTraceElement/src/p/ThrowException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/StackTraceElement/src/p/ThrowException.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package p; + +import java.lang.StackWalker.StackFrame; + +public class ThrowException { + public static void throwError() { + throw new Error("testing"); + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/StackWalker/VerifyStackTrace.java --- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java Wed Jul 05 22:25:59 2017 +0200 @@ -71,7 +71,7 @@ "3: VerifyStackTrace$Handle.run(VerifyStackTrace.java:158)\n" + "4: VerifyStackTrace.invoke(VerifyStackTrace.java:188)\n" + "5: VerifyStackTrace$1.run(VerifyStackTrace.java:218)\n" + - "6: java.security.AccessController.doPrivileged(java.base/Native Method)\n" + + "6: java.base/java.security.AccessController.doPrivileged(Native Method)\n" + "7: VerifyStackTrace.test(VerifyStackTrace.java:227)\n" + "8: VerifyStackTrace.main(VerifyStackTrace.java:182)\n"; @@ -100,12 +100,12 @@ "2: VerifyStackTrace$Handle.execute(VerifyStackTrace.java:147)\n" + "3: VerifyStackTrace$Handle.run(VerifyStackTrace.java:160)\n" + "4: VerifyStackTrace.invoke(VerifyStackTrace.java:190)\n" + - "5: jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base/Native Method)\n" + - "6: jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base/NativeMethodAccessorImpl.java:62)\n" + - "7: jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base/DelegatingMethodAccessorImpl.java:43)\n" + - "8: java.lang.reflect.Method.invoke(java.base/Method.java:520)\n" + + "5: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + "6: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n" + + "7: java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" + + "8: java.base/java.lang.reflect.Method.invoke(Method.java:520)\n" + "9: VerifyStackTrace$1.run(VerifyStackTrace.java:220)\n" + - "10: java.security.AccessController.doPrivileged(java.base/Native Method)\n" + + "10: java.base/java.security.AccessController.doPrivileged(Native Method)\n" + "11: VerifyStackTrace.test(VerifyStackTrace.java:229)\n" + "12: VerifyStackTrace.main(VerifyStackTrace.java:185)\n"; @@ -133,16 +133,16 @@ "1: VerifyStackTrace.lambda$test$1(VerifyStackTrace.java:213)\n" + "2: VerifyStackTrace$$Lambda$1/662441761.run(Unknown Source)\n" + "3: VerifyStackTrace$Handle.execute(VerifyStackTrace.java:149)\n" + - "4: java.lang.invoke.LambdaForm$DMH/2008017533.invokeVirtual_LL_V(java.base/LambdaForm$DMH)\n" + - "5: java.lang.invoke.LambdaForm$MH/1395089624.invoke_MT(java.base/LambdaForm$MH)\n" + + "4: java.base/java.lang.invoke.LambdaForm$DMH/2008017533.invokeVirtual_LL_V(LambdaForm$DMH)\n" + + "5: java.base/java.lang.invoke.LambdaForm$MH/1395089624.invoke_MT(LambdaForm$MH)\n" + "6: VerifyStackTrace$Handle.run(VerifyStackTrace.java:162)\n" + "7: VerifyStackTrace.invoke(VerifyStackTrace.java:192)\n" + - "8: jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base/Native Method)\n" + - "9: jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base/NativeMethodAccessorImpl.java:62)\n" + - "10: jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base/DelegatingMethodAccessorImpl.java:43)\n" + - "11: java.lang.reflect.Method.invoke(java.base/Method.java:520)\n" + + "8: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + "9: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n" + + "10: java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" + + "11: java.base/java.lang.reflect.Method.invoke(Method.java:520)\n" + "12: VerifyStackTrace$1.run(VerifyStackTrace.java:222)\n" + - "13: java.security.AccessController.doPrivileged(java.base/Native Method)\n" + + "13: java.base/java.security.AccessController.doPrivileged(Native Method)\n" + "14: VerifyStackTrace.test(VerifyStackTrace.java:231)\n" + "15: VerifyStackTrace.main(VerifyStackTrace.java:188)\n"; @@ -201,8 +201,6 @@ // out before comparing. We also erase the hash-like names of // synthetic frames introduced by lambdas & method handles return produced.replaceAll(":[1-9][0-9]*\\)", ":00)") - .replaceAll("-internal/", "/").replaceAll("-ea/", "/") - .replaceAll("java.base@(\\d+\\.){0,3}(\\d+)/", "java.base/") .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run") .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke") // LFs may or may not be pre-generated, making frames differ diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/annotation/AnnotationToStringTest.java --- a/jdk/test/java/lang/annotation/AnnotationToStringTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/lang/annotation/AnnotationToStringTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -23,7 +23,7 @@ /* * @test - * @bug 8162817 + * @bug 8162817 8168921 * @summary Test of toString on normal annotations */ @@ -70,6 +70,8 @@ "d1=1.0/0.0, " + "l0=5, " + "l1=9223372036854775807L, " + + "l2=-9223372036854775808L, " + + "l3=-2147483648, " + "s0=\"Hello world.\", " + "s1=\"a\\\"b\", " + "class0=Obj[].class)") @@ -84,6 +86,8 @@ d1=2.0/0.0, l0=5, l1=Long.MAX_VALUE, + l2=Long.MIN_VALUE, + l3=Integer.MIN_VALUE, s0="Hello world.", s1="a\"b", class0=Obj[].class @@ -185,8 +189,10 @@ public int[] f6; @ExpectedString( - "@LongArray(value={-2147483647, 2147483648L, 9223372036854775807L})") - @LongArray(value={-Integer.MAX_VALUE, Integer.MAX_VALUE+1L, Long.MAX_VALUE}) + "@LongArray(value={-9223372036854775808L, -2147483649L, -2147483648," + + " -2147483647, 2147483648L, 9223372036854775807L})") + @LongArray(value={Long.MIN_VALUE, Integer.MIN_VALUE-1L, Integer.MIN_VALUE, + -Integer.MAX_VALUE, Integer.MAX_VALUE+1L, Long.MAX_VALUE}) public long[] f7; @ExpectedString( @@ -287,6 +293,8 @@ double d1(); long l0(); long l1(); + long l2(); + long l3(); String s0(); String s1(); Class class0(); diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java --- a/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java Wed Jul 05 22:25:59 2017 +0200 @@ -337,9 +337,10 @@ }; private static final String[] steItemNames = { - "className", + "classLoaderName", "moduleName", "moduleVersion", + "className", "methodName", "fileName", "lineNumber", @@ -362,9 +363,10 @@ validItemTypes[STACK_TRACE] = new ArrayType(1, steCType); final Object[] steValue = { - ste[0].getClassName(), + ste[0].getClassLoaderName(), ste[0].getModuleName(), ste[0].getModuleVersion(), + ste[0].getClassName(), ste[0].getMethodName(), ste[0].getFileName(), new Integer(ste[0].getLineNumber()), diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/URLClassLoader/NullURLTest.java --- a/jdk/test/java/net/URLClassLoader/NullURLTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/URLClassLoader/NullURLTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -109,7 +109,7 @@ failures++; } try { - loader = new URLClassLoader(null, null, null); + loader = new URLClassLoader((URL[])null, null, null); System.err.println("URLClassLoader(null, null, null) did not throw NPE"); failures++; } catch (NullPointerException e) { diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/URLPermission/nstest/LookupTest.java --- a/jdk/test/java/net/URLPermission/nstest/LookupTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/URLPermission/nstest/LookupTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -22,124 +22,195 @@ */ /** - * This is a simple smoke test of the HttpURLPermission mechanism, which - * checks for either IOException (due to unknown host) or SecurityException - * due to lack of permission to connect + * @test + * @summary A simple smoke test of the HttpURLPermission mechanism, which checks + * for either IOException (due to unknown host) or SecurityException + * due to lack of permission to connect + * @run main/othervm LookupTest */ -import java.net.*; -import java.io.*; -import jdk.testlibrary.Utils; +import java.io.BufferedWriter; +import java.io.FilePermission; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.NetPermission; +import java.net.ProxySelector; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketPermission; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLPermission; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; +import java.security.ProtectionDomain; +import static java.nio.charset.StandardCharsets.US_ASCII; public class LookupTest { - static void test( - String url, boolean throwsSecException, boolean throwsIOException) - { + static int port; + static volatile ServerSocket serverSocket; + + static void test(String url, + boolean throwsSecException, + boolean throwsIOException) { + ProxySelector.setDefault(null); + URL u; + InputStream is = null; try { - ProxySelector.setDefault(null); - URL u = new URL(url); - System.err.println ("Connecting to " + u); + u = new URL(url); + System.err.println("Connecting to " + u); URLConnection urlc = u.openConnection(); - InputStream is = urlc.getInputStream(); + is = urlc.getInputStream(); } catch (SecurityException e) { if (!throwsSecException) { - throw new RuntimeException ("(1) was not expecting ", e); + throw new RuntimeException("Unexpected SecurityException:", e); + } + return; + } catch (IOException e) { + if (!throwsIOException) { + System.err.println("Unexpected IOException:" + e.getMessage()); + throw new RuntimeException(e); } return; - } catch (IOException ioe) { - if (!throwsIOException) { - throw new RuntimeException ("(2) was not expecting ", ioe); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + System.err.println("Unexpected IOException:" + e.getMessage()); + throw new RuntimeException(e); + } } - return; } + if (throwsSecException || throwsIOException) { - System.err.printf ("was expecting a %s\n", throwsSecException ? - "security exception" : "IOException"); + System.err.printf("was expecting a %s\n", throwsSecException + ? "security exception" : "IOException"); throw new RuntimeException("was expecting an exception"); } } - static int port; - static ServerSocket serverSocket; + static final String CWD = System.getProperty("user.dir", "."); public static void main(String args[]) throws Exception { - - - String cmd = args[0]; - if (cmd.equals("-getport")) { - port = Utils.getFreePort(); - System.out.print(port); - } else if (cmd.equals("-runtest")) { - port = Integer.parseInt(args[1]); - String hostsFileName = System.getProperty("user.dir", ".") + "/LookupTestHosts"; - System.setProperty("jdk.net.hosts.file", hostsFileName); - addMappingToHostsFile("allowedAndFound.com", "127.0.0.1", hostsFileName, false); - addMappingToHostsFile("notAllowedButFound.com", "99.99.99.99", hostsFileName, true); - // name "notAllowedAndNotFound.com" is not in map - // name "allowedButNotfound.com" is not in map - try { - startServer(); - - System.setSecurityManager(new SecurityManager()); - - test("http://allowedAndFound.com:" + port + "/foo", false, false); - - test("http://notAllowedButFound.com:" + port + "/foo", true, false); - - test("http://allowedButNotfound.com:" + port + "/foo", false, true); - - test("http://notAllowedAndNotFound.com:" + port + "/foo", true, false); - } finally { - serverSocket.close(); - } - } else { - throw new RuntimeException("Bad invocation: " + cmd); + String hostsFileName = CWD + "/LookupTestHosts"; + System.setProperty("jdk.net.hosts.file", hostsFileName); + addMappingToHostsFile("allowedAndFound.com", + "127.0.0.1", + hostsFileName, + false); + addMappingToHostsFile("notAllowedButFound.com", + "99.99.99.99", + hostsFileName, + true); + // name "notAllowedAndNotFound.com" is not in map + // name "allowedButNotfound.com" is not in map + Server server = new Server(); + try { + Policy.setPolicy(new LookupTestPolicy()); + System.setSecurityManager(new SecurityManager()); + server.start(); + test("http://allowedAndFound.com:" + port + "/foo", false, false); + test("http://notAllowedButFound.com:" + port + "/foo", true, false); + test("http://allowedButNotfound.com:" + port + "/foo", false, true); + test("http://notAllowedAndNotFound.com:" + port + "/foo", true, false); + } finally { + server.terminate(); } } - static Thread server; + static class Server extends Thread { + private volatile boolean done; - static class Server extends Thread { + public Server() throws IOException { + serverSocket = new ServerSocket(0); + port = serverSocket.getLocalPort(); + } + public void run() { - byte[] buf = new byte[1000]; try { - while (true) { - Socket s = serverSocket.accept(); - InputStream i = s.getInputStream(); - i.read(buf); - OutputStream o = s.getOutputStream(); - String rsp = "HTTP/1.1 200 Ok\r\n" + - "Connection: close\r\nContent-length: 0\r\n\r\n"; - o.write(rsp.getBytes()); - o.close(); + while (!done) { + try (Socket s = serverSocket.accept()) { + readOneRequest(s.getInputStream()); + OutputStream o = s.getOutputStream(); + String rsp = "HTTP/1.1 200 Ok\r\n" + + "Connection: close\r\n" + + "Content-length: 0\r\n\r\n"; + o.write(rsp.getBytes(US_ASCII)); + } } } catch (IOException e) { - return; + if (!done) + e.printStackTrace(); } - } - } + } + + void terminate() { + done = true; + try { serverSocket.close(); } + catch (IOException unexpected) { unexpected.printStackTrace(); } + } + + static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' }; - static void startServer() { - try { - serverSocket = new ServerSocket(port); - server = new Server(); - server.start(); - } catch (Exception e) { - throw new RuntimeException ("Test failed to initialize", e); + // Read until the end of a HTTP request + void readOneRequest(InputStream is) throws IOException { + int requestEndCount = 0, r; + while ((r = is.read()) != -1) { + if (r == requestEnd[requestEndCount]) { + requestEndCount++; + if (requestEndCount == 4) { + break; + } + } else { + requestEndCount = 0; + } + } } } - private static void addMappingToHostsFile (String host, - String addr, - String hostsFileName, - boolean append) - throws Exception { + private static void addMappingToHostsFile(String host, + String addr, + String hostsFileName, + boolean append) + throws IOException + { String mapping = addr + " " + host; - try (PrintWriter hfPWriter = new PrintWriter(new BufferedWriter( - new FileWriter(hostsFileName, append)))) { + try (FileWriter fr = new FileWriter(hostsFileName, append); + PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(fr))) { hfPWriter.println(mapping); -} + } } + static class LookupTestPolicy extends Policy { + final PermissionCollection perms = new Permissions(); + + LookupTestPolicy() throws Exception { + perms.add(new NetPermission("setProxySelector")); + perms.add(new SocketPermission("localhost:1024-", "resolve,accept")); + perms.add(new URLPermission("http://allowedAndFound.com:" + port + "/-", "*:*")); + perms.add(new URLPermission("http://allowedButNotfound.com:" + port + "/-", "*:*")); + perms.add(new FilePermission("<>", "read,write,delete")); + //perms.add(new PropertyPermission("java.io.tmpdir", "read")); + } + + public PermissionCollection getPermissions(ProtectionDomain domain) { + return perms; + } + + public PermissionCollection getPermissions(CodeSource codesource) { + return perms; + } + + public boolean implies(ProtectionDomain domain, Permission perm) { + return perms.implies(perm); + } + } } diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/URLPermission/nstest/lookup.sh --- a/jdk/test/java/net/URLPermission/nstest/lookup.sh Mon Nov 07 16:08:18 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2013, 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 -# @library /lib/testlibrary -# @build jdk.testlibrary.* -# @compile -XDignore.symbol.file=true LookupTest.java -# @run shell/timeout=50 lookup.sh -# @key intermittent -# - -OS=`uname -s` -case ${OS} in -Windows_* | CYGWIN*) - PS=";" - FS="\\" - ;; -*) - PS=":" - FS="/" - ;; -esac - -port=`${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} LookupTest -getport` - -cat << POLICY > policy -grant { - permission java.net.URLPermission "http://allowedAndFound.com:${port}/-", "*:*"; - permission java.net.URLPermission "http://allowedButNotfound.com:${port}/-", "*:*"; - permission java.net.NetPermission "setProxySelector"; - permission java.io.FilePermission "<>", "read,write,delete"; - permission java.util.PropertyPermission "java.io.tmpdir", "read"; - - // needed for HttpServer - permission "java.net.SocketPermission" "localhost:1024-", "resolve,accept"; -}; -POLICY - -${TESTJAVA}/bin/java ${TESTVMOPTS} \ - -Djava.security.policy=file:./policy \ - -Dtest.src=${TESTSRC} \ - -cp ${TESTCLASSPATH}${PS}${TESTSRC} LookupTest -runtest ${port} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/httpclient/APIErrors.java --- a/jdk/test/java/net/httpclient/APIErrors.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/httpclient/APIErrors.java Wed Jul 05 22:25:59 2017 +0200 @@ -21,10 +21,11 @@ * questions. */ -/** +/* * @test * @bug 8087112 * @modules java.httpclient + * java.logging * jdk.httpserver * @library /lib/testlibrary/ * @build jdk.testlibrary.SimpleSSLContext ProxyServer @@ -35,13 +36,23 @@ */ //package javaapplication16; -import com.sun.net.httpserver.*; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsServer; import java.io.IOException; -import java.net.*; -import java.net.http.*; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.ProxySelector; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.util.LinkedList; import java.util.List; -import java.util.concurrent.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; import java.util.function.Supplier; /** diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/httpclient/ManyRequests.java --- a/jdk/test/java/net/httpclient/ManyRequests.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/httpclient/ManyRequests.java Wed Jul 05 22:25:59 2017 +0200 @@ -21,10 +21,11 @@ * questions. */ -/** +/* * @test * @bug 8087112 * @modules java.httpclient + * java.logging * jdk.httpserver * @library /lib/testlibrary/ / * @build jdk.testlibrary.SimpleSSLContext EchoHandler @@ -36,7 +37,9 @@ //package javaapplication16; -import com.sun.net.httpserver.*; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsParameters; +import com.sun.net.httpserver.HttpsServer; import java.io.IOException; import java.io.UncheckedIOException; import java.net.http.HttpClient; @@ -48,9 +51,10 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.Random; -import java.util.logging.*; +import java.util.logging.Logger; +import java.util.logging.Level; import java.util.concurrent.CompletableFuture; -import javax.net.ssl.*; +import javax.net.ssl.SSLContext; import jdk.testlibrary.SimpleSSLContext; public class ManyRequests { diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/httpclient/RequestBodyTest.java --- a/jdk/test/java/net/httpclient/RequestBodyTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/httpclient/RequestBodyTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -21,9 +21,10 @@ * questions. */ -/** +/* * @test @bug 8087112 * @modules java.httpclient + * java.logging * jdk.httpserver * @library /lib/testlibrary/ / * @compile ../../../com/sun/net/httpserver/LogFilter.java diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/httpclient/SmokeTest.java --- a/jdk/test/java/net/httpclient/SmokeTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/httpclient/SmokeTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -21,10 +21,11 @@ * questions. */ -/** +/* * @test * @bug 8087112 * @modules java.httpclient + * java.logging * jdk.httpserver * @library /lib/testlibrary/ / * @build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler @@ -33,13 +34,40 @@ * @run main/othervm SmokeTest */ -import com.sun.net.httpserver.*; -import java.net.*; -import java.net.http.*; -import java.io.*; -import java.util.concurrent.*; -import javax.net.ssl.*; -import java.nio.file.*; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsParameters; +import com.sun.net.httpserver.HttpsServer; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.ProxySelector; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.HashSet; import java.util.LinkedList; import java.util.List; diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/httpclient/security/Driver.java --- a/jdk/test/java/net/httpclient/security/Driver.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/httpclient/security/Driver.java Wed Jul 05 22:25:59 2017 +0200 @@ -28,6 +28,7 @@ * @bug 8087112 * @library /lib/testlibrary/ * @modules java.httpclient + * java.logging * jdk.httpserver * @build jdk.testlibrary.SimpleSSLContext jdk.testlibrary.Utils * @compile ../../../../com/sun/net/httpserver/LogFilter.java diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/httpclient/security/Security.java --- a/jdk/test/java/net/httpclient/security/Security.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/httpclient/security/Security.java Wed Jul 05 22:25:59 2017 +0200 @@ -23,10 +23,11 @@ * questions. */ -/** +/* * @test * @bug 8087112 * @modules java.httpclient + * java.logging * jdk.httpserver * @library /lib/testlibrary/ * @build jdk.testlibrary.SimpleSSLContext @@ -50,14 +51,27 @@ // Tests 1, 10, 11 and 12 executed from Driver -import com.sun.net.httpserver.*; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsServer; import java.io.IOException; import java.io.InputStream; import java.io.File; import java.io.OutputStream; import java.lang.reflect.Constructor; -import java.net.*; -import java.net.http.*; +import java.net.BindException; +import java.net.InetSocketAddress; +import java.net.ProxySelector; +import java.net.URI; +import java.net.URLClassLoader; +import java.net.URL; +import java.net.http.HttpHeaders; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -66,13 +80,15 @@ import java.nio.file.StandardCopyOption; import java.util.LinkedList; import java.util.List; -import java.util.concurrent.*; -import java.util.function.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.function.LongConsumer; import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; import java.lang.reflect.InvocationTargetException; -import java.net.BindException; /** * Security checks test diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/ipv6tests/Tests.java --- a/jdk/test/java/net/ipv6tests/Tests.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/ipv6tests/Tests.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -139,11 +139,17 @@ /* check the time got is within 50% of the time expected */ public static void checkTime (long got, long expected) { - dprintln ("checkTime: got " + got + " expected " + expected); - long upper = expected + (expected / 2); - long lower = expected - (expected / 2); + checkTime(got, expected, expected); + } + + /* check the time got is between start and end, given 50% tolerance */ + public static void checkTime(long got, long start, long end) { + dprintln("checkTime: got = " + got + " start = " + start + " end = " + end); + long upper = end + (end / 2); + long lower = start - (start / 2); if (got > upper || got < lower) { - throw new RuntimeException ("checkTime failed: got " + got + " expected " + expected); + throw new RuntimeException("checkTime failed: got " + got + + ", expected between " + start + " and " + end); } } diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/net/ipv6tests/UdpTest.java --- a/jdk/test/java/net/ipv6tests/UdpTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/net/ipv6tests/UdpTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -24,7 +24,6 @@ /* * @test * @bug 4868820 - * @key intermittent * @summary IPv6 support for Windows XP and 2003 server */ @@ -159,7 +158,7 @@ }); t1 = System.currentTimeMillis(); s1.receive (new DatagramPacket (new byte [128], 128)); - checkTime (System.currentTimeMillis() - t1, 4000); + checkTime (System.currentTimeMillis() - t1, 2000, 10000); s1.close (); s2.close (); System.out.println ("Test2: OK"); diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/util/stream/bootlib/java.base/java/util/stream/ThowableHelper.java --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/ThowableHelper.java Mon Nov 07 16:08:18 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +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. - */ -package java.util.stream; - -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; - -public final class ThowableHelper { - - public static void checkException(Class ce, Runnable r) { - Exception caught = null; - try { - r.run(); - } catch (Exception e) { - caught = e; - } - - assertNotNull(caught); - assertTrue(ce.isInstance(caught)); - } - - public static void checkNPE(Runnable r) { - checkException(NullPointerException.class, r); - } - - public static void checkISE(Runnable r) { - checkException(IllegalStateException.class, r); - } -} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/util/stream/bootlib/java.base/java/util/stream/ThrowableHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/ThrowableHelper.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, 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. + */ +package java.util.stream; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +public final class ThrowableHelper { + + public static void checkException(Class ce, Runnable r) { + Exception caught = null; + try { + r.run(); + } catch (Exception e) { + caught = e; + } + + assertNotNull(caught); + assertTrue(ce.isInstance(caught)); + } + + public static void checkNPE(Runnable r) { + checkException(NullPointerException.class, r); + } + + public static void checkISE(Runnable r) { + checkException(IllegalStateException.class, r); + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -43,7 +43,7 @@ import java.util.stream.OpTestCase; import static java.util.stream.LambdaTestHelpers.countTo; -import static java.util.stream.ThowableHelper.checkNPE; +import static java.util.stream.ThrowableHelper.checkNPE; @Test public class CollectAndSummaryStatisticsTest extends OpTestCase { diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -113,7 +113,7 @@ Map>> maps = new HashMap<>(); maps.put(HashMap.class.getName(), () -> new HashMap<>(content)); - maps.put(HashMap.class.getName(), () -> new LinkedHashMap<>(content)); + maps.put(LinkedHashMap.class.getName(), () -> new LinkedHashMap<>(content)); maps.put(IdentityHashMap.class.getName(), () -> new IdentityHashMap<>(content)); maps.put(WeakHashMap.class.getName(), () -> new WeakHashMap<>(content)); diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -49,7 +49,7 @@ import java.util.stream.TestData; import static java.util.stream.LambdaTestHelpers.*; -import static java.util.stream.ThowableHelper.checkNPE; +import static java.util.stream.ThrowableHelper.checkNPE; @Test public class FlatMapOpTest extends OpTestCase { diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -38,7 +38,7 @@ import java.util.stream.TestData; import java.util.stream.TestData.Factory; -import static java.util.stream.ThowableHelper.checkNPE; +import static java.util.stream.ThrowableHelper.checkNPE; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ import java.util.stream.TestData; import static java.util.stream.Collectors.toList; -import static java.util.stream.ThowableHelper.checkISE; +import static java.util.stream.ThrowableHelper.checkISE; @Test public class StreamBuilderTest extends OpTestCase { diff -r a4ee110842fb -r 8750872276b8 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -36,8 +36,8 @@ import org.testng.annotations.Test; import static java.util.stream.LambdaTestHelpers.countTo; -import static java.util.stream.ThowableHelper.checkNPE; -import static java.util.stream.ThowableHelper.checkISE; +import static java.util.stream.ThrowableHelper.checkNPE; +import static java.util.stream.ThrowableHelper.checkISE; @Test(groups = { "serialization-hostile" }) public class StreamCloseTest extends OpTestCase { diff -r a4ee110842fb -r 8750872276b8 jdk/test/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,373 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8133632 + * @summary javax.net.ssl.SSLEngine does not properly handle received + * SSL fatal alerts + * @run main/othervm EngineCloseOnAlert + */ + +import java.io.FileInputStream; +import java.io.IOException; +import javax.net.ssl.*; +import java.nio.ByteBuffer; +import java.util.*; +import java.security.*; +import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; + +public class EngineCloseOnAlert { + + private static final String pathToStores = "../etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + private static final String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + private static final String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + private static KeyManagerFactory KMF; + private static TrustManagerFactory TMF; + private static TrustManagerFactory EMPTY_TMF; + + private static final String[] TLS10ONLY = { "TLSv1" }; + private static final String[] TLS12ONLY = { "TLSv1.2" }; + private static final String[] ONECIPHER = + { "TLS_RSA_WITH_AES_128_CBC_SHA" }; + + public interface TestCase { + public void runTest() throws Exception; + } + + public static void main(String[] args) throws Exception { + int failed = 0; + List testMatrix = new LinkedList() {{ + add(clientReceivesAlert); + add(serverReceivesAlert); + }}; + + // Create the various key/trust manager factories we'll need + createManagerFactories(); + + for (TestCase test : testMatrix) { + try { + test.runTest(); + } catch (Exception e) { + System.out.println("Exception in test:\n" + e); + e.printStackTrace(System.out); + failed++; + } + } + + System.out.println("Total tests: " + testMatrix.size() + ", passed: " + + (testMatrix.size() - failed) + ", failed: " + failed); + if (failed > 0) { + throw new RuntimeException("One or more tests failed."); + } + } + + private static final TestCase clientReceivesAlert = new TestCase() { + @Override + public void runTest() throws Exception { + System.out.println(""); + System.out.println("======================================="); + System.out.println("Test: Client receives alert from server"); + System.out.println("======================================="); + + // For this test, we won't initialize any keystore so the + // server will throw an exception because it has no key/cert to + // match the requested ciphers offered by the client. This + // will generate an alert from the server to the client. + + SSLContext context = SSLContext.getDefault(); + SSLEngine client = context.createSSLEngine(); + SSLEngine server = context.createSSLEngine(); + client.setUseClientMode(true); + server.setUseClientMode(false); + SSLEngineResult clientResult; + SSLEngineResult serverResult; + + ByteBuffer raw = ByteBuffer.allocate(32768); + ByteBuffer plain = ByteBuffer.allocate(32768); + + // Generate the client hello and have the server unwrap it + client.wrap(plain, raw); + checkEngineState(client, NEED_UNWRAP, false, false); + raw.flip(); + System.out.println("Client-to-Server:\n-----------------\n" + + dumpHexBytes(raw, 16, "\n", ":")); + + + // The server should need to run a delegated task while processing + // the client hello data. + serverResult = server.unwrap(raw, plain); + checkEngineState(server, NEED_TASK, false, false); + System.out.println("Server result: " + serverResult); + runDelegatedTasks(serverResult, server); + checkEngineState(server, NEED_WRAP, true, false); + + try { + raw.clear(); + serverResult = server.wrap(plain, raw); + System.out.println("Server result: " + serverResult); + runDelegatedTasks(serverResult, server); + } catch (SSLException e) { + // This is the expected code path + System.out.println("Server throws exception: " + e); + System.out.println("Server engine state: " + + "isInboundDone = "+ server.isInboundDone() + + ", isOutboundDone = " + server.isOutboundDone() + + ", handshake status = " + server.getHandshakeStatus()); + checkEngineState(server, NEED_WRAP, true, false); + } + raw.clear(); + + // The above should show that isInboundDone returns true, and + // handshake status is NEED_WRAP. That is the correct behavior, + // wrap will put a fatal alert message in the buffer. + serverResult = server.wrap(plain, raw); + System.out.println("Server result (wrap after exception): " + + serverResult); + System.out.println("Server engine closure state: isInboundDone=" + + server.isInboundDone() + ", isOutboundDone=" + + server.isOutboundDone()); + checkEngineState(server, NEED_UNWRAP, true, true); + raw.flip(); + + System.out.println("Server-to-Client:\n-----------------\n" + + dumpHexBytes(raw, 16, "\n", ":")); + + // Client side will read the fatal alert and throw exception. + try { + clientResult = client.unwrap(raw, plain); + System.out.println("Client result (unwrap alert): " + + clientResult); + } catch (SSLException e) { + System.out.println("Client throws exception: " + e); + System.out.println("Engine closure status: isInboundDone=" + + client.isInboundDone() + ", isOutboundDone=" + + client.isOutboundDone() + ", handshake status=" + + client.getHandshakeStatus()); + checkEngineState(client, NOT_HANDSHAKING, true, true); + } + raw.clear(); + + // Last test, we try to unwrap + clientResult = client.unwrap(raw, plain); + checkEngineState(client, NOT_HANDSHAKING, true, true); + System.out.println("Client result (wrap after exception): " + + clientResult); + } + }; + + private static final TestCase serverReceivesAlert = new TestCase() { + @Override + public void runTest() throws Exception { + SSLContext cliContext = SSLContext.getDefault(); + SSLContext servContext = SSLContext.getInstance("TLS"); + servContext.init(KMF.getKeyManagers(), TMF.getTrustManagers(), + null); + SSLEngine client = cliContext.createSSLEngine(); + SSLEngine server = servContext.createSSLEngine(); + client.setUseClientMode(true); + client.setEnabledProtocols(TLS12ONLY); + client.setEnabledCipherSuites(ONECIPHER); + server.setUseClientMode(false); + server.setEnabledProtocols(TLS10ONLY); + SSLEngineResult clientResult; + SSLEngineResult serverResult; + ByteBuffer raw = ByteBuffer.allocate(32768); + ByteBuffer plain = ByteBuffer.allocate(32768); + + System.out.println(""); + System.out.println("======================================="); + System.out.println("Test: Server receives alert from client"); + System.out.println("======================================="); + + // Generate the client hello and have the server unwrap it + checkEngineState(client, NOT_HANDSHAKING, false, false); + client.wrap(plain, raw); + checkEngineState(client, NEED_UNWRAP, false, false); + raw.flip(); + System.out.println("Client-to-Server:\n-----------------\n" + + dumpHexBytes(raw, 16, "\n", ":")); + + // The server should need to run a delegated task while processing + // the client hello data. + serverResult = server.unwrap(raw, plain); + checkEngineState(server, NEED_TASK, false, false); + runDelegatedTasks(serverResult, server); + checkEngineState(server, NEED_WRAP, false, false); + raw.compact(); + + // The server should now wrap the response back to the client + server.wrap(plain, raw); + checkEngineState(server, NEED_UNWRAP, false, false); + raw.flip(); + System.out.println("Server-to-Client:\n-----------------\n" + + dumpHexBytes(raw, 16, "\n", ":")); + + // The client should parse this and throw an exception because + // It is unwiling to do TLS 1.0 + clientResult = client.unwrap(raw, plain); + checkEngineState(client, NEED_TASK, false, false); + runDelegatedTasks(clientResult, client); + checkEngineState(client, NEED_UNWRAP, false, false); + + try { + client.unwrap(raw, plain); + } catch (SSLException e) { + System.out.println("Client throws exception: " + e); + System.out.println("Engine closure status: isInboundDone=" + + client.isInboundDone() + ", isOutboundDone=" + + client.isOutboundDone() + ", handshake status=" + + client.getHandshakeStatus()); + checkEngineState(client, NEED_WRAP, true, false); + } + raw.clear(); + + // Now the client should wrap the exception + client.wrap(plain, raw); + checkEngineState(client, NEED_UNWRAP, true, true); + raw.flip(); + System.out.println("Client-to-Server:\n-----------------\n" + + dumpHexBytes(raw, 16, "\n", ":")); + + try { + server.unwrap(raw, plain); + checkEngineState(server, NEED_UNWRAP, false, false); + } catch (SSLException e) { + System.out.println("Server throws exception: " + e); + System.out.println("Engine closure status: isInboundDone=" + + server.isInboundDone() + ", isOutboundDone=" + + server.isOutboundDone() + ", handshake status=" + + server.getHandshakeStatus()); + checkEngineState(server, NOT_HANDSHAKING, true, true); + } + raw.clear(); + } + }; + + + /* + * If the result indicates that we have outstanding tasks to do, + * go ahead and run them in this thread. + */ + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == + SSLEngineResult.HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + System.out.println("\trunning delegated task..."); + runnable.run(); + } + SSLEngineResult.HandshakeStatus hsStatus = + engine.getHandshakeStatus(); + if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + System.out.println("\tnew HandshakeStatus: " + hsStatus); + } + } + + /** + * + * @param data The array of bytes to dump to stdout. + * @param itemsPerLine The number of bytes to display per line + * if the {@code lineDelim} character is blank then all bytes will be + * printed on a single line. + * @param lineDelim The delimiter between lines + * @param itemDelim The delimiter between bytes + * + * @return The hexdump of the byte array + */ + private static String dumpHexBytes(ByteBuffer data, int itemsPerLine, + String lineDelim, String itemDelim) { + StringBuilder sb = new StringBuilder(); + + if (data != null) { + data.mark(); + for (int i = 0; i < data.limit(); i++) { + if (i % itemsPerLine == 0 && i != 0) { + sb.append(lineDelim); + } + sb.append(String.format("%02X", data.get(i))); + if (i % itemsPerLine != (itemsPerLine - 1) && + i != (data.limit() -1)) { + sb.append(itemDelim); + } + } + data.reset(); + } + + return sb.toString(); + } + + private static void createManagerFactories() + throws GeneralSecurityException, IOException { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + KeyStore truststore = KeyStore.getInstance("PKCS12"); + KeyStore empty_ts = KeyStore.getInstance("PKCS12"); + char[] passphrase = passwd.toCharArray(); + + keystore.load(new FileInputStream(keyFilename), passphrase); + truststore.load(new FileInputStream(trustFilename), passphrase); + empty_ts.load(null, "".toCharArray()); + + KMF = KeyManagerFactory.getInstance("PKIX"); + KMF.init(keystore, passphrase); + TMF = TrustManagerFactory.getInstance("PKIX"); + TMF.init(truststore); + EMPTY_TMF = TrustManagerFactory.getInstance("PKIX"); + EMPTY_TMF.init(truststore); + } + + private static void checkEngineState(SSLEngine engine, + SSLEngineResult.HandshakeStatus expectedHSStat, + boolean expectedInboundDone, boolean expectedOutboundDone) { + if (engine.getHandshakeStatus() != expectedHSStat || + engine.isInboundDone() != expectedInboundDone || + engine.isOutboundDone() != expectedOutboundDone) { + throw new RuntimeException("Error: engine not in expected state\n" + + "Expected: state = " + expectedHSStat + + ", inDone = " + expectedInboundDone + + ", outDone = " + expectedOutboundDone + "\n" + + "Actual: state = " + engine.getHandshakeStatus() + + ", inDone = " + engine.isInboundDone() + + ", outDone = " + engine.isOutboundDone()); + } else { + System.out.println((engine.getUseClientMode() ? + "Client" : "Server") + " handshake status: " + + engine.getHandshakeStatus() + ", inDone = " + + engine.isInboundDone() + ", outDone = " + + engine.isOutboundDone()); + } + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Devices/ClosedReceiver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Devices/ClosedReceiver.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Devices/IOLoop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Devices/IOLoop.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Devices/MidiDeviceGetReceivers.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Devices/MidiDeviceGetReceivers.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Devices/MidiIO.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Devices/MidiIO.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Devices/MidiOutGetMicrosecondPositionBug.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Devices/MidiOutGetMicrosecondPositionBug.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Devices/OpenClose.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Devices/OpenClose.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Devices/ReceiverTransmitterAvailable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Devices/ReceiverTransmitterAvailable.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Devices/Reopen.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Devices/Reopen.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/File/SMFCp037.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/File/SMFCp037.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/File/SMFParserBreak.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/File/SMFParserBreak.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/File/WriteRealTimeMessageNPE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/File/WriteRealTimeMessageNPE.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/MetaMessage/MetaMessageClone.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/MetaMessage/MetaMessageClone.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/MidiSystem/6411624/bug6411624.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/MidiSystem/6411624/bug6411624.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/MidiSystem/MidiFileTypeUniqueness.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/MidiSystem/MidiFileTypeUniqueness.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/MidiSystem/ProviderCacheing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/MidiSystem/ProviderCacheing.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/MidiSystem/testdata/conf/sound.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/MidiSystem/testdata/conf/sound.properties Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequence/GetMicrosecondLength.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequence/GetMicrosecondLength.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequence/MidiSMPTE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequence/MidiSMPTE.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequence/SMPTEDuration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequence/SMPTEDuration.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/LoopIAE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/LoopIAE.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/Looping.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/Looping.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/MetaCallback.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/MetaCallback.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/Recording.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/Recording.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/SeqRecordDoesNotCopy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/SeqRecordDoesNotCopy.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/SeqRecordsRealTimeEvents.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/SeqRecordsRealTimeEvents.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/SeqStartRecording.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/SeqStartRecording.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/SequencerCacheValues.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/SequencerCacheValues.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/SequencerState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/SequencerState.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/SetTickPosition.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/SetTickPosition.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Sequencer/TickLength.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Sequencer/TickLength.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/ShortMessage/FastShortMessage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/ShortMessage/FastShortMessage.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/ShortMessage/FastShortMessage2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/ShortMessage/FastShortMessage2.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Soundbanks/ExtraCharInSoundbank.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Soundbanks/ExtraCharInSoundbank.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Soundbanks/GetSoundBankIOException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Soundbanks/GetSoundBankIOException.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Synthesizer/AsynchronousMidiChannel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Synthesizer/AsynchronousMidiChannel.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Synthesizer/Receiver/bug6186488.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Synthesizer/Receiver/bug6186488.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Synthesizer/bug4685396.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Synthesizer/bug4685396.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Track/TrackAddSameTick.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Track/TrackAddSameTick.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Track/bug6416024.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Track/bug6416024.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/midi/Transmitter/bug6415669.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/midi/Transmitter/bug6415669.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioFileFormat/AudioFileFormatToString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioFileFormat/AudioFileFormatToString.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioFileFormat/Properties.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioFileFormat/Properties.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioFileFormat/TypeEquals.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioFileFormat/TypeEquals.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioFormat/AudioFormatBitSize.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioFormat/AudioFormatBitSize.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioFormat/EncodingEquals.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioFormat/EncodingEquals.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioFormat/Properties.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioFormat/Properties.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioInputStream/AISReadFraction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioInputStream/AISReadFraction.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioInputStream/bug6188860.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioInputStream/bug6188860.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioSystem/AudioFileTypes/AudioFileTypeUniqueness.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioSystem/AudioFileTypes/AudioFileTypeUniqueness.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioSystem/AudioFileTypes/ShowAudioFileTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioSystem/AudioFileTypes/ShowAudioFileTypes.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioSystem/DefaultMixers.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioSystem/DefaultMixers.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioSystem/DefaultProperties.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioSystem/DefaultProperties.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioSystem/ProviderCacheing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioSystem/ProviderCacheing.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/AudioSystem/testdata/conf/sound.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioSystem/testdata/conf/sound.properties Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Clip/ClipCloseLoss.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Clip/ClipCloseLoss.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Clip/ClipFlushCrash.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Clip/ClipFlushCrash.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Clip/Drain/ClipDrain.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Clip/Drain/ClipDrain.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Clip/Duration/ClipDuration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Clip/Duration/ClipDuration.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Clip/Endpoint/ClipSetEndPoint.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Clip/Endpoint/ClipSetEndPoint.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Clip/Open/ClipOpenBug.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Clip/Open/ClipOpenBug.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Clip/bug5070081.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Clip/bug5070081.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Clip/bug6251460.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Clip/bug6251460.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Controls/CompoundControl/ToString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Controls/CompoundControl/ToString.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Controls/FloatControl/FloatControlBug.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Controls/FloatControl/FloatControlBug.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/DataLine/DataLineInfoNegBufferSize.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/DataLine/DataLineInfoNegBufferSize.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/DataLine/LineDefFormat.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/DataLine/LineDefFormat.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/DirectAudio/TickAtEndOfPlay.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/DirectAudio/TickAtEndOfPlay.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/FileTypeExtension/FileTypeExtensionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/FileTypeExtension/FileTypeExtensionTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/LineEvent/LineInfoNPE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/LineEvent/LineInfoNPE.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Lines/16and32KHz/Has16and32KHz.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Lines/16and32KHz/Has16and32KHz.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Lines/BufferSizeCheck.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Lines/BufferSizeCheck.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Lines/ChangingBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Lines/ChangingBuffer.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Lines/ClipOpenException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Lines/ClipOpenException.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Lines/SourceDataLineDefaultBufferSizeCrash.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Lines/SourceDataLineDefaultBufferSizeCrash.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Lines/StopStart.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Lines/StopStart.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/LinuxBlock/PlaySine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/LinuxBlock/PlaySine.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash2.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/LinuxCrash/SDLLinuxCrash.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/LinuxCrash/SDLLinuxCrash.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/BogusMixers.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/BogusMixers.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/DirectSoundRepeatingBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/DirectSoundRepeatingBuffer.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/Test4997635.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/Test4997635.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/DirectSoundUnderrunSilence.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/DirectSoundUnderrunSilence.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/Test5032020.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/Test5032020.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/DisabledAssertionCrash.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/DisabledAssertionCrash.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/NoSimpleInputDevice.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/NoSimpleInputDevice.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/PhantomMixers.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/PhantomMixers.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/PlugHwMonoAnd8bitAvailable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/PlugHwMonoAnd8bitAvailable.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/Mixers/UnexpectedIAE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/Mixers/UnexpectedIAE.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileReader/AIFFCp037.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/AIFFCp037.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileReader/AIFFLargeHeader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/AIFFLargeHeader.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileReader/Aiff12bit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/Aiff12bit.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileReader/AuNotSpecified.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/AuNotSpecified.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileReader/AuZeroLength.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/AuZeroLength.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileReader/OpenWaveFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/OpenWaveFile.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileWriter/AUwithULAW.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/AUwithULAW.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileWriter/AiffSampleRate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/AiffSampleRate.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileWriter/RIFFHeader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/RIFFHeader.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileWriter/WaveBigEndian.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/WaveBigEndian.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/AudioFileWriter/WriteAuUnspecifiedLength.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/WriteAuUnspecifiedLength.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 -r a4ee110842fb -r 8750872276b8 jdk/test/javax/sound/sampled/spi/FormatConversionProvider/AlawUlaw.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/spi/FormatConversionProvider/AlawUlaw.java Wed Jul 05 22:25:59 2017 +0200 @@ -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 CONFIGS = getConfigs(); + + private static List getConfigs() { + + Random rnd = RandomFactory.getRandom(); + + List configs = new ArrayList<>(); + + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] devices = ge.getScreenDevices(); + + for (GraphicsDevice device : devices) { + GraphicsConfiguration[] allConfigs = device.getConfigurations(); + int nConfigs = allConfigs.length; + if (nConfigs <= MAX_N_CONFIGS) { + Collections.addAll(configs, allConfigs); + } else { // see JDK-8159454 + System.out.println("check only " + MAX_N_CONFIGS + + " configurations for device " + device); + configs.add(device.getDefaultConfiguration()); // check default + for (int j = 0; j < MAX_N_CONFIGS - 1; j++) { + int k = rnd.nextInt(nConfigs); + configs.add(allConfigs[k]); + } + } + } + + return configs; + } + + private static class TestFactory extends PopupFactory { private static TestFactory newFactory = new TestFactory(); @@ -62,15 +117,21 @@ } // Actual test happens here + @Override public Popup getPopup(Component owner, Component contents, int x, int y) { - GraphicsConfiguration mouseGC = testGC(MouseInfo.getPointerInfo().getLocation()); + + GraphicsConfiguration mouseGC = + testGC(MouseInfo.getPointerInfo().getLocation()); + if (mouseGC == null) { - throw new RuntimeException("Can't find GraphicsConfiguration that mouse pointer belongs to"); + throw new RuntimeException("Can't find GraphicsConfiguration " + + "that mouse pointer belongs to"); } GraphicsConfiguration tipGC = testGC(new Point(x, y)); if (tipGC == null) { - throw new RuntimeException("Can't find GraphicsConfiguration that tip belongs to"); + throw new RuntimeException( + "Can't find GraphicsConfiguration that tip belongs to"); } if (!mouseGC.equals(tipGC)) { @@ -81,17 +142,14 @@ } private static GraphicsConfiguration testGC(Point pt) { - GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] devices = environment.getScreenDevices(); - for (GraphicsDevice device : devices) { - GraphicsConfiguration[] configs = device.getConfigurations(); - for (GraphicsConfiguration config : configs) { - Rectangle rect = config.getBounds(); - Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config); - adjustInsets(rect, insets); - if (rect.contains(pt)) - return config; - } + + for (GraphicsConfiguration config: CONFIGS) { + + Rectangle rect = config.getBounds(); + Insets insets = + Toolkit.getDefaultToolkit().getScreenInsets(config); + adjustInsets(rect, insets); + if (rect.contains(pt)) { return config; } } return null; @@ -103,15 +161,18 @@ private static Robot robot; public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new MetalLookAndFeel()); setUp(); testToolTip(); TestFactory.uninstall(); + if (frame != null) { frame.dispose(); } } // Creates a window that is stretched across all available monitors // and adds itself as ContainerListener to track tooltips drawing private bug7123767() { + super(); ToolTipManager.sharedInstance().setInitialDelay(0); @@ -135,17 +196,16 @@ pack(); Rectangle rect = new Rectangle(); - GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] devices = environment.getScreenDevices(); - for (GraphicsDevice device : devices) { - GraphicsConfiguration[] configs = device.getConfigurations(); - for (GraphicsConfiguration config : configs) { - Insets localInsets = Toolkit.getDefaultToolkit().getScreenInsets(config); - Rectangle localRect = config.getBounds(); - adjustInsets(localRect, localInsets); - rect.add(localRect); - } + + for (GraphicsConfiguration config: CONFIGS) { + + Insets localInsets = + Toolkit.getDefaultToolkit().getScreenInsets(config); + Rectangle localRect = config.getBounds(); + adjustInsets(localRect, localInsets); + rect.add(localRect); } + setBounds(rect); } @@ -166,35 +226,32 @@ robot.setAutoDelay(20); robot.waitForIdle(); - GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] devices = environment.getScreenDevices(); - for (GraphicsDevice device : devices) { - GraphicsConfiguration[] configs = device.getConfigurations(); - for (GraphicsConfiguration config : configs) { - Rectangle rect = config.getBounds(); - Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config); - adjustInsets(rect, insets); + for (GraphicsConfiguration config: CONFIGS) { - // Upper left - glide(rect.x + rect.width / 2, rect.y + rect.height / 2, - rect.x + MARGIN, rect.y + MARGIN); - robot.waitForIdle(); + Rectangle rect = config.getBounds(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config); + adjustInsets(rect, insets); + + // Upper left + glide(rect.x + rect.width / 2, rect.y + rect.height / 2, + rect.x + MARGIN, rect.y + MARGIN); + robot.waitForIdle(); - // Lower left - glide(rect.x + rect.width / 2, rect.y + rect.height / 2, - rect.x + MARGIN, rect.y + rect.height - MARGIN); - robot.waitForIdle(); + // Lower left + glide(rect.x + rect.width / 2, rect.y + rect.height / 2, + rect.x + MARGIN, rect.y + rect.height - MARGIN); + robot.waitForIdle(); - // Upper right - glide(rect.x + rect.width / 2, rect.y + rect.height / 2, - rect.x + rect.width - MARGIN, rect.y + MARGIN); - robot.waitForIdle(); + // Upper right + glide(rect.x + rect.width / 2, rect.y + rect.height / 2, + rect.x + rect.width - MARGIN, rect.y + MARGIN); + robot.waitForIdle(); - // Lower right - glide(rect.x + rect.width / 2, rect.y + rect.height / 2, - rect.x + rect.width - MARGIN, rect.y + rect.height - MARGIN); - robot.waitForIdle(); - } + // Lower right + glide(rect.x + rect.width / 2, rect.y + rect.height / 2, + rect.x + rect.width - MARGIN, rect.y + rect.height - MARGIN); + + robot.waitForIdle(); } } diff -r a4ee110842fb -r 8750872276b8 jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java --- a/jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java Wed Jul 05 22:25:59 2017 +0200 @@ -24,11 +24,10 @@ /* * @test * @key headful - * @bug 6796710 7124242 + * @bug 6796710 7124242 8168540 * @summary Html content in JEditorPane is overlapping on swing components while resizing the application. * @library ../../../regtesthelpers * @build Util - * @author Pavel Porvatov @run main bug6796710 */ @@ -109,7 +108,7 @@ } }); - robot.waitForIdle(); + robot.delay(1000); // On Linux platforms realSync doesn't guaranties setSize completion Thread.sleep(1000); diff -r a4ee110842fb -r 8750872276b8 jdk/test/jdk/editpad/EditPadTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/editpad/EditPadTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,342 @@ +/* + * Copyright (c) 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 8167636 8167639 8168972 + * @summary Testing built-in editor. + * @modules java.desktop/java.awt + * jdk.internal.ed/jdk.internal.editor.spi + * jdk.editpad/jdk.editpad + * @run testng EditPadTest + */ + +import java.awt.AWTException; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GraphicsEnvironment; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.ServiceLoader; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.function.Consumer; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JViewport; +import javax.swing.SwingUtilities; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import jdk.internal.editor.spi.BuildInEditorProvider; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +@Test +public class EditPadTest { + + private static final int DELAY = 500; + private static final String WINDOW_LABEL = "Test Edit Pad"; + + private static ExecutorService executor; + private static Robot robot; + private static JFrame frame = null; + private static JTextArea area = null; + private static JButton cancel = null; + private static JButton accept = null; + private static JButton exit = null; + + @BeforeClass + public static void setUpEditorPadTest() { + if (!GraphicsEnvironment.isHeadless()) { + try { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(DELAY); + } catch (AWTException e) { + throw new ExceptionInInitializerError(e); + } + } + } + + @AfterClass + public static void shutdown() { + executorShutdown(); + } + + public void testSimple() { + testEdit("abcdef", 1, "xyz", + () -> assertSource("abcdef"), + () -> writeSource("xyz"), + () -> accept(), + () -> assertSource("xyz"), + () -> shutdownEditor()); + } + + public void testCancel() { + testEdit("abcdef", 0, "abcdef", + () -> assertSource("abcdef"), + () -> writeSource("xyz"), + () -> cancel()); + } + + public void testAbort() { + testEdit("abcdef", 0, "abcdef", + () -> assertSource("abcdef"), + () -> writeSource("xyz"), + () -> shutdownEditor()); + } + + public void testAcceptCancel() { + testEdit("abcdef", 1, "xyz", + () -> assertSource("abcdef"), + () -> writeSource("xyz"), + () -> accept(), + () -> assertSource("xyz"), + () -> writeSource("!!!!!!!!!"), + () -> cancel()); + } + + public void testAcceptEdit() { + testEdit("abcdef", 2, "xyz", + () -> assertSource("abcdef"), + () -> writeSource("NoNo"), + () -> accept(), + () -> assertSource("NoNo"), + () -> writeSource("xyz"), + () -> exit()); + } + + private void testEdit(String initialText, + int savedCount, String savedText, Runnable... actions) { + class Handler { + + String text = null; + int count = 0; + + void handle(String s) { + ++count; + text = s; + } + } + Handler save = new Handler(); + Handler error = new Handler(); + + if (GraphicsEnvironment.isHeadless()) { + // Do not actually run if we are headless + return; + } + Future task = doActions(actions); + builtInEdit(initialText, save::handle, error::handle); + complete(task); + assertEquals(error.count, 0, "Error: " + error.text); + assertTrue(save.count != savedCount + || save.text == null + ? savedText != null + : savedText.equals(save.text), + "Expected " + savedCount + " saves, got " + save.count + + ", expected \"" + savedText + "\" got \"" + save.text + "\""); + } + + private static ExecutorService getExecutor() { + if (executor == null) { + executor = Executors.newSingleThreadExecutor(); + } + return executor; + } + + private static void executorShutdown() { + if (executor != null) { + executor.shutdown(); + executor = null; + } + } + + private void builtInEdit(String initialText, + Consumer saveHandler, Consumer errorHandler) { + ServiceLoader sl + = ServiceLoader.load(BuildInEditorProvider.class); + // Find the highest ranking provider + BuildInEditorProvider provider = null; + for (BuildInEditorProvider p : sl) { + if (provider == null || p.rank() > provider.rank()) { + provider = p; + } + } + if (provider != null) { + provider.edit(WINDOW_LABEL, + initialText, saveHandler, errorHandler); + } else { + throw new InternalError("Cannot find provider"); + } + } + + private Future doActions(Runnable... actions) { + return getExecutor().submit(() -> { + try { + waitForIdle(); + SwingUtilities.invokeLater(this::seekElements); + waitForIdle(); + for (Runnable act : actions) { + act.run(); + } + } catch (Throwable e) { + shutdownEditor(); + if (e instanceof AssertionError) { + throw (AssertionError) e; + } + throw new RuntimeException(e); + } + }); + } + + private void complete(Future task) { + try { + task.get(); + waitForIdle(); + } catch (ExecutionException e) { + if (e.getCause() instanceof AssertionError) { + throw (AssertionError) e.getCause(); + } + throw new RuntimeException(e); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + shutdownEditor(); + } + } + + private void writeSource(String s) { + SwingUtilities.invokeLater(() -> area.setText(s)); + } + + private void assertSource(String expected) { + String[] s = new String[1]; + try { + SwingUtilities.invokeAndWait(() -> s[0] = area.getText()); + } catch (InvocationTargetException | InterruptedException e) { + throw new RuntimeException(e); + } + assertEquals(s[0], expected); + } + + private void accept() { + clickOn(accept); + } + + private void exit() { + clickOn(exit); + } + + private void cancel() { + clickOn(cancel); + } + + private void shutdownEditor() { + SwingUtilities.invokeLater(this::clearElements); + waitForIdle(); + } + + private void waitForIdle() { + robot.waitForIdle(); + robot.delay(DELAY); + } + + private void seekElements() { + for (Frame f : Frame.getFrames()) { + if (f.getTitle().equals(WINDOW_LABEL)) { + frame = (JFrame) f; + // workaround + frame.setLocation(0, 0); + Container root = frame.getContentPane(); + for (Component c : root.getComponents()) { + if (c instanceof JScrollPane) { + JScrollPane scrollPane = (JScrollPane) c; + for (Component comp : scrollPane.getComponents()) { + if (comp instanceof JViewport) { + JViewport view = (JViewport) comp; + area = (JTextArea) view.getComponent(0); + } + } + } + if (c instanceof JPanel) { + JPanel p = (JPanel) c; + for (Component comp : p.getComponents()) { + if (comp instanceof JButton) { + JButton b = (JButton) comp; + switch (b.getText()) { + case "Cancel": + cancel = b; + break; + case "Exit": + exit = b; + break; + case "Accept": + accept = b; + break; + } + } + } + } + } + } + } + } + + private void clearElements() { + if (frame != null) { + frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); + frame = null; + } + area = null; + accept = null; + cancel = null; + exit = null; + } + + private void clickOn(JButton button) { + waitForIdle(); + waitForIdle(); + waitForIdle(); + waitForIdle(); + waitForIdle(); + waitForIdle(); + Point p = button.getLocationOnScreen(); + Dimension d = button.getSize(); + robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java --- a/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java Wed Jul 05 22:25:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -35,7 +35,7 @@ * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary JavaVM + * @build JavaVM * @run main/othervm NoConsoleOutput */ @@ -43,8 +43,6 @@ import java.io.File; import java.rmi.Remote; import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; public class NoConsoleOutput { @@ -53,7 +51,7 @@ System.err.println("\nRegression test for bug 6409194\n"); /* - * Exdecute a subprocess VM that does a bunch of RMI activity + * Execute a subprocess VM that does a bunch of RMI activity * with a logging configuration file that does not specify a * ConsoleHandler and with no legacy sun.rmi.*.logLevel system * properties set. @@ -65,7 +63,7 @@ ByteArrayOutputStream err = new ByteArrayOutputStream(); // We instantiate a JavaVM that should not produce any console output - // (neither on standard output, nor on standard err streams). + // on standard err streams, where RMI logging messages are sent to. JavaVM vm = new JavaVM( DoRMIStuff.class.getName(), "--add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED" @@ -77,8 +75,7 @@ vm.execute(); /* - * Verify that the subprocess had no System.out or System.err - * output. + * Verify that the subprocess had no System.err output. */ String outString = out.toString(); String errString = err.toString(); @@ -89,7 +86,7 @@ System.err.print(err); System.err.println("---------------------------------------------"); - if (outString.length() > 0 || errString.length() > 0) { + if (errString.length() > 0) { throw new Error("TEST FAILED: unexpected subprocess output"); } @@ -105,13 +102,8 @@ public Object echo(Object obj) { return obj; } } public static void main(String[] args) throws Exception { - Registry registry = TestLibrary.createRegistryOnUnusedPort(); - int registryPort = TestLibrary.getRegistryPort(registry); - Registry reg = LocateRegistry.getRegistry("", registryPort); FooImpl fooimpl = new FooImpl(); - UnicastRemoteObject.exportObject(fooimpl, 0); - reg.rebind("foo", fooimpl); - Foo foostub = (Foo) reg.lookup("foo"); + Foo foostub = (Foo) UnicastRemoteObject.exportObject(fooimpl, 0); FooImpl fooimpl2 = new FooImpl(); UnicastRemoteObject.exportObject(fooimpl2, 0); foostub.echo(fooimpl2); diff -r a4ee110842fb -r 8750872276b8 jdk/test/sun/security/ec/TestEC.java --- a/jdk/test/sun/security/ec/TestEC.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/sun/security/ec/TestEC.java Wed Jul 05 22:25:59 2017 +0200 @@ -35,7 +35,7 @@ * @library ../pkcs11/sslecc * @library ../../../java/security/testlibrary * @modules jdk.crypto.pkcs11/sun.security.pkcs11.wrapper - * @compile -XDignore.symbol.file TestEC.java + * @compile --add-modules jdk.crypto.pkcs11 TestEC.java * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC * @run main/othervm/java.security.policy=TestEC.policy -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC */ diff -r a4ee110842fb -r 8750872276b8 jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java --- a/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java Wed Jul 05 22:25:59 2017 +0200 @@ -26,6 +26,7 @@ * @bug 6318171 6931562 * @requires os.family == "windows" * @modules jdk.crypto.mscapi/sun.security.mscapi + * @compile --add-modules jdk.crypto.mscapi IsSunMSCAPIAvailable.java * @run main/othervm IsSunMSCAPIAvailable */ diff -r a4ee110842fb -r 8750872276b8 jdk/test/sun/security/pkcs11/ec/TestCurves.java --- a/jdk/test/sun/security/pkcs11/ec/TestCurves.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/sun/security/pkcs11/ec/TestCurves.java Wed Jul 05 22:25:59 2017 +0200 @@ -28,7 +28,7 @@ * @author Andreas Sterbenz * @library .. * @modules jdk.crypto.pkcs11/sun.security.pkcs11.wrapper - * @compile -XDignore.symbol.file TestCurves.java + * @compile --add-modules jdk.crypto.pkcs11 TestCurves.java * @run main/othervm TestCurves * @run main/othervm TestCurves sm * @key randomness diff -r a4ee110842fb -r 8750872276b8 jdk/test/tools/jlink/JLinkSigningTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/jlink/JLinkSigningTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,195 @@ +/* + * 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 8159393 + * @summary Test signed jars involved in image creation + * @modules java.base/jdk.internal.jimage + * jdk.jlink/jdk.tools.jlink.internal + * jdk.compiler/com.sun.tools.javac + * java.base/sun.security.tools.keytool + * jdk.jartool/sun.security.tools.jarsigner + * jdk.jartool/sun.tools.jar + * @run main/othervm JLinkSigningTest + */ + + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +public class JLinkSigningTest { + static final String[] MODULE_INFO = { + "module test {", + "}", + }; + + static final String[] TEST_CLASS = { + "package test;", + "public class test {", + " public static void main(String[] args) {", + " }", + "}", + }; + + static void report(String command, String[] args) { + System.out.println(command + " " + String.join(" ", Arrays.asList(args))); + } + + static void javac(String[] args) { + report("javac", args); + com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main(); + + if (javac.compile(args) != 0) { + throw new RuntimeException("javac failed"); + } + } + + static void jar(String[] args) { + report("jar", args); + sun.tools.jar.Main jar = new sun.tools.jar.Main(System.out, System.err, "jar"); + + if (!jar.run(args)) { + throw new RuntimeException("jar failed"); + } + } + + static void keytool(String[] args) { + report("keytool", args); + + try { + sun.security.tools.keytool.Main.main(args); + } catch (Exception ex) { + throw new RuntimeException("keytool failed"); + } + } + + static void jarsigner(String[] args) { + report("jarsigner", args); + + try { + sun.security.tools.jarsigner.Main.main(args); + } catch (Exception ex) { + throw new RuntimeException("jarsigner failed"); + } + } + + static void jlink(String[] args) { + report("jlink", args); + + try { + jdk.tools.jlink.internal.Main.run(new PrintWriter(System.out, true), + new PrintWriter(System.err, true), + args); + } catch (Exception ex) { + throw new RuntimeException("jlink failed"); + } + } + + public static void main(String[] args) { + final String JAVA_HOME = System.getProperty("java.home"); + Path moduleInfoJavaPath = Paths.get("module-info.java"); + Path moduleInfoClassPath = Paths.get("module-info.class"); + Path testDirectoryPath = Paths.get("test"); + Path testJavaPath = testDirectoryPath.resolve("test.java"); + Path testClassPath = testDirectoryPath.resolve("test.class"); + Path testModsDirectoryPath = Paths.get("testmods"); + Path jmodsPath = Paths.get(JAVA_HOME, "jmods"); + Path testjarPath = testModsDirectoryPath.resolve("test.jar"); + String modulesPath = testjarPath.toString() + + File.pathSeparator + + jmodsPath.toString(); + + try { + Files.write(moduleInfoJavaPath, Arrays.asList(MODULE_INFO)); + Files.createDirectories(testDirectoryPath); + Files.write(testJavaPath, Arrays.asList(TEST_CLASS)); + Files.createDirectories(testModsDirectoryPath); + } catch (IOException ex) { + throw new RuntimeException("file construction failed"); + } + + javac(new String[] { + testJavaPath.toString(), + moduleInfoJavaPath.toString(), + }); + + jar(new String[] { + "-c", + "-f", testjarPath.toString(), + "--module-path", jmodsPath.toString(), + testClassPath.toString(), + moduleInfoClassPath.toString(), + }); + + keytool(new String[] { + "-genkey", + "-keyalg", "RSA", + "-dname", "CN=John Doe, OU=JPG, O=Oracle, L=Santa Clara, ST=California, C=US", + "-alias", "examplekey", + "-storepass", "password", + "-keypass", "password", + "-keystore", "examplekeystore", + "-validity", "365", + }); + + jarsigner(new String[] { + "-keystore", "examplekeystore", + "-verbose", testjarPath.toString(), + "-storepass", "password", + "-keypass", "password", + "examplekey", + }); + + try { + jlink(new String[] { + "--module-path", modulesPath, + "--add-modules", "test", + "--output", "foo", + }); + } catch (Throwable ex) { + System.out.println("Failed as should"); + } + + try { + jlink(new String[] { + "--module-path", modulesPath, + "--add-modules", "test", + "--ignore-signing-information", + "--output", "foo", + }); + System.out.println("Suceeded as should"); + } catch (Throwable ex) { + System.err.println("Should not have failed"); + throw new RuntimeException(ex); + } + + System.out.println("Done"); + } +} + diff -r a4ee110842fb -r 8750872276b8 jdk/test/tools/jmod/JmodTest.java --- a/jdk/test/tools/jmod/JmodTest.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/tools/jmod/JmodTest.java Wed Jul 05 22:25:59 2017 +0200 @@ -28,6 +28,7 @@ * jdk.jlink * @build jdk.testlibrary.FileUtils CompilerUtils * @run testng JmodTest + * @bug 8142968 * @summary Basic test for jmod */ @@ -85,6 +86,31 @@ Files.createDirectories(MODS_DIR); } + // JDK-8166286 - jmod fails on symlink to directory + @Test + public void testSymlinks() throws IOException { + Path apaDir = EXPLODED_DIR.resolve("apa"); + Path classesDir = EXPLODED_DIR.resolve("apa").resolve("classes"); + assertTrue(compileModule("apa", classesDir)); + Path libDir = apaDir.resolve("lib"); + createFiles(libDir, List.of("foo/bar/libfoo.so")); + try { + Path link = Files.createSymbolicLink( + libDir.resolve("baz"), libDir.resolve("foo").toAbsolutePath()); + assertTrue(Files.exists(link)); + } catch (UnsupportedOperationException uoe) { + // OS does not support symlinks. Nothing to test! + return; + } + + Path jmod = MODS_DIR.resolve("apa.jmod"); + jmod("create", + "--libs=", libDir.toString(), + "--class-path", classesDir.toString(), + jmod.toString()) + .assertSuccess(); + } + @Test public void testList() throws IOException { String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString(); diff -r a4ee110842fb -r 8750872276b8 jdk/test/tools/jmod/src/apa/jdk/test/apa/Apa.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/jmod/src/apa/jdk/test/apa/Apa.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,28 @@ +/* + * 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. 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 jdk.test.apa; + +public class Apa { } diff -r a4ee110842fb -r 8750872276b8 jdk/test/tools/jmod/src/apa/module-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/jmod/src/apa/module-info.java Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,28 @@ +/* + * 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. 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. + */ + +module apa { + exports jdk.test.apa; +} diff -r a4ee110842fb -r 8750872276b8 jdk/test/tools/launcher/MiscTests.java --- a/jdk/test/tools/launcher/MiscTests.java Mon Nov 07 16:08:18 2016 +0000 +++ b/jdk/test/tools/launcher/MiscTests.java Wed Jul 05 22:25:59 2017 +0200 @@ -69,8 +69,6 @@ static void test6856415() throws IOException { final String mainClass = "Foo6856415"; - final String exportOpts - = "--add-exports=jdk.crypto.pkcs11/sun.security.pkcs11=ALL-UNNAMED"; List scratch = new ArrayList<>(); scratch.add("public class Foo6856415 {"); @@ -81,7 +79,9 @@ scratch.add("}"); createFile(new File(mainClass + ".java"), scratch); - compile(mainClass + ".java", exportOpts); + compile(mainClass + ".java", + "--add-modules=jdk.crypto.pkcs11", + "--add-exports=jdk.crypto.pkcs11/sun.security.pkcs11=ALL-UNNAMED"); File testJar = new File("Foo.jar"); testJar.delete(); diff -r a4ee110842fb -r 8750872276b8 make/Bundles.gmk --- a/make/Bundles.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/make/Bundles.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -256,7 +256,7 @@ $(eval $(call SetupBundleFile, BUILD_DEMOS_BUNDLE, \ BUNDLE_NAME := $(DEMOS_BUNDLE_NAME), \ - FILES := $(call DoubleDollar, $(DEMOS_BUNDLE_FILES)), \ + FILES := $(DEMOS_BUNDLE_FILES), \ BASE_DIR := $(JDK_IMAGE_DIR), \ SUBDIR := $(JDK_BUNDLE_SUBDIR), \ )) @@ -271,7 +271,7 @@ $(eval $(call SetupBundleFile, BUILD_TEST_BUNDLE, \ BUNDLE_NAME := $(TEST_BUNDLE_NAME), \ - FILES := $(call DoubleDollar, $(TEST_BUNDLE_FILES)), \ + FILES := $(TEST_BUNDLE_FILES), \ BASE_DIR := $(TEST_IMAGE_DIR), \ )) diff -r a4ee110842fb -r 8750872276b8 make/CompileJavaModules.gmk --- a/make/CompileJavaModules.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/make/CompileJavaModules.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -95,7 +95,7 @@ ################################################################################ java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference \ - '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation,-exports + '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation,exports java.desktop_COPY := .gif .png .wav .txt .xml .css .pf java.desktop_CLEAN := iio-plugin.properties cursors.properties @@ -365,6 +365,10 @@ ################################################################################ +jdk.editpad_COPY := .properties + +################################################################################ + jdk.internal.le_COPY := .properties ################################################################################ diff -r a4ee110842fb -r 8750872276b8 make/CreateJmods.gmk --- a/make/CreateJmods.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/make/CreateJmods.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -36,6 +36,7 @@ ################################################################################ JMODS_DIR := $(IMAGES_OUTPUTDIR)/jmods +JMODS_TEMPDIR := $(SUPPORT_OUTPUTDIR)/jmods LIBS_DIR := $(firstword $(wildcard $(addsuffix /$(MODULE), \ $(SUPPORT_OUTPUTDIR)/modules_libs $(IMPORT_MODULES_LIBS)))) @@ -81,16 +82,19 @@ # Add dependencies on other jmod files. Only java.base needs access to other # jmods. ifeq ($(MODULE), java.base) - ALL_UPGRADEABLE_MODULES = $(call FindAllUpgradeableModules) # When creating a BUILDJDK, we don't need to add hashes to java.base ifneq ($(CREATING_BUILDJDK), true) - DEPS += $(patsubst %, $(JMODS_DIR)/%.jmod, \ - $(filter-out java.base $(ALL_UPGRADEABLE_MODULES), $(call FindAllModules))) + # When creating interim versions of jmods, skip hashes + ifneq ($(INTERIM_JMOD), true) + ALL_UPGRADEABLE_MODULES := $(call FindAllUpgradeableModules) + DEPS += $(patsubst %, $(JMODS_DIR)/%.jmod, \ + $(filter-out java.base $(ALL_UPGRADEABLE_MODULES), $(call FindAllModules))) - EXCLUDE_PATTERN := $(strip $(subst $(SPACE),|,$(strip $(ALL_UPGRADEABLE_MODULES)))) + EXCLUDE_PATTERN := $(strip $(subst $(SPACE),|,$(strip $(ALL_UPGRADEABLE_MODULES)))) - JMOD_FLAGS += --module-path $(JMODS_DIR) \ - --hash-modules '^(?!$(EXCLUDE_PATTERN))' + JMOD_FLAGS += --module-path $(JMODS_DIR) \ + --hash-modules '^(?!$(EXCLUDE_PATTERN))' + endif endif endif @@ -102,13 +106,19 @@ DEPS += $(call CacheFind, $(JDK_OUTPUTDIR)/modules/jdk.jlink/jdk/tools/jmod) endif +# If creating interim versions of jmods, certain files need to be filtered out +# to avoid false incremental rebuilds. +ifeq ($(INTERIM_JMOD), true) + DEPS := $(filter-out $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/classlist, $(DEPS)) +endif + # TODO: What about headers? # Create jmods in a temp dir and then move them into place to keep the # module path in $(IMAGES_OUTPUTDIR)/jmods valid at all times. $(JMODS_DIR)/$(MODULE).jmod: $(DEPS) $(call LogWarn, Creating $(patsubst $(OUTPUT_ROOT)/%, %, $@)) - $(call MakeDir, $(@D) $(SUPPORT_OUTPUTDIR)/jmods) - $(RM) $@ $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) + $(call MakeDir, $(JMODS_DIR) $(JMODS_TEMPDIR)) + $(RM) $@ $(JMODS_TEMPDIR)/$(notdir $@) $(JMOD) create \ --module-version $(VERSION_SHORT) \ --os-name $(REQUIRED_OS_NAME) \ @@ -116,10 +126,10 @@ --os-version $(REQUIRED_OS_VERSION) \ --module-path $(JMODS_DIR) \ --exclude '**{_the.*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM,*.pdb,*.map}' \ - $(JMOD_FLAGS) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) - $(MV) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) $@ + $(JMOD_FLAGS) $(JMODS_TEMPDIR)/$(notdir $@) + $(MV) $(JMODS_TEMPDIR)/$(notdir $@) $@ -TARGETS += $(IMAGES_OUTPUTDIR)/jmods/$(MODULE).jmod +TARGETS += $(JMODS_DIR)/$(MODULE).jmod ################################################################################ diff -r a4ee110842fb -r 8750872276b8 make/GenerateLinkOptData.gmk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/GenerateLinkOptData.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,88 @@ +# +# 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. 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. +# + +################################################################################ +# Generate classlist +################################################################################ + +default: all + +include $(SPEC) +include MakeBase.gmk +include JarArchive.gmk + +################################################################################ +# Create a jar with our generator class. Using a jar is intentional since it +# will load more classes + +$(eval $(call SetupJarArchive, CLASSLIST_JAR, \ + SRCS := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \ + INCLUDES := build/tools/classlist, \ + JAR := $(SUPPORT_OUTPUTDIR)/classlist.jar, \ +)) + +TARGETS += $(CLASSLIST_JAR) + +################################################################################ + +LINK_OPT_DIR := $(SUPPORT_OUTPUTDIR)/link_opt +CLASSLIST_FILE := $(LINK_OPT_DIR)/classlist +JLI_TRACE_FILE := $(LINK_OPT_DIR)/jli_trace.out + +# If an external buildjdk has been supplied, we don't build a separate interim +# image, so just use the external build jdk instead. +ifeq ($(EXTERNAL_BUILDJDK), true) + INTERIM_IMAGE_DIR := $(BUILD_JDK) +endif + +$(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR) + $(call MakeDir, $(LINK_OPT_DIR)) + $(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $@)) + $(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $(JLI_TRACE_FILE))) + $(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \ + -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \ + -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \ + build.tools.classlist.HelloClasslist \ + $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE) + +# The jli trace is created by the same recipe as classlist. By declaring these +# dependencies, make will correctly rebuild both jli trace and classlist +# incrementally using the single recpie above. +$(CLASSLIST_FILE): $(JLI_TRACE_FILE) +$(JLI_TRACE_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR) + +TARGETS += $(CLASSLIST_FILE) $(JLI_TRACE_FILE) + +# Copy the classlist file into java.base libs +$(eval $(call SetupCopyFiles, COPY_CLASSLIST, \ + FILES := $(CLASSLIST_FILE), \ + DEST := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base, \ +)) + +TARGETS += $(COPY_CLASSLIST) + +################################################################################ + +all: $(TARGETS) diff -r a4ee110842fb -r 8750872276b8 make/Images.gmk --- a/make/Images.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/make/Images.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -113,8 +113,8 @@ JLINK_ORDER_RESOURCES := **module-info.class JLINK_JLI_CLASSES := ifeq ($(ENABLE_GENERATE_CLASSLIST), true) - JLINK_ORDER_RESOURCES += @$(SUPPORT_OUTPUTDIR)/classlist/classlist - JLINK_JLI_CLASSES := --generate-jli-classes=@$(SUPPORT_OUTPUTDIR)/classlist/jli_trace.out + JLINK_ORDER_RESOURCES += @$(SUPPORT_OUTPUTDIR)/link_opt/classlist + JLINK_JLI_CLASSES := --generate-jli-classes=@$(SUPPORT_OUTPUTDIR)/link_opt/jli_trace.out endif JLINK_ORDER_RESOURCES += \ /java.base/java/** \ @@ -142,7 +142,7 @@ $(ECHO) Creating jdk jimage $(RM) -r $(JDK_IMAGE_DIR) $(JLINK_TOOL) --add-modules $(JDK_MODULES_LIST) \ - $(JLINK_JDK_EXTRA_OPTS) \ + $(JLINK_JDK_EXTRA_OPTS) \ --output $(JDK_IMAGE_DIR) $(TOUCH) $@ @@ -152,7 +152,7 @@ $(RM) -r $(JRE_IMAGE_DIR) $(JLINK_TOOL) --add-modules $(JRE_MODULES_LIST) \ $(JLINK_JRE_EXTRA_OPTS) \ - --output $(JRE_IMAGE_DIR) + --output $(JRE_IMAGE_DIR) $(TOUCH) $@ JRE_COMPACT1_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact1 @@ -360,34 +360,15 @@ JDK_TARGETS += $(JDK_IMAGE_DIR)/src.zip ################################################################################ -# classlist - -ifeq ($(ENABLE_GENERATE_CLASSLIST), true) - $(eval $(call SetupCopyFiles, JDK_COPY_CLASSLIST, \ - FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ - DEST := $(JDK_IMAGE_DIR)/lib, \ - )) - - JDK_TARGETS += $(JDK_COPY_CLASSLIST) - - $(eval $(call SetupCopyFiles, JRE_COPY_CLASSLIST, \ - FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ - DEST := $(JRE_IMAGE_DIR)/lib, \ - )) - - JRE_TARGETS += $(JRE_COPY_CLASSLIST) -endif - -################################################################################ # /demo dir # Avoid doing the expensive find unless called with "jdk" as target. ifneq ($(filter jdk, $(MAKECMDGOALS)), ) DEMO_FILES := \ $(if $(wildcard $(SUPPORT_OUTPUTDIR)/demos/image), \ - $(call DoubleDollar, $(call DoubleDollar, \ + $(call DoubleDollar, \ $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/demos/image \ - -type f -a ! \( -name "_the*" -o -name "javac_state" \) ))) \ + -type f -a ! \( -name "_the*" -o -name "javac_state" \) )) \ ) ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true) diff -r a4ee110842fb -r 8750872276b8 make/InterimImage.gmk --- a/make/InterimImage.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/make/InterimImage.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -36,15 +36,15 @@ INTERIM_MODULES_LIST := $(call CommaList, $(INTERIM_IMAGE_MODULES)) -JMODS := $(patsubst %, $(IMAGES_OUTPUTDIR)/jmods/%.jmod, $(INTERIM_IMAGE_MODULES)) +JMODS := $(patsubst %, $(INTERIM_JMODS_DIR)/%.jmod, $(INTERIM_IMAGE_MODULES)) JLINK_TOOL := $(JLINK) \ - --module-path $(IMAGES_OUTPUTDIR)/jmods \ + --module-path $(INTERIM_JMODS_DIR) \ --endian $(OPENJDK_BUILD_CPU_ENDIAN) $(INTERIM_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \ $(call DependOnVariable, INTERIM_MODULES_LIST) - $(ECHO) Creating interim jimage + $(call LogWarn, Creating interim jimage) $(RM) -r $(INTERIM_IMAGE_DIR) $(JLINK_TOOL) \ --output $(INTERIM_IMAGE_DIR) \ diff -r a4ee110842fb -r 8750872276b8 make/Main.gmk --- a/make/Main.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/make/Main.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -376,15 +376,29 @@ # The interim-image is a small jlinked image that is used to generate artifacts # at build time for use when linking the real images. +INTERIM_JMOD_TARGETS := $(addsuffix -interim-jmod, $(INTERIM_IMAGE_MODULES)) + +define DeclareInterimJmodRecipe + $1-interim-jmod: + +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f CreateJmods.gmk \ + MODULE=$1 \ + JMODS_DIR=$(INTERIM_JMODS_DIR) \ + JMODS_TEMPDIR=$(INTERIM_JMODS_DIR)/temp \ + INTERIM_JMOD=true \ + ) +endef + +$(foreach m, $(INTERIM_IMAGE_MODULES), $(eval $(call DeclareInterimJmodRecipe,$m))) + interim-image: +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f InterimImage.gmk) ifeq ($(ENABLE_GENERATE_CLASSLIST), true) - generate-classlist: - +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f GenerateClasslist.gmk) + generate-link-opt-data: + +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f GenerateLinkOptData.gmk) endif -ALL_TARGETS += interim-image generate-classlist +ALL_TARGETS += $(INTERIM_JMOD_TARGETS) interim-image generate-link-opt-data ################################################################################ # Build tests @@ -607,13 +621,15 @@ # When creating a BUILDJDK, the java compilation has already been done by the # normal build and copied in. ifneq ($(CREATING_BUILDJDK), true) - $(foreach m, $(JAVA_MODULES), $(eval $m-jmod: $m-java)) + $(foreach m, $(JAVA_MODULES), $(eval $m_JMOD_DEPS += $m-java)) endif - $(foreach m, $(GENDATA_MODULES), $(eval $m-jmod: $m-gendata)) - $(foreach m, $(RMIC_MODULES), $(eval $m-jmod: $m-rmic)) - $(foreach m, $(LIBS_MODULES), $(eval $m-jmod: $m-libs)) - $(foreach m, $(LAUNCHER_MODULES), $(eval $m-jmod: $m-launchers)) - $(foreach m, $(COPY_MODULES), $(eval $m-jmod: $m-copy)) + $(foreach m, $(GENDATA_MODULES), $(eval $m_JMOD_DEPS += $m-gendata)) + $(foreach m, $(RMIC_MODULES), $(eval $m_JMOD_DEPS += $m-rmic)) + $(foreach m, $(LIBS_MODULES), $(eval $m_JMOD_DEPS += $m-libs)) + $(foreach m, $(LAUNCHER_MODULES), $(eval $m_JMOD_DEPS += $m-launchers)) + $(foreach m, $(COPY_MODULES), $(eval $m_JMOD_DEPS += $m-copy)) + $(foreach m, $(ALL_MODULES), $(eval $m-jmod: $($(m)_JMOD_DEPS))) + $(foreach m, $(INTERIM_IMAGE_MODULES), $(eval $m-interim-jmod: $($(m)_JMOD_DEPS))) # Jmods cannot be created until we have the jmod tool ready to run. During # a normal build we run it from the exploded image, but when cross compiling @@ -636,12 +652,13 @@ buildtools-modules: create-buildjdk else # While actually creating the buildjdk, the default deps applies. - $(JMOD_TARGETS): $(DEFAULT_JMOD_DEPS) + $(JMOD_TARGETS) $(INTERIM_JMOD_TARGETS): $(DEFAULT_JMOD_DEPS) endif else # The normal non cross compilation case uses the default deps. # To avoid races with the optimize target, that also needs to happen first. - $(JMOD_TARGETS): $(DEFAULT_JMOD_DEPS) exploded-image-optimize + $(JMOD_TARGETS) $(INTERIM_JMOD_TARGETS): $(DEFAULT_JMOD_DEPS) \ + exploded-image-optimize endif zip-security: java.base-java java.security.jgss-java java.security.jgss-libs \ @@ -654,16 +671,17 @@ ifeq ($(ENABLE_GENERATE_CLASSLIST), true) ifeq ($(CREATE_BUILDJDK), true) # If creating a buildjdk, the interim image needs to be based on that. - generate-classlist: create-buildjdk + generate-link-opt-data: create-buildjdk else ifeq ($(EXTERNAL_BUILDJDK), false) # If an external buildjdk has been provided, we skip generating an # interim-image and just use the external buildjdk for generating # classlist. - generate-classlist: interim-image + generate-link-opt-data: interim-image endif - generate-classlist: buildtools-jdk + generate-link-opt-data: buildtools-jdk - jdk-image jre-image: generate-classlist + # The generated classlist needs to go into java.base-jmod. + java.base-jmod jdk-image jre-image: generate-link-opt-data endif jdk-image: jmods zip-source source-tips demos samples jrtfs-jar @@ -695,7 +713,7 @@ create-buildjdk-interim-image: create-buildjdk-copy - interim-image: $(addsuffix -jmod, $(INTERIM_IMAGE_MODULES)) + interim-image: $(INTERIM_JMOD_TARGETS) test-make: clean-test-make diff -r a4ee110842fb -r 8750872276b8 make/common/MakeBase.gmk --- a/make/common/MakeBase.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/make/common/MakeBase.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -454,7 +454,7 @@ Too many named arguments to macro, please update MAX_PARAMS in MakeBase.gmk)) # Iterate over 2 3 4... and evaluate the named parameters with $1_ as prefix $(foreach i,$(PARAM_SEQUENCE), $(if $(strip $($i)),\ - $(strip $1)_$(strip $($i)))$(NEWLINE)) + $(strip $1)_$(strip $(call DoubleDollar, $($i))))$(NEWLINE)) # Debug print all named parameter names and values $(if $(findstring $(LOG_LEVEL),debug trace), \ $(info $0 $(strip $1) $(foreach i,$(PARAM_SEQUENCE), \ diff -r a4ee110842fb -r 8750872276b8 nashorn/.hgtags --- a/nashorn/.hgtags Mon Nov 07 16:08:18 2016 +0000 +++ b/nashorn/.hgtags Wed Jul 05 22:25:59 2017 +0200 @@ -376,3 +376,4 @@ 785843878cf78d50cc2959ea2c5a4202bbe885b4 jdk-9+140 a46b7d3867957a868a6cc8ee66c05079b883733a jdk-9+141 d3f5d7311a1aec3152b17d75046d5d298245a0b4 jdk-9+142 +b4e57ead3fae4939b70dd345d1f6744a1dedfa21 jdk-9+143 diff -r a4ee110842fb -r 8750872276b8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Mon Nov 07 16:08:18 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Wed Jul 05 22:25:59 2017 +0200 @@ -343,7 +343,7 @@ symbol = null; } else if (symbol.isParam()) { // Duplicate parameter. Null return will force an error. - throw new AssertionError("duplicate parameter"); + throwParserException(ECMAErrors.getMessage("syntax.error.duplicate.parameter", name), origin); } } else if (isVar) { if (isBlockScope) { diff -r a4ee110842fb -r 8750872276b8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Mon Nov 07 16:08:18 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Wed Jul 05 22:25:59 2017 +0200 @@ -45,6 +45,7 @@ import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CaseNode; import jdk.nashorn.internal.ir.CatchNode; +import jdk.nashorn.internal.ir.ClassNode; import jdk.nashorn.internal.ir.ContinueNode; import jdk.nashorn.internal.ir.DebuggerNode; import jdk.nashorn.internal.ir.EmptyNode; @@ -60,9 +61,11 @@ import jdk.nashorn.internal.ir.LabelNode; import jdk.nashorn.internal.ir.LexicalContext; import jdk.nashorn.internal.ir.LiteralNode; +import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode; import jdk.nashorn.internal.ir.LoopNode; import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.ObjectNode; import jdk.nashorn.internal.ir.ReturnNode; import jdk.nashorn.internal.ir.RuntimeNode; import jdk.nashorn.internal.ir.Statement; @@ -70,6 +73,7 @@ import jdk.nashorn.internal.ir.Symbol; import jdk.nashorn.internal.ir.ThrowNode; import jdk.nashorn.internal.ir.TryNode; +import jdk.nashorn.internal.ir.UnaryNode; import jdk.nashorn.internal.ir.VarNode; import jdk.nashorn.internal.ir.WhileNode; import jdk.nashorn.internal.ir.WithNode; @@ -78,6 +82,8 @@ import jdk.nashorn.internal.parser.Token; import jdk.nashorn.internal.parser.TokenType; import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.ECMAErrors; +import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.logging.DebugLogger; @@ -98,6 +104,7 @@ private final DebugLogger log; private final boolean es6; + private final Source source; // Conservative pattern to test if element names consist of characters valid for identifiers. // This matches any non-zero length alphanumeric string including _ and $ and not starting with a digit. @@ -146,6 +153,7 @@ this.log = initLogger(compiler.getContext()); this.es6 = compiler.getScriptEnvironment()._es6; + this.source = compiler.getSource(); } @Override @@ -241,6 +249,10 @@ } } + if (es6 && expressionStatement.destructuringDeclarationType() != null) { + throwNotImplementedYet("es6.destructuring", expressionStatement); + } + return addStatement(node); } @@ -250,6 +262,14 @@ } @Override + public boolean enterForNode(final ForNode forNode) { + if (es6 && (forNode.getInit() instanceof ObjectNode || forNode.getInit() instanceof ArrayLiteralNode)) { + throwNotImplementedYet("es6.destructuring", forNode); + } + return super.enterForNode(forNode); + } + + @Override public Node leaveForNode(final ForNode forNode) { ForNode newForNode = forNode; @@ -270,6 +290,37 @@ } @Override + public boolean enterFunctionNode(final FunctionNode functionNode) { + if (es6) { + if (functionNode.getKind() == FunctionNode.Kind.MODULE) { + throwNotImplementedYet("es6.module", functionNode); + } + + if (functionNode.getKind() == FunctionNode.Kind.GENERATOR) { + throwNotImplementedYet("es6.generator", functionNode); + } + if (functionNode.usesSuper()) { + throwNotImplementedYet("es6.super", functionNode); + } + + final int numParams = functionNode.getNumOfParams(); + if (numParams > 0) { + final IdentNode lastParam = functionNode.getParameter(numParams - 1); + if (lastParam.isRestParameter()) { + throwNotImplementedYet("es6.rest.param", lastParam); + } + } + for (final IdentNode param : functionNode.getParameters()) { + if (param.isDestructuredParameter()) { + throwNotImplementedYet("es6.destructuring", functionNode); + } + } + } + + return super.enterFunctionNode(functionNode); + } + + @Override public Node leaveFunctionNode(final FunctionNode functionNode) { log.info("END FunctionNode: ", functionNode.getName()); return functionNode; @@ -578,6 +629,29 @@ } @Override + public boolean enterUnaryNode(final UnaryNode unaryNode) { + if (es6) { + if (unaryNode.isTokenType(TokenType.YIELD) || + unaryNode.isTokenType(TokenType.YIELD_STAR)) { + throwNotImplementedYet("es6.yield", unaryNode); + } else if (unaryNode.isTokenType(TokenType.SPREAD_ARGUMENT) || + unaryNode.isTokenType(TokenType.SPREAD_ARRAY)) { + throwNotImplementedYet("es6.spread", unaryNode); + } + } + + return super.enterUnaryNode(unaryNode); + } + + @Override + public boolean enterASSIGN(BinaryNode binaryNode) { + if (es6 && (binaryNode.lhs() instanceof ObjectNode || binaryNode.lhs() instanceof ArrayLiteralNode)) { + throwNotImplementedYet("es6.destructuring", binaryNode); + } + return super.enterASSIGN(binaryNode); + } + + @Override public Node leaveVarNode(final VarNode varNode) { addStatement(varNode); if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) @@ -608,6 +682,12 @@ return addStatement(withNode); } + @Override + public boolean enterClassNode(final ClassNode classNode) { + throwNotImplementedYet("es6.class", classNode); + return super.enterClassNode(classNode); + } + /** * Given a function node that is a callee in a CallNode, replace it with * the appropriate marker function. This is used by {@link CodeGenerator} @@ -766,4 +846,13 @@ } return false; } + + private void throwNotImplementedYet(final String msgId, final Node node) { + final long token = node.getToken(); + final int line = source.getLine(node.getStart()); + final int column = source.getColumn(node.getStart()); + final String message = ECMAErrors.getMessage("unimplemented." + msgId); + final String formatted = ErrorManager.format(message, source, line, column, token); + throw new RuntimeException(formatted); + } } diff -r a4ee110842fb -r 8750872276b8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Mon Nov 07 16:08:18 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Wed Jul 05 22:25:59 2017 +0200 @@ -45,7 +45,7 @@ } @Override - public final boolean enterUnaryNode(final UnaryNode unaryNode) { + public boolean enterUnaryNode(final UnaryNode unaryNode) { switch (unaryNode.tokenType()) { case ADD: return enterADD(unaryNode); diff -r a4ee110842fb -r 8750872276b8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Mon Nov 07 16:08:18 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Jul 05 22:25:59 2017 +0200 @@ -1962,6 +1962,18 @@ switch (type) { case SEMICOLON: // for (init; test; modify) + if (varDeclList != null) { + assert init == null; + init = varDeclList.init; + // late check for missing assignment, now we know it's a for (init; test; modify) loop + if (varDeclList.missingAssignment != null) { + if (varDeclList.missingAssignment instanceof IdentNode) { + throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)varDeclList.missingAssignment).getName())); + } else { + throw error(AbstractParser.message("missing.destructuring.assignment"), varDeclList.missingAssignment.getToken()); + } + } + } // for each (init; test; modify) is invalid if ((flags & ForNode.IS_FOR_EACH) != 0) { diff -r a4ee110842fb -r 8750872276b8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Mon Nov 07 16:08:18 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Jul 05 22:25:59 2017 +0200 @@ -214,6 +214,7 @@ syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode syntax.error.redeclare.variable=Variable "{0}" has already been declared syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement +syntax.error.duplicate.parameter=Duplicate parameter name "{0}" io.error.cant.write=cannot write "{0}" @@ -222,3 +223,12 @@ uri.error.bad.uri=Bad URI "{0}" near offset {1} list.adapter.null.global=Attempted to create the adapter from outside a JavaScript execution context. + +unimplemented.es6.module=ES6 modules are not yet implemented +unimplemented.es6.rest.param=ES6 function rest parameter declaration is not yet implemented +unimplemented.es6.yield=ES6 yield and yield* are not yet implemented +unimplemented.es6.spread=ES6 spread operator is not yet implemented +unimplemented.es6.class=ES6 class declarations and expressions are not yet implemented +unimplemented.es6.destructuring=ES6 destructuring is not yet implemented +unimplemented.es6.generator=ES6 generator is not yet implemented +unimplemented.es6.super=ES6 super keyword is not yet implemented diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/class.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/class.js Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/** + * Class declaration is not implemented + * + * @test + * @run + * @option --language=es6 + */ + +try { + eval("class Foo {}"); +} catch (e) { + print(String(e).replace(/\\/g, "/")) +} diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/class.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/class.js.EXPECTED Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,3 @@ +java.lang.RuntimeException: test/script/basic/es6/class.js#33:3:1:0 ES6 class declarations and expressions are not yet implemented +class Foo {} +^ diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/destructuring.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/destructuring.js Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/** + * Destructuring is not implemented + * + * @test + * @run + * @option --language=es6 + */ + + +function check(code) { + try { + eval(code); + } catch (e) { + print(String(e).replace(/\\/g, "/")) + } +} + +check("var { x: y } = obj;"); +check("let { x: y } = obj;"); +check("const { x: y } = obj;"); +check("({ x: y }) = obj;"); +check("for (var { x: y } of obj) ;"); +check("for (let { x: y } of obj) ;"); +check("var { x, y } = obj;"); +check("let { x, y } = obj;"); +check("const { x, y } = obj;"); +check("({ x, y }) = obj;"); +check("for (var { x, y } of obj) ;"); +check("for (let { x, y } of obj) ;"); +check("var [a, b] = obj;"); +check("let [a, b] = obj;"); +check("const [a, b] = obj;"); +check("[a, b] = obj;"); +check("for ([a, b] of obj) ;"); +check("for (var [a, b] of obj) ;"); +check("for (let [a, b] of obj) ;"); +check("(function({ x: y }) { return x; })()"); +check("(function({ x }) { return x; })()"); +check("(function([x]) { return x; })()"); +check("for (var [[x, y, z] = [4, 5, 6]] = [7, 8, 9]; iterCount < 1; ) ;"); +check("for ([ arrow = () => {} ] of [[]]) ;"); + diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/destructuring.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/destructuring.js.EXPECTED Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,72 @@ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:4 ES6 destructuring is not yet implemented +var { x: y } = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:4 ES6 destructuring is not yet implemented +let { x: y } = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:6 ES6 destructuring is not yet implemented +const { x: y } = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:1 ES6 destructuring is not yet implemented +({ x: y }) = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +for (var { x: y } of obj) ; +^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +for (let { x: y } of obj) ; +^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:4 ES6 destructuring is not yet implemented +var { x, y } = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:4 ES6 destructuring is not yet implemented +let { x, y } = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:6 ES6 destructuring is not yet implemented +const { x, y } = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:1 ES6 destructuring is not yet implemented +({ x, y }) = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +for (var { x, y } of obj) ; +^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +for (let { x, y } of obj) ; +^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:4 ES6 destructuring is not yet implemented +var [a, b] = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:4 ES6 destructuring is not yet implemented +let [a, b] = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:6 ES6 destructuring is not yet implemented +const [a, b] = obj; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +[a, b] = obj; +^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +for ([a, b] of obj) ; +^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +for (var [a, b] of obj) ; +^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +for (let [a, b] of obj) ; +^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:9 ES6 destructuring is not yet implemented +(function({ x: y }) { return x; })() + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:9 ES6 destructuring is not yet implemented +(function({ x }) { return x; })() + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:9 ES6 destructuring is not yet implemented +(function([x]) { return x; })() + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:9 ES6 destructuring is not yet implemented +for (var [[x, y, z] = [4, 5, 6]] = [7, 8, 9]; iterCount < 1; ) ; + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented +for ([ arrow = () => {} ] of [[]]) ; +^ diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/generator.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/generator.js Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,42 @@ +/* + * 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. + */ + +/** + * Generators are not implemented + * + * @test + * @run + * @option --language=es6 + */ + +function check(code) { + try { + eval(code); + } catch (e) { + print(String(e).replace(/\\/g, "/")) + } +} + +check("function* func() { yield 1; }"); +check("({ * generatorMethod() { yield 1; } })"); +check("var func = function*() { yield 1; }"); diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/generator.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/generator.js.EXPECTED Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,9 @@ +java.lang.RuntimeException: test/script/basic/es6/generator.js#34:6:1:17 ES6 generator is not yet implemented +function* func() { yield 1; } + ^ +java.lang.RuntimeException: test/script/basic/es6/generator.js#34:6:1:23 ES6 generator is not yet implemented +({ * generatorMethod() { yield 1; } }) + ^ +java.lang.RuntimeException: test/script/basic/es6/generator.js#34:6:1:23 ES6 generator is not yet implemented +var func = function*() { yield 1; } + ^ diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/restparam.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/restparam.js Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,46 @@ +/* + * 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. + */ + +/** + * ES6 rest params are not implemented + * + * @test + * @run + * @option --language=es6 + */ + + +function check(code) { + try { + eval(code); + } catch (e) { + print(String(e).replace(/\\/g, "/")) + } +} + +check("function func(...args) {}"); +check("function func(x, y, ...args) {}"); +check("({ meth(...args) {} })"); +check("({ meth(x, y, ...args) {} })"); +check("({ meth(x = 0, x) {} })"); + diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/restparam.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/restparam.js.EXPECTED Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,15 @@ +java.lang.RuntimeException: test/script/basic/es6/restparam.js#35:6:1:17 ES6 function rest parameter declaration is not yet implemented +function func(...args) {} + ^ +java.lang.RuntimeException: test/script/basic/es6/restparam.js#35:6:1:23 ES6 function rest parameter declaration is not yet implemented +function func(x, y, ...args) {} + ^ +java.lang.RuntimeException: test/script/basic/es6/restparam.js#35:6:1:11 ES6 function rest parameter declaration is not yet implemented +({ meth(...args) {} }) + ^ +java.lang.RuntimeException: test/script/basic/es6/restparam.js#35:6:1:17 ES6 function rest parameter declaration is not yet implemented +({ meth(x, y, ...args) {} }) + ^ +SyntaxError: test/script/basic/es6/restparam.js#35:6:1:15 Duplicate parameter name "x" +({ meth(x = 0, x) {} }) + ^ diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/spread.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/spread.js Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,43 @@ +/* + * 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. + */ + +/** + * ES6 spread operator is not implemented + * + * @test + * @run + * @option --language=es6 + */ + +function check(code) { + try { + eval(code); + } catch (e) { + print(String(e).replace(/\\/g, "/")) + } +} + +check("var x = [...args]"); +check("var x = [1, 2, ...args]"); +check("var x = [...args, 3, 5]"); +check("var r = func(...arr)"); diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/spread.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/spread.js.EXPECTED Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,12 @@ +java.lang.RuntimeException: test/script/basic/es6/spread.js#34:8:1:9 ES6 spread operator is not yet implemented +var x = [...args] + ^ +java.lang.RuntimeException: test/script/basic/es6/spread.js#34:8:1:15 ES6 spread operator is not yet implemented +var x = [1, 2, ...args] + ^ +java.lang.RuntimeException: test/script/basic/es6/spread.js#34:8:1:9 ES6 spread operator is not yet implemented +var x = [...args, 3, 5] + ^ +java.lang.RuntimeException: test/script/basic/es6/spread.js#34:8:1:13 ES6 spread operator is not yet implemented +var r = func(...arr) + ^ diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/super.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/super.js Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,42 @@ +/* + * 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. + */ + +/** + * ES6 super keyword is not implemented + * + * @test + * @run + * @option --language=es6 + */ + +function check(code) { + try { + eval(code); + } catch (e) { + print(String(e).replace(/\\/g, "/")) + } +} + +check("({ meth() { x = super.x } })"); +check("({ meth() { x = super.x() } })"); +check("({ meth() { x = super['x'] } })"); diff -r a4ee110842fb -r 8750872276b8 nashorn/test/script/basic/es6/super.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/super.js.EXPECTED Wed Jul 05 22:25:59 2017 +0200 @@ -0,0 +1,9 @@ +java.lang.RuntimeException: test/script/basic/es6/super.js#34:8:1:10 ES6 super keyword is not yet implemented +({ meth() { x = super.x } }) + ^ +java.lang.RuntimeException: test/script/basic/es6/super.js#34:8:1:10 ES6 super keyword is not yet implemented +({ meth() { x = super.x() } }) + ^ +java.lang.RuntimeException: test/script/basic/es6/super.js#34:8:1:10 ES6 super keyword is not yet implemented +({ meth() { x = super['x'] } }) + ^ diff -r a4ee110842fb -r 8750872276b8 test/make/TestJavaCompilation.gmk --- a/test/make/TestJavaCompilation.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/test/make/TestJavaCompilation.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -202,9 +202,9 @@ DEPENDENCIES := $(OUTPUT_DIR)/_jar3_created, \ SRCS := $(JAR3_SRC_ROOT1) $(JAR3_SRC_ROOT2), \ EXTRA_FILES := extra-file \ - dir2/file$$$$foo.dollar \ + dir2/file$$foo.dollar \ $(JAR3_SRC_ROOT2)/extra-file-abs, \ - EXCLUDE_FILES := dir1/file1$$$$foo.class, \ + EXCLUDE_FILES := dir1/file1$$foo.class, \ JAR := $(JAR3_FILE), \ )) diff -r a4ee110842fb -r 8750872276b8 test/make/TestMakeBase.gmk --- a/test/make/TestMakeBase.gmk Mon Nov 07 16:08:18 2016 +0000 +++ b/test/make/TestMakeBase.gmk Wed Jul 05 22:25:59 2017 +0200 @@ -209,9 +209,9 @@ test ! -e $(VARDEP_FLAG_FILE) # # Test including some problematic characters - $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR='value4 \$$$$ORIGIN' $(VARDEP_TARGET_FILE) + $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR='value4 \$$ORIGIN' $(VARDEP_TARGET_FILE) $(RM) $(VARDEP_FLAG_FILE) - $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR='value4 \$$$$ORIGIN' $(VARDEP_TARGET_FILE) + $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR='value4 \$$ORIGIN' $(VARDEP_TARGET_FILE) test ! -e $(VARDEP_FLAG_FILE) # Test specifying a specific value file to store variable in