diff --git a/.hgtags b/.hgtags index 5618d206183..74caecd3098 100644 --- a/.hgtags +++ b/.hgtags @@ -361,3 +361,5 @@ c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114 84aba7335005a3a47751dcf1f37935f97df9f99a jdk-9+116 82b8d12a553f5617737c238cec060281d52e351c jdk-9+117 7c04fcb12bd4a31570a238e663fa846dfa5ec3b8 jdk-9+118 +caf97b37ebec84288c112d21d3a60cb628cba1e8 jdk-9+119 +9330543436402b8f3bd070524846a464d8143557 jdk-9+120 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 08fd371176c..cdd21c19b18 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -361,3 +361,5 @@ f900d5afd9c83a0df8f36161c27c5e4c86a66f4c jdk-9+111 6743a8e0cab7b5f6f4a0575f6664892f0ab740af jdk-9+116 e882bcdbdac436523f3d5681611d3118a3804ea7 jdk-9+117 047f95de8f918d8ff5e8cd2636a2abb5c3c8adb8 jdk-9+118 +3463a3f14f0f0e8a68f29ac6405454f2fa2f598a jdk-9+119 +647e0142a5a52749db572b5e6638d561def6479e jdk-9+120 diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index f295a46d3c4..6a64c47b964 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -484,6 +484,8 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], BASIC_REQUIRE_PROGS(FILE, file) BASIC_REQUIRE_PROGS(FIND, find) BASIC_REQUIRE_PROGS(HEAD, head) + BASIC_REQUIRE_PROGS(GUNZIP, gunzip) + BASIC_REQUIRE_PROGS(GZIP, pigz gzip) BASIC_REQUIRE_PROGS(LN, ln) BASIC_REQUIRE_PROGS(LS, ls) BASIC_REQUIRE_PROGS(MKDIR, mkdir) @@ -496,7 +498,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], BASIC_REQUIRE_PROGS(SH, sh) BASIC_REQUIRE_PROGS(SORT, sort) BASIC_REQUIRE_PROGS(TAIL, tail) - BASIC_REQUIRE_PROGS(TAR, tar) + BASIC_REQUIRE_PROGS(TAR, gtar tar) BASIC_REQUIRE_PROGS(TEE, tee) BASIC_REQUIRE_PROGS(TOUCH, touch) BASIC_REQUIRE_PROGS(TR, tr) @@ -839,8 +841,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], # The spec.gmk file contains all variables for the make system. AC_CONFIG_FILES([$OUTPUT_ROOT/spec.gmk:$AUTOCONF_DIR/spec.gmk.in]) - # The hotspot-spec.gmk file contains legacy variables for the hotspot make system. - AC_CONFIG_FILES([$OUTPUT_ROOT/hotspot-spec.gmk:$AUTOCONF_DIR/hotspot-spec.gmk.in]) # The bootcycle-spec.gmk file contains support for boot cycle builds. AC_CONFIG_FILES([$OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in]) # The buildjdk-spec.gmk file contains support for building a buildjdk when cross compiling. @@ -1009,11 +1009,36 @@ AC_DEFUN([BASIC_CHECK_FIND_DELETE], AC_SUBST(FIND_DELETE) ]) +AC_DEFUN([BASIC_CHECK_TAR], +[ + # Test which kind of tar was found + if test "x$($TAR --version | $GREP "GNU tar")" != "x"; then + TAR_TYPE="gnu" + elif test "x$($TAR -v | $GREP "bsdtar")" != "x"; then + TAR_TYPE="bsd" + elif test "x$OPENJDK_BUILD_OS" = "xsolaris"; then + TAR_TYPE="solaris" + fi + AC_MSG_CHECKING([what type of tar was found]) + AC_MSG_RESULT([$TAR_TYPE]) + + if test "x$TAR_TYPE" = "xgnu"; then + TAR_INCLUDE_PARAM="T" + TAR_SUPPORTS_TRANSFORM="true" + else + TAR_INCLUDE_PARAM="I" + TAR_SUPPORTS_TRANSFORM="false" + fi + AC_SUBST(TAR_INCLUDE_PARAM) + AC_SUBST(TAR_SUPPORTS_TRANSFORM) +]) + AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], [ BASIC_CHECK_GNU_MAKE BASIC_CHECK_FIND_DELETE + BASIC_CHECK_TAR # These tools might not be installed by default, # need hint on how to install them. diff --git a/common/autoconf/buildjdk-spec.gmk.in b/common/autoconf/buildjdk-spec.gmk.in index 818f21eed95..c4b7d9051cc 100644 --- a/common/autoconf/buildjdk-spec.gmk.in +++ b/common/autoconf/buildjdk-spec.gmk.in @@ -134,8 +134,9 @@ ifeq ($(JVM_INTERPRETER), cpp) endif HOTSPOT_MAKE_ARGS := product docs export_product -# Control wether Hotspot runs Queens test after building -TEST_IN_BUILD := false + +# Control wether Hotspot builds gtest tests +BUILD_GTEST := false USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@ diff --git a/common/autoconf/compare.sh.in b/common/autoconf/compare.sh.in index 67a69ff73bd..f7e2003ca32 100644 --- a/common/autoconf/compare.sh.in +++ b/common/autoconf/compare.sh.in @@ -48,6 +48,7 @@ export EXPR="@EXPR@" export FILE="@FILE@" export FIND="@FIND@" export GREP="@GREP@" +export GUNZIP="@GUNZIP@" export LDD="@LDD@" export LN="@LN@" export MKDIR="@MKDIR@" @@ -63,10 +64,11 @@ export SED="@SED@" export SORT="@SORT@" export STAT="@STAT@" export STRIP="@STRIP@ @STRIPFLAGS@" +export TAR="@TAR@" export TEE="@TEE@" export UNIQ="@UNIQ@" export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200" -export UNARCHIVE="@UNZIP@ -q" +export UNARCHIVE="@UNZIP@ -q -o" export SRC_ROOT="@TOPDIR@" export OUTPUT_ROOT="@OUTPUT_ROOT@" diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 291851f8d10..bb5491ba0b4 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -207,6 +207,7 @@ JDKOPT_SETUP_CODE_COVERAGE # Need toolchain to setup dtrace HOTSPOT_SETUP_DTRACE HOTSPOT_SETUP_JVM_FEATURES +HOTSPOT_ENABLE_DISABLE_GTEST ############################################################################### # @@ -226,9 +227,9 @@ LIB_SETUP_LIBRARIES # ############################################################################### -HOTSPOT_SETUP_LEGACY_BUILD JDKOPT_DETECT_INTREE_EC JDKOPT_ENABLE_DISABLE_FAILURE_HANDLER +JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST ############################################################################### # diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index f40198f8da3..e4c2dab06f9 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -650,23 +650,10 @@ TEST_JOBS JOBS MEMORY_SIZE NUM_CORES +ENABLE_GENERATE_CLASSLIST BUILD_FAILURE_HANDLER ENABLE_INTREE_EC -JVM_VARIANT_CORE -JVM_VARIANT_ZEROSHARK -JVM_VARIANT_ZERO -JVM_VARIANT_HOTSPOT -JVM_VARIANT_MINIMAL1 -JVM_VARIANT_CLIENT -JVM_VARIANT_SERVER -JVM_VARIANTS_COMMA -TEST_IN_BUILD -HOTSPOT_MAKE_ARGS -MACOSX_UNIVERSAL -DEBUG_CLASSFILES -FASTDEBUG -VARIANT -USE_NEW_HOTSPOT_BUILD +STLPORT_LIB LIBZIP_CAN_USE_MMAP LIBDL LIBM @@ -702,6 +689,7 @@ LIBCXX STATIC_CXX_SETTING FIXPATH_DETACH_FLAG FIXPATH +BUILD_GTEST VALID_JVM_FEATURES JVM_FEATURES_custom JVM_FEATURES_zeroshark @@ -963,6 +951,8 @@ OTOOL LDD ZIP UNZIP +TAR_SUPPORTS_TRANSFORM +TAR_INCLUDE_PARAM FIND_DELETE OUTPUT_SYNC OUTPUT_SYNC_SUPPORTED @@ -995,6 +985,9 @@ HOTSPOT_BUILD_CPU_ARCH HOTSPOT_BUILD_CPU HOTSPOT_BUILD_OS_TYPE HOTSPOT_BUILD_OS +OPENJDK_BUILD_BUNDLE_PLATFORM +OPENJDK_BUILD_CPU_BUNDLE +OPENJDK_BUILD_OS_BUNDLE OPENJDK_BUILD_OS_EXPORT_DIR OPENJDK_BUILD_CPU_JLI_CFLAGS OPENJDK_BUILD_CPU_OSARCH @@ -1009,6 +1002,9 @@ HOTSPOT_TARGET_OS_TYPE HOTSPOT_TARGET_OS DEFINE_CROSS_COMPILE_ARCH LP64 +OPENJDK_TARGET_BUNDLE_PLATFORM +OPENJDK_TARGET_CPU_BUNDLE +OPENJDK_TARGET_OS_BUNDLE OPENJDK_TARGET_OS_EXPORT_DIR OPENJDK_TARGET_CPU_JLI_CFLAGS OPENJDK_TARGET_CPU_OSARCH @@ -1078,6 +1074,8 @@ MKTEMP MKDIR LS LN +GZIP +GUNZIP HEAD FIND FILE @@ -1202,6 +1200,7 @@ enable_native_coverage enable_dtrace with_jvm_features with_jvm_interpreter +enable_hotspot_gtest with_stdc__lib with_msvcr_dll with_msvcp_dll @@ -1227,9 +1226,8 @@ with_lcms with_dxsdk with_dxsdk_lib with_dxsdk_include -enable_new_hotspot_build -enable_hotspot_test_in_build enable_jtreg_failure_handler +enable_generate_classlist with_num_cores with_memory_size with_jobs @@ -1262,6 +1260,8 @@ EXPR FILE FIND HEAD +GUNZIP +GZIP LN LS MKDIR @@ -1996,21 +1996,21 @@ Optional Features: --enable-dtrace[=yes/no/auto] enable dtrace. Default is auto, where dtrace is enabled if all dependencies are present. + --disable-hotspot-gtest Disables building of the Hotspot unit tests --disable-freetype-bundling disable bundling of the freetype library with the build result [enabled on Windows or when using --with-freetype, disabled otherwise] - --disable-new-hotspot-build - disable the new hotspot build system (use the old) - [enabled] - --enable-hotspot-test-in-build - run the Queens test after Hotspot build [disabled] --enable-jtreg-failure-handler forces build of the jtreg failure handler to be enabled, missing dependencies become fatal errors. Default is auto, where the failure handler is built if all dependencies are present and otherwise just disabled. + --disable-generate-classlist + forces enabling or disabling of the generation of a + CDS classlist at build time. Default is to generate + it when either the server or client JVMs are built. --enable-sjavac use sjavac to do fast incremental compiles [disabled] --disable-javac-server disable javac server [enabled] @@ -2205,6 +2205,8 @@ Some influential environment variables: FILE Override default value for FILE FIND Override default value for FIND HEAD Override default value for HEAD + GUNZIP Override default value for GUNZIP + GZIP Override default value for GZIP LN Override default value for LN LS Override default value for LS MKDIR Override default value for MKDIR @@ -3707,6 +3709,8 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + # Check if build directory is on local disk. If not possible to determine, # we prefer to claim it's local. # Argument 1: directory to test @@ -4303,9 +4307,8 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # -############################################################################### -# Support for old hotspot build. Remove once new hotspot build has proven -# to work satisfactory. +################################################################################ +# Check if gtest should be built # @@ -4394,6 +4397,12 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # +################################################################################ +# +# Enable or disable generation of the classlist at build time +# + + # # Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -4732,6 +4741,13 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" ################################################################################ +################################################################################ +# libstlport.so.1 is needed for running gtest on Solaris. Find it to +# redistribute it in the test image. +################################################################################ + + + # # Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -5076,7 +5092,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1462970869 +DATE_WHEN_GENERATED=1464173584 ############################################################################### # @@ -8401,6 +8417,414 @@ $as_echo "$tool_specified" >&6; } + # Publish this variable in the help. + + + if [ -z "${GUNZIP+x}" ]; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in gunzip +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GUNZIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GUNZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GUNZIP="$GUNZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GUNZIP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GUNZIP=$ac_cv_path_GUNZIP +if test -n "$GUNZIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GUNZIP" >&5 +$as_echo "$GUNZIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$GUNZIP" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !GUNZIP! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!GUNZIP!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xGUNZIP" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of GUNZIP from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of GUNZIP from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in gunzip +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GUNZIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GUNZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GUNZIP="$GUNZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GUNZIP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GUNZIP=$ac_cv_path_GUNZIP +if test -n "$GUNZIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GUNZIP" >&5 +$as_echo "$GUNZIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$GUNZIP" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if we try to supply an empty value + if test "x$GUNZIP" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool GUNZIP= (no value)" >&5 +$as_echo "$as_me: Setting user supplied tool GUNZIP= (no value)" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GUNZIP" >&5 +$as_echo_n "checking for GUNZIP... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } + else + # Check if the provided tool contains a complete path. + tool_specified="$GUNZIP" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool GUNZIP=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool GUNZIP=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GUNZIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GUNZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GUNZIP="$GUNZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GUNZIP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GUNZIP=$ac_cv_path_GUNZIP +if test -n "$GUNZIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GUNZIP" >&5 +$as_echo "$GUNZIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$GUNZIP" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool GUNZIP=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool GUNZIP=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GUNZIP" >&5 +$as_echo_n "checking for GUNZIP... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool GUNZIP=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + fi + + + + if test "x$GUNZIP" = x; then + as_fn_error $? "Could not find required tool for GUNZIP" "$LINENO" 5 + fi + + + + + + # Publish this variable in the help. + + + if [ -z "${GZIP+x}" ]; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in pigz gzip +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GZIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GZIP="$GZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GZIP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GZIP=$ac_cv_path_GZIP +if test -n "$GZIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GZIP" >&5 +$as_echo "$GZIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$GZIP" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !GZIP! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!GZIP!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xGZIP" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of GZIP from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of GZIP from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in pigz gzip +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GZIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GZIP="$GZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GZIP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GZIP=$ac_cv_path_GZIP +if test -n "$GZIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GZIP" >&5 +$as_echo "$GZIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$GZIP" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if we try to supply an empty value + if test "x$GZIP" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool GZIP= (no value)" >&5 +$as_echo "$as_me: Setting user supplied tool GZIP= (no value)" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GZIP" >&5 +$as_echo_n "checking for GZIP... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } + else + # Check if the provided tool contains a complete path. + tool_specified="$GZIP" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool GZIP=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool GZIP=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GZIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GZIP="$GZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GZIP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GZIP=$ac_cv_path_GZIP +if test -n "$GZIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GZIP" >&5 +$as_echo "$GZIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$GZIP" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool GZIP=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool GZIP=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GZIP" >&5 +$as_echo_n "checking for GZIP... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool GZIP=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + fi + + + + if test "x$GZIP" = x; then + as_fn_error $? "Could not find required tool for GZIP" "$LINENO" 5 + fi + + + + + # Publish this variable in the help. @@ -10854,7 +11278,7 @@ $as_echo "$tool_specified" >&6; } if [ -z "${TAR+x}" ]; then # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in tar + for ac_prog in gtar tar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -10912,7 +11336,7 @@ done $as_echo "$as_me: WARNING: Ignoring value of TAR from the environment. Use command line variables instead." >&2;} fi # Try to locate tool using the code snippet - for ac_prog in tar + for ac_prog in gtar tar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -15428,6 +15852,23 @@ $as_echo "$COMPILE_TYPE" >&6; } fi + # The new version string in JDK 9 also defined new naming of OS and ARCH for bundles + # Macosx is osx and x86_64 is x64 + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + OPENJDK_TARGET_OS_BUNDLE="osx" + else + OPENJDK_TARGET_OS_BUNDLE="$OPENJDK_TARGET_OS" + fi + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_TARGET_CPU_BUNDLE="x64" + else + OPENJDK_TARGET_CPU_BUNDLE="$OPENJDK_TARGET_CPU" + fi + OPENJDK_TARGET_BUNDLE_PLATFORM="${OPENJDK_TARGET_OS_BUNDLE}-${OPENJDK_TARGET_CPU_BUNDLE}" + + + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in @@ -15584,6 +16025,23 @@ $as_echo "$COMPILE_TYPE" >&6; } fi + # The new version string in JDK 9 also defined new naming of OS and ARCH for bundles + # Macosx is osx and x86_64 is x64 + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_OS_BUNDLE="osx" + else + OPENJDK_BUILD_OS_BUNDLE="$OPENJDK_TARGET_OS" + fi + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_CPU_BUNDLE="x64" + else + OPENJDK_BUILD_CPU_BUNDLE="$OPENJDK_BUILD_CPU" + fi + OPENJDK_BUILD_BUNDLE_PLATFORM="${OPENJDK_BUILD_OS_BUNDLE}-${OPENJDK_BUILD_CPU_BUNDLE}" + + + + if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in @@ -16297,7 +16755,10 @@ $as_echo "$JVM_VARIANTS" >&6; } # Check that the selected variants are valid # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 - INVALID_VARIANTS=`$GREP -Fvx "${VALID_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + # Notice that the original variant failes on SLES 10 and 11 + NEEDLE=${VALID_JVM_VARIANTS// /$'\n'} + STACK=${JVM_VARIANTS// /$'\n'} + INVALID_VARIANTS=`$GREP -Fvx "${NEEDLE}" <<< "${STACK}"` if test "x$INVALID_VARIANTS" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: Unknown variant(s) specified: $INVALID_VARIANTS" >&5 $as_echo "$as_me: Unknown variant(s) specified: $INVALID_VARIANTS" >&6;} @@ -16306,7 +16767,9 @@ $as_echo "$as_me: Unknown variant(s) specified: $INVALID_VARIANTS" >&6;} # All "special" variants share the same output directory ("server") VALID_MULTIPLE_JVM_VARIANTS="server client minimal" - INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + NEEDLE=${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'} + STACK=${JVM_VARIANTS// /$'\n'} + INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${NEEDLE}" <<< "${STACK}"` if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then as_fn_error $? "You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS." "$LINENO" 5 fi @@ -17016,9 +17479,6 @@ $as_echo "$as_me: The path of OUTPUT_ROOT, which resolves as \"$path\", is inval # The spec.gmk file contains all variables for the make system. ac_config_files="$ac_config_files $OUTPUT_ROOT/spec.gmk:$AUTOCONF_DIR/spec.gmk.in" - # The hotspot-spec.gmk file contains legacy variables for the hotspot make system. - ac_config_files="$ac_config_files $OUTPUT_ROOT/hotspot-spec.gmk:$AUTOCONF_DIR/hotspot-spec.gmk.in" - # The bootcycle-spec.gmk file contains support for boot cycle builds. ac_config_files="$ac_config_files $OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in" @@ -20699,6 +21159,30 @@ $as_echo "yes" >&6; } + # Test which kind of tar was found + if test "x$($TAR --version | $GREP "GNU tar")" != "x"; then + TAR_TYPE="gnu" + elif test "x$($TAR -v | $GREP "bsdtar")" != "x"; then + TAR_TYPE="bsd" + elif test "x$OPENJDK_BUILD_OS" = "xsolaris"; then + TAR_TYPE="solaris" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking what type of tar was found" >&5 +$as_echo_n "checking what type of tar was found... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TAR_TYPE" >&5 +$as_echo "$TAR_TYPE" >&6; } + + if test "x$TAR_TYPE" = "xgnu"; then + TAR_INCLUDE_PARAM="T" + TAR_SUPPORTS_TRANSFORM="true" + else + TAR_INCLUDE_PARAM="I" + TAR_SUPPORTS_TRANSFORM="false" + fi + + + + # These tools might not be installed by default, # need hint on how to install them. @@ -23790,9 +24274,6 @@ fi if test "x$OPENJDK_TARGET_OS" = xaix ; then INCLUDE_SA=false fi - if test "x$OPENJDK_TARGET_CPU" = xaarch64; then - INCLUDE_SA=false - fi # Compress jars @@ -52948,6 +53429,49 @@ fi + # Check whether --enable-hotspot-gtest was given. +if test "${enable_hotspot_gtest+set}" = set; then : + enableval=$enable_hotspot_gtest; +fi + + + if test -e "$HOTSPOT_TOPDIR/test/native"; then + GTEST_DIR_EXISTS="true" + else + GTEST_DIR_EXISTS="false" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Hotspot gtest unit tests should be built" >&5 +$as_echo_n "checking if Hotspot gtest unit tests should be built... " >&6; } + if test "x$enable_hotspot_gtest" = "xyes"; then + if test "x$GTEST_DIR_EXISTS" = "xtrue"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5 +$as_echo "yes, forced" >&6; } + BUILD_GTEST="true" + else + as_fn_error $? "Cannot build gtest without the test source" "$LINENO" 5 + fi + elif test "x$enable_hotspot_gtest" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5 +$as_echo "no, forced" >&6; } + BUILD_GTEST="false" + elif test "x$enable_hotspot_gtest" = "x"; then + if test "x$GTEST_DIR_EXISTS" = "xtrue"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + BUILD_GTEST="true" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + BUILD_GTEST="false" + fi + else + as_fn_error $? "--enable-gtest must be either yes or no" "$LINENO" 5 + fi + + + + ############################################################################### # # Check dependencies for external and internal libraries. @@ -64076,6 +64600,157 @@ fi + if test "$OPENJDK_TARGET_OS" = "solaris"; then + # Find the root of the Solaris Studio installation from the compiler path + SOLARIS_STUDIO_DIR="$(dirname $CC)/.." + STLPORT_LIB="$SOLARIS_STUDIO_DIR/lib/stlport4$OPENJDK_TARGET_CPU_ISADIR/libstlport.so.1" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libstlport.so.1" >&5 +$as_echo_n "checking for libstlport.so.1... " >&6; } + if test -f "$STLPORT_LIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, $STLPORT_LIB" >&5 +$as_echo "yes, $STLPORT_LIB" >&6; } + + # Only process if variable expands to non-empty + + if test "x$STLPORT_LIB" != x; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # Input might be given as Windows format, start by converting to + # unix format. + path="$STLPORT_LIB" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STLPORT_LIB, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of STLPORT_LIB, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of STLPORT_LIB" "$LINENO" 5 + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-style (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + + if test "x$path" != "x$new_path"; then + STLPORT_LIB="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STLPORT_LIB to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting STLPORT_LIB to \"$new_path\"" >&6;} + fi + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + path="$STLPORT_LIB" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi + + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + if test "x$path" != "x$new_path"; then + STLPORT_LIB="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STLPORT_LIB to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting STLPORT_LIB to \"$new_path\"" >&6;} + fi + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + + else + # We're on a unix platform. Hooray! :) + path="$STLPORT_LIB" + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STLPORT_LIB, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of STLPORT_LIB, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + + # Use eval to expand a potential ~ + eval path="$path" + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of STLPORT_LIB, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + if test -d "$path"; then + STLPORT_LIB="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + STLPORT_LIB="`cd "$dir"; $THEPWDCMD -L`/$base" + fi + fi + fi + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, not found at $STLPORT_LIB" >&5 +$as_echo "no, not found at $STLPORT_LIB" >&6; } + as_fn_error $? "Failed to find libstlport.so.1, cannot build Hotspot gtests" "$LINENO" 5 + fi + + fi + + + @@ -64094,144 +64769,6 @@ fi ############################################################################### - # Check whether --enable-new-hotspot-build was given. -if test "${enable_new_hotspot_build+set}" = set; then : - enableval=$enable_new_hotspot_build; -fi - - - if test "x$enable_new_hotspot_build" = "x" || test "x$enable_new_hotspot_build" = "xyes"; then - USE_NEW_HOTSPOT_BUILD=true - else - USE_NEW_HOTSPOT_BUILD=false - fi - - - case $HOTSPOT_DEBUG_LEVEL in - product ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - ;; - fastdebug ) - VARIANT="DBG" - FASTDEBUG="true" - DEBUG_CLASSFILES="true" - ;; - debug ) - VARIANT="DBG" - FASTDEBUG="false" - DEBUG_CLASSFILES="true" - ;; - optimized ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - ;; - esac - - - - - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - MACOSX_UNIVERSAL="true" - fi - - - - # Make sure JVM_VARIANTS_COMMA use minimal1 for backwards compatibility - JVM_VARIANTS_COMMA=`$ECHO ,$JVM_VARIANTS_OPT, | $SED -e 's/,minimal,/,minimal1,/'` - - JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` - JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` - JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,minimal1\?,/!s/.*/false/g' -e '/,minimal1\?,/s/.*/true/g'` - JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` - JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` - JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` - JVM_VARIANT_CUSTOM=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,custom,/!s/.*/false/g' -e '/,custom,/s/.*/true/g'` - - ##### - # Generate the legacy makefile targets for hotspot. - HOTSPOT_TARGET="" - - if test "x$JVM_VARIANT_SERVER" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} " - fi - - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 " - fi - - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 " - fi - - if test "x$JVM_VARIANT_ZERO" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero " - fi - - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark " - fi - - if test "x$JVM_VARIANT_CORE" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " - fi - - HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_DEBUG_LEVEL" - - # On Macosx universal binaries are produced, but they only contain - # 64 bit intel. This invalidates control of which jvms are built - # from configure, but only server is valid anyway. Fix this - # when hotspot makefiles are rewritten. - if test "x$MACOSX_UNIVERSAL" = xtrue; then - HOTSPOT_TARGET=universal_${HOTSPOT_DEBUG_LEVEL} - fi - - HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" - - - # Control wether Hotspot runs Queens test after build. - # Check whether --enable-hotspot-test-in-build was given. -if test "${enable_hotspot_test_in_build+set}" = set; then : - enableval=$enable_hotspot_test_in_build; -else - enable_hotspot_test_in_build=no -fi - - if test "x$enable_hotspot_test_in_build" = "xyes"; then - TEST_IN_BUILD=true - else - TEST_IN_BUILD=false - fi - - - if test "x$USE_NEW_HOTSPOT_BUILD" = xfalse; then - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - as_fn_error $? "You cannot build a client JVM for a 64-bit machine." "$LINENO" 5 - fi - fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - as_fn_error $? "You cannot build a minimal JVM for a 64-bit machine." "$LINENO" 5 - fi - fi - if test "x$JVM_VARIANT_CUSTOM" = xtrue; then - as_fn_error $? "You cannot build a custom JVM using the old hotspot build system." "$LINENO" 5 - fi - fi - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if elliptic curve crypto implementation is present" >&5 $as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; } @@ -64287,6 +64824,51 @@ $as_echo "yes, jtreg present" >&6; } + # Check whether --enable-generate-classlist was given. +if test "${enable_generate_classlist+set}" = set; then : + enableval=$enable_generate_classlist; +fi + + + # Check if it's likely that it's possible to generate the classlist. Depending + # on exact jvm configuration it could be possible anyway. + if [[ " $JVM_VARIANTS " =~ " server " ]] || [[ " $JVM_VARIANTS " =~ " client " ]] ; then + ENABLE_GENERATE_CLASSLIST_POSSIBLE="true" + else + ENABLE_GENERATE_CLASSLIST_POSSIBLE="false" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the CDS classlist generation should be enabled" >&5 +$as_echo_n "checking if the CDS classlist generation should be enabled... " >&6; } + if test "x$enable_generate_classlist" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5 +$as_echo "yes, forced" >&6; } + ENABLE_GENERATE_CLASSLIST="true" + if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS" >&5 +$as_echo "$as_me: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS" >&2;} + fi + elif test "x$enable_generate_classlist" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5 +$as_echo "no, forced" >&6; } + ENABLE_GENERATE_CLASSLIST="false" + elif test "x$enable_generate_classlist" = "x"; then + if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xtrue"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ENABLE_GENERATE_CLASSLIST="true" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ENABLE_GENERATE_CLASSLIST="false" + fi + else + as_fn_error $? "Invalid value for --enable-generate-classlist: $enable_generate_classlist" "$LINENO" 5 + fi + + + + ############################################################################### # # Configure parts of the build that only affect the build performance, @@ -65977,7 +66559,9 @@ $as_echo_n "checking JVM features for JVM variant '$variant'... " >&6; } JVM_FEATURES_TO_TEST=${!features_var_name} { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_FEATURES_TO_TEST" >&5 $as_echo "$JVM_FEATURES_TO_TEST" >&6; } - INVALID_FEATURES=`$GREP -Fvx "${VALID_JVM_FEATURES// /$'\n'}" <<< "${JVM_FEATURES_TO_TEST// /$'\n'}"` + NEEDLE=${VALID_JVM_FEATURES// /$'\n'} + STACK=${JVM_FEATURES_TO_TEST// /$'\n'} + INVALID_FEATURES=`$GREP -Fvx "${NEEDLE}" <<< "${STACK}"` if test "x$INVALID_FEATURES" != x; then as_fn_error $? "Invalid JVM feature(s): $INVALID_FEATURES" "$LINENO" 5 fi @@ -66697,7 +67281,6 @@ for ac_config_target in $ac_config_targets do case $ac_config_target in "$OUTPUT_ROOT/spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/spec.gmk:$AUTOCONF_DIR/spec.gmk.in" ;; - "$OUTPUT_ROOT/hotspot-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/hotspot-spec.gmk:$AUTOCONF_DIR/hotspot-spec.gmk.in" ;; "$OUTPUT_ROOT/bootcycle-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in" ;; "$OUTPUT_ROOT/buildjdk-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in" ;; "$OUTPUT_ROOT/compare.sh") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in" ;; diff --git a/common/autoconf/hotspot-spec.gmk.in b/common/autoconf/hotspot-spec.gmk.in deleted file mode 100644 index 50d790876a6..00000000000 --- a/common/autoconf/hotspot-spec.gmk.in +++ /dev/null @@ -1,158 +0,0 @@ -# -# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute 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. -# - - -# Chaining of spec files -HOTSPOT_SPEC:=$(dir $(SPEC))hotspot-spec.gmk -override SPEC=$(HOTSPOT_SPEC) -# Now include the base spec.gmk file -include $(BASE_SPEC) - -# Additional legacy variables defined for Hotspot - -@SET_OPENJDK@ -@HOTSPOT_SET_WARNINGS_AS_ERRORS@ - -# Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options. -@BUILD_HEADLESS@ - -JVM_VARIANTS:=@JVM_VARIANTS_COMMA@ - -JVM_VARIANT_SERVER:=@JVM_VARIANT_SERVER@ -JVM_VARIANT_CLIENT:=@JVM_VARIANT_CLIENT@ -JVM_VARIANT_MINIMAL1:=@JVM_VARIANT_MINIMAL1@ -JVM_VARIANT_CORE:=@JVM_VARIANT_CORE@ -JVM_VARIANT_ZERO:=@JVM_VARIANT_ZERO@ -JVM_VARIANT_ZEROSHARK:=@JVM_VARIANT_ZEROSHARK@ -JVM_VARIANT_CUSTOM:=@JVM_VARIANT_HOTSPOT@ - -# Legacy setting: OPT or DBG -VARIANT:=@VARIANT@ -# Legacy setting: true or false -FASTDEBUG:=@FASTDEBUG@ -# Legacy setting: debugging the class files? -DEBUG_CLASSFILES:=@DEBUG_CLASSFILES@ - -ALT_CUPS_HEADERS_PATH:=$(patsubst -I%,%,$(filter -I%,@CUPS_CFLAGS@)) - -# The HOSTCC/HOSTCXX is Hotspot terminology for the BUILD_CC/BUILD_CXX, i.e. the -# compiler that produces code that can be run on the build platform. -HOSTCC:=@FIXPATH@ @BUILD_ICECC@ @BUILD_CC@ $(BUILD_SYSROOT_CFLAGS) -HOSTCXX:=@FIXPATH@ @BUILD_ICECC@ @BUILD_CXX@ $(BUILD_SYSROOT_CFLAGS) - -#################################################### -# -# Legacy Hotspot support - -# If cross compiling, then define CROSS_COMPILE_ARCH:=cpu_name here. -@DEFINE_CROSS_COMPILE_ARCH@ - -# Old name for OPENJDK_TARGET_OS (aix,bsd,hpux,linux,macosx,solaris,windows etc) -PLATFORM=$(OPENJDK_TARGET_OS) -# 32 or 64 bit -ARCH_DATA_MODEL=$(OPENJDK_TARGET_CPU_BITS) - -ALT_BOOTDIR=$(BOOT_JDK) -# Can be /sparcv9 or /amd64 on Solaris -ISA_DIR=$(OPENJDK_TARGET_CPU_ISADIR) -# Yet another name for arch used for an extra subdir below the jvm lib. -# Uses i386 and amd64, instead of x86 and x86_64. -LIBARCH=$(OPENJDK_TARGET_CPU_LEGACY_LIB) -# Set the cpu architecture -ARCH=$(OPENJDK_TARGET_CPU_ARCH) -# Legacy setting for building for a 64 bit machine. -# If yes then this expands to _LP64:=1 -@LP64@ - -# Legacy settings for zero -ZERO_ENDIANNESS=$(OPENJDK_TARGET_CPU_ENDIAN) -ZERO_LIBARCH=$(OPENJDK_TARGET_CPU_LEGACY_LIB) -ZERO_ARCHDEF=@ZERO_ARCHDEF@ -ZERO_ARCHFLAG=@ZERO_ARCHFLAG@ -LIBFFI_CFLAGS=@LIBFFI_CFLAGS@ -LIBFFI_LIBS=@LIBFFI_LIBS@ - -# Legacy settings for zeroshark -LLVM_CFLAGS=@LLVM_CFLAGS@ -LLVM_LIBS=@LLVM_LIBS@ -LLVM_LDFLAGS=@LLVM_LDFLAGS@ - -ALT_OUTPUTDIR=$(HOTSPOT_OUTPUTDIR) -ALT_EXPORT_PATH=$(HOTSPOT_DIST) - -ifeq ($(HOTSPOT_TARGET_CPU), zero) - CC_INTERP=true -endif - -HOTSPOT_MAKE_ARGS:=@HOTSPOT_MAKE_ARGS@ @STATIC_CXX_SETTING@ -# Control wether Hotspot runs Queens test after building -TEST_IN_BUILD=@TEST_IN_BUILD@ - -USE_CLANG := @USE_CLANG@ - -# For hotspot, override compiler/tools definition to not include FIXPATH prefix. -# Hotspot has its own handling on the Windows path situation. -CXX:=@CCACHE@ @ICECC@ @HOTSPOT_CXX@ -LD:=@HOTSPOT_LD@ -MT:=@HOTSPOT_MT@ -RC:=@HOTSPOT_RC@ - -EXTRA_CFLAGS=@LEGACY_EXTRA_CFLAGS@ $(CFLAGS_CCACHE) $(NO_NULL_POINTER_CHECK_FLAG) \ - $(NO_LIFETIME_DSE_CFLAG) $(CXXSTD_CXXFLAG) -EXTRA_CXXFLAGS=@LEGACY_EXTRA_CXXFLAGS@ $(CFLAGS_CCACHE) -EXTRA_LDFLAGS=@LEGACY_EXTRA_LDFLAGS@ - -USE_PRECOMPILED_HEADER=@USE_PRECOMPILED_HEADER@ - -# Hotspot expects the variable FULL_DEBUG_SYMBOLS=1/0 to control debug symbols -# creation. -ifeq ($(COPY_DEBUG_SYMBOLS), true) - FULL_DEBUG_SYMBOLS=1 - # Ensure hotspot uses the objcopy that configure located - ALT_OBJCOPY:=$(OBJCOPY) -else - FULL_DEBUG_SYMBOLS=0 -endif - -# Hotspot expects the variable ZIP_DEBUGINFO_FILES=1/0 and not true/false. -ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true) - ZIP_DEBUGINFO_FILES:=1 -else - ZIP_DEBUGINFO_FILES:=0 -endif - -DEBUG_BINARIES := @DEBUG_BINARIES@ -STRIP_POLICY := @STRIP_POLICY@ - -ifeq ($(OPENJDK_TARGET_OS), windows) - # On Windows, the Visual Studio toolchain needs the LIB and INCLUDE - # environment variables (in Windows path style). - export INCLUDE:=@VS_INCLUDE@ - export LIB:=@VS_LIB@ -endif - -# Sneak this in via the spec.gmk file, since we don't want to mess around too much with the Hotspot make files. -# This is needed to get the LOG setting to work properly. -include $(SRC_ROOT)/make/common/MakeBase.gmk diff --git a/common/autoconf/hotspot.m4 b/common/autoconf/hotspot.m4 index 4fffa86983d..18b6ec0aa21 100644 --- a/common/autoconf/hotspot.m4 +++ b/common/autoconf/hotspot.m4 @@ -93,7 +93,10 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], # Check that the selected variants are valid # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 - INVALID_VARIANTS=`$GREP -Fvx "${VALID_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + # Notice that the original variant failes on SLES 10 and 11 + NEEDLE=${VALID_JVM_VARIANTS// /$'\n'} + STACK=${JVM_VARIANTS// /$'\n'} + INVALID_VARIANTS=`$GREP -Fvx "${NEEDLE}" <<< "${STACK}"` if test "x$INVALID_VARIANTS" != x; then AC_MSG_NOTICE([Unknown variant(s) specified: $INVALID_VARIANTS]) AC_MSG_ERROR([The available JVM variants are: $VALID_JVM_VARIANTS]) @@ -101,7 +104,9 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], # All "special" variants share the same output directory ("server") VALID_MULTIPLE_JVM_VARIANTS="server client minimal" - INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + NEEDLE=${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'} + STACK=${JVM_VARIANTS// /$'\n'} + INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${NEEDLE}" <<< "${STACK}"` if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then AC_MSG_ERROR([You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS.]) fi @@ -293,146 +298,51 @@ AC_DEFUN_ONCE([HOTSPOT_VALIDATE_JVM_FEATURES], features_var_name=JVM_FEATURES_$variant JVM_FEATURES_TO_TEST=${!features_var_name} AC_MSG_RESULT([$JVM_FEATURES_TO_TEST]) - INVALID_FEATURES=`$GREP -Fvx "${VALID_JVM_FEATURES// /$'\n'}" <<< "${JVM_FEATURES_TO_TEST// /$'\n'}"` + NEEDLE=${VALID_JVM_FEATURES// /$'\n'} + STACK=${JVM_FEATURES_TO_TEST// /$'\n'} + INVALID_FEATURES=`$GREP -Fvx "${NEEDLE}" <<< "${STACK}"` if test "x$INVALID_FEATURES" != x; then AC_MSG_ERROR([Invalid JVM feature(s): $INVALID_FEATURES]) fi done ]) -############################################################################### -# Support for old hotspot build. Remove once new hotspot build has proven -# to work satisfactory. +################################################################################ +# Check if gtest should be built # -AC_DEFUN_ONCE([HOTSPOT_SETUP_LEGACY_BUILD], +AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_GTEST], [ - AC_ARG_ENABLE(new-hotspot-build, [AS_HELP_STRING([--disable-new-hotspot-build], - [disable the new hotspot build system (use the old) @<:@enabled@:>@])]) + AC_ARG_ENABLE([hotspot-gtest], [AS_HELP_STRING([--disable-hotspot-gtest], + [Disables building of the Hotspot unit tests])]) - if test "x$enable_new_hotspot_build" = "x" || test "x$enable_new_hotspot_build" = "xyes"; then - USE_NEW_HOTSPOT_BUILD=true - else - USE_NEW_HOTSPOT_BUILD=false - fi - AC_SUBST(USE_NEW_HOTSPOT_BUILD) - - case $HOTSPOT_DEBUG_LEVEL in - product ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - ;; - fastdebug ) - VARIANT="DBG" - FASTDEBUG="true" - DEBUG_CLASSFILES="true" - ;; - debug ) - VARIANT="DBG" - FASTDEBUG="false" - DEBUG_CLASSFILES="true" - ;; - optimized ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - ;; - esac - AC_SUBST(VARIANT) - AC_SUBST(FASTDEBUG) - AC_SUBST(DEBUG_CLASSFILES) - - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - MACOSX_UNIVERSAL="true" - fi - - AC_SUBST(MACOSX_UNIVERSAL) - - # Make sure JVM_VARIANTS_COMMA use minimal1 for backwards compatibility - JVM_VARIANTS_COMMA=`$ECHO ,$JVM_VARIANTS_OPT, | $SED -e 's/,minimal,/,minimal1,/'` - - JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` - JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` - JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,minimal1\?,/!s/.*/false/g' -e '/,minimal1\?,/s/.*/true/g'` - JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` - JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` - JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` - JVM_VARIANT_CUSTOM=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,custom,/!s/.*/false/g' -e '/,custom,/s/.*/true/g'` - - ##### - # Generate the legacy makefile targets for hotspot. - HOTSPOT_TARGET="" - - if test "x$JVM_VARIANT_SERVER" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} " - fi - - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 " - fi - - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 " - fi - - if test "x$JVM_VARIANT_ZERO" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero " - fi - - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark " - fi - - if test "x$JVM_VARIANT_CORE" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " - fi - - HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_DEBUG_LEVEL" - - # On Macosx universal binaries are produced, but they only contain - # 64 bit intel. This invalidates control of which jvms are built - # from configure, but only server is valid anyway. Fix this - # when hotspot makefiles are rewritten. - if test "x$MACOSX_UNIVERSAL" = xtrue; then - HOTSPOT_TARGET=universal_${HOTSPOT_DEBUG_LEVEL} - fi - - HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" - AC_SUBST(HOTSPOT_MAKE_ARGS) - - # Control wether Hotspot runs Queens test after build. - AC_ARG_ENABLE([hotspot-test-in-build], [AS_HELP_STRING([--enable-hotspot-test-in-build], - [run the Queens test after Hotspot build @<:@disabled@:>@])],, - [enable_hotspot_test_in_build=no]) - if test "x$enable_hotspot_test_in_build" = "xyes"; then - TEST_IN_BUILD=true + if test -e "$HOTSPOT_TOPDIR/test/native"; then + GTEST_DIR_EXISTS="true" else - TEST_IN_BUILD=false - fi - AC_SUBST(TEST_IN_BUILD) - - if test "x$USE_NEW_HOTSPOT_BUILD" = xfalse; then - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.]) - fi - fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.]) - fi - fi - if test "x$JVM_VARIANT_CUSTOM" = xtrue; then - AC_MSG_ERROR([You cannot build a custom JVM using the old hotspot build system.]) - fi + GTEST_DIR_EXISTS="false" fi - AC_SUBST(JVM_VARIANTS_COMMA) - AC_SUBST(JVM_VARIANT_SERVER) - AC_SUBST(JVM_VARIANT_CLIENT) - AC_SUBST(JVM_VARIANT_MINIMAL1) - AC_SUBST(JVM_VARIANT_HOTSPOT) - AC_SUBST(JVM_VARIANT_ZERO) - AC_SUBST(JVM_VARIANT_ZEROSHARK) - AC_SUBST(JVM_VARIANT_CORE) + AC_MSG_CHECKING([if Hotspot gtest unit tests should be built]) + if test "x$enable_hotspot_gtest" = "xyes"; then + if test "x$GTEST_DIR_EXISTS" = "xtrue"; then + AC_MSG_RESULT([yes, forced]) + BUILD_GTEST="true" + else + AC_MSG_ERROR([Cannot build gtest without the test source]) + fi + elif test "x$enable_hotspot_gtest" = "xno"; then + AC_MSG_RESULT([no, forced]) + BUILD_GTEST="false" + elif test "x$enable_hotspot_gtest" = "x"; then + if test "x$GTEST_DIR_EXISTS" = "xtrue"; then + AC_MSG_RESULT([yes]) + BUILD_GTEST="true" + else + AC_MSG_RESULT([no]) + BUILD_GTEST="false" + fi + else + AC_MSG_ERROR([--enable-gtest must be either yes or no]) + fi + + AC_SUBST(BUILD_GTEST) ]) diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index e34e4d927dd..4ae07928262 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -209,9 +209,6 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], if test "x$OPENJDK_TARGET_OS" = xaix ; then INCLUDE_SA=false fi - if test "x$OPENJDK_TARGET_CPU" = xaarch64; then - INCLUDE_SA=false - fi AC_SUBST(INCLUDE_SA) # Compress jars @@ -494,3 +491,46 @@ AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_FAILURE_HANDLER], AC_SUBST(BUILD_FAILURE_HANDLER) ]) + +################################################################################ +# +# Enable or disable generation of the classlist at build time +# +AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST], +[ + AC_ARG_ENABLE([generate-classlist], [AS_HELP_STRING([--disable-generate-classlist], + [forces enabling or disabling of the generation of a CDS classlist at build time. + Default is to generate it when either the server or client JVMs are built.])]) + + # Check if it's likely that it's possible to generate the classlist. Depending + # on exact jvm configuration it could be possible anyway. + if HOTSPOT_CHECK_JVM_VARIANT(server) || HOTSPOT_CHECK_JVM_VARIANT(client); then + ENABLE_GENERATE_CLASSLIST_POSSIBLE="true" + else + ENABLE_GENERATE_CLASSLIST_POSSIBLE="false" + fi + + AC_MSG_CHECKING([if the CDS classlist generation should be enabled]) + if test "x$enable_generate_classlist" = "xyes"; then + AC_MSG_RESULT([yes, forced]) + ENABLE_GENERATE_CLASSLIST="true" + if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then + AC_MSG_WARN([Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS]) + fi + elif test "x$enable_generate_classlist" = "xno"; then + AC_MSG_RESULT([no, forced]) + ENABLE_GENERATE_CLASSLIST="false" + elif test "x$enable_generate_classlist" = "x"; then + if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xtrue"; then + AC_MSG_RESULT([yes]) + ENABLE_GENERATE_CLASSLIST="true" + else + AC_MSG_RESULT([no]) + ENABLE_GENERATE_CLASSLIST="false" + fi + else + AC_MSG_ERROR([Invalid value for --enable-generate-classlist: $enable_generate_classlist]) + fi + + AC_SUBST([ENABLE_GENERATE_CLASSLIST]) +]) diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index e1e91d678d6..4238a17fe82 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -95,6 +95,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], LIB_SETUP_LLVM LIB_SETUP_BUNDLED_LIBS LIB_SETUP_MISC_LIBS + LIB_SETUP_SOLARIS_STLPORT ]) ################################################################################ @@ -189,3 +190,26 @@ AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS], LIBZIP_CAN_USE_MMAP=true AC_SUBST(LIBZIP_CAN_USE_MMAP) ]) + +################################################################################ +# libstlport.so.1 is needed for running gtest on Solaris. Find it to +# redistribute it in the test image. +################################################################################ +AC_DEFUN_ONCE([LIB_SETUP_SOLARIS_STLPORT], +[ + if test "$OPENJDK_TARGET_OS" = "solaris"; then + # Find the root of the Solaris Studio installation from the compiler path + SOLARIS_STUDIO_DIR="$(dirname $CC)/.." + STLPORT_LIB="$SOLARIS_STUDIO_DIR/lib/stlport4$OPENJDK_TARGET_CPU_ISADIR/libstlport.so.1" + AC_MSG_CHECKING([for libstlport.so.1]) + if test -f "$STLPORT_LIB"; then + AC_MSG_RESULT([yes, $STLPORT_LIB]) + BASIC_FIXUP_PATH([STLPORT_LIB]) + else + AC_MSG_RESULT([no, not found at $STLPORT_LIB]) + AC_MSG_ERROR([Failed to find libstlport.so.1, cannot build Hotspot gtests]) + fi + AC_SUBST(STLPORT_LIB) + fi +]) + diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index 2e99c452694..2fbac1d0dd3 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -366,6 +366,23 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], fi AC_SUBST(OPENJDK_$1_OS_EXPORT_DIR) + # The new version string in JDK 9 also defined new naming of OS and ARCH for bundles + # Macosx is osx and x86_64 is x64 + if test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_OS_BUNDLE="osx" + else + OPENJDK_$1_OS_BUNDLE="$OPENJDK_TARGET_OS" + fi + if test "x$OPENJDK_$1_CPU" = xx86_64; then + OPENJDK_$1_CPU_BUNDLE="x64" + else + OPENJDK_$1_CPU_BUNDLE="$OPENJDK_$1_CPU" + fi + OPENJDK_$1_BUNDLE_PLATFORM="${OPENJDK_$1_OS_BUNDLE}-${OPENJDK_$1_CPU_BUNDLE}" + AC_SUBST(OPENJDK_$1_OS_BUNDLE) + AC_SUBST(OPENJDK_$1_CPU_BUNDLE) + AC_SUBST(OPENJDK_$1_BUNDLE_PLATFORM) + if test "x$OPENJDK_$1_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 467cc304b20..a58639f2b8a 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -89,6 +89,10 @@ HOTSPOT_TARGET_CPU := @HOTSPOT_TARGET_CPU@ HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_TARGET_CPU_ARCH@ HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_TARGET_CPU_DEFINE@ +OPENJDK_TARGET_CPU_BUNDLE:=@OPENJDK_TARGET_CPU_BUNDLE@ +OPENJDK_TARGET_OS_BUNDLE:=@OPENJDK_TARGET_OS_BUNDLE@ +OPENJDK_TARGET_BUNDLE_PLATFORM:=@OPENJDK_TARGET_BUNDLE_PLATFORM@ + # We are building on this build system. # When not cross-compiling, it is the same as the target. OPENJDK_BUILD_OS:=@OPENJDK_BUILD_OS@ @@ -232,6 +236,9 @@ JVM_FEATURES_custom := @JVM_FEATURES_custom@ VALID_JVM_FEATURES := @VALID_JVM_FEATURES@ VALID_JVM_VARIANTS := @VALID_JVM_VARIANTS@ +# Control wether Hotspot builds gtest tests +BUILD_GTEST := @BUILD_GTEST@ + # Control use of precompiled header in hotspot libjvm build USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@ @@ -265,6 +272,7 @@ BUILDTOOLS_OUTPUTDIR=$(BUILD_OUTPUT)/buildtools HOTSPOT_OUTPUTDIR=$(BUILD_OUTPUT)/hotspot JDK_OUTPUTDIR=$(BUILD_OUTPUT)/jdk IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images +BUNDLES_OUTPUTDIR=$(BUILD_OUTPUT)/bundles TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support # This does not get overridden in a bootcycle build @@ -277,6 +285,8 @@ BUILD_HOTSPOT=@BUILD_HOTSPOT@ BUILD_FAILURE_HANDLER := @BUILD_FAILURE_HANDLER@ +ENABLE_GENERATE_CLASSLIST := @ENABLE_GENERATE_CLASSLIST@ + # The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep # it in sync. BOOT_JDK:=@BOOT_JDK@ @@ -629,6 +639,7 @@ ECHO:=@ECHO@ EGREP:=@EGREP@ FGREP:=@FGREP@ GREP:=@GREP@ +GZIP:=@GZIP@ HEAD:=@HEAD@ LS:=@LS@ LN:=@LN@ @@ -676,6 +687,9 @@ XCODEBUILD=@XCODEBUILD@ DTRACE := @DTRACE@ FIXPATH:=@FIXPATH@ +TAR_INCLUDE_PARAM:=@TAR_INCLUDE_PARAM@ +TAR_SUPPORTS_TRANSFORM:=@TAR_SUPPORTS_TRANSFORM@ + # Build setup ENABLE_JFR=@ENABLE_JFR@ ENABLE_INTREE_EC=@ENABLE_INTREE_EC@ @@ -685,6 +699,7 @@ USE_EXTERNAL_LIBZ:=@USE_EXTERNAL_LIBZ@ LIBZIP_CAN_USE_MMAP:=@LIBZIP_CAN_USE_MMAP@ MSVCR_DLL:=@MSVCR_DLL@ MSVCP_DLL:=@MSVCP_DLL@ +STLPORT_LIB:=@STLPORT_LIB@ #################################################### # @@ -781,11 +796,46 @@ SYMBOLS_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(SYMBOLS_IMAGE_SUBDIR) # Interim image INTERIM_IMAGE_DIR := $(SUPPORT_OUTPUTDIR)/interim-image +# Docs image +DOCS_IMAGE_SUBDIR := docs +DOCS_IMAGE_DIR := $(IMAGES_OUTPUTDIR)/$(DOCS_IMAGE_SUBDIR) + # Macosx bundles directory definitions -JDK_MACOSX_BUNDLE_SUBDIR=jdk-bundle/jdk-$(VERSION_NUMBER).jdk/Contents -JRE_MACOSX_BUNDLE_SUBDIR=jre-bundle/jre-$(VERSION_NUMBER).jre/Contents +JDK_MACOSX_BUNDLE_SUBDIR=jdk-bundle +JRE_MACOSX_BUNDLE_SUBDIR=jre-bundle JDK_MACOSX_BUNDLE_DIR=$(IMAGES_OUTPUTDIR)/$(JDK_MACOSX_BUNDLE_SUBDIR) JRE_MACOSX_BUNDLE_DIR=$(IMAGES_OUTPUTDIR)/$(JRE_MACOSX_BUNDLE_SUBDIR) +JDK_MACOSX_CONTENTS_SUBDIR=jdk-$(VERSION_NUMBER).jdk/Contents +JRE_MACOSX_CONTENTS_SUBDIR=jre-$(VERSION_NUMBER).jre/Contents +JDK_MACOSX_CONTENTS_DIR=$(JDK_MACOSX_BUNDLE_DIR)/$(JDK_MACOSX_CONTENTS_SUBDIR) +JRE_MACOSX_CONTENTS_DIR=$(JRE_MACOSX_BUNDLE_DIR)/$(JRE_MACOSX_CONTENTS_SUBDIR) + +# Bundle names +BASE_NAME := $(VERSION_SHORT)+$(VERSION_BUILD)_$(OPENJDK_TARGET_BUNDLE_PLATFORM) +ifeq ($(DEBUG_LEVEL), fastdebug) + DEBUG_PART := -debug +else ifneq ($(DEBUG_LEVEL), release) + DEBUG_PART := -$(DEBUG_LEVEL) +endif +JDK_BUNDLE_NAME := jdk-$(BASE_NAME)_bin$(DEBUG_PART).tar.gz +JRE_BUNDLE_NAME := jre-$(BASE_NAME)_bin$(DEBUG_PART).tar.gz +JDK_SYMBOLS_BUNDLE_NAME := jdk-$(BASE_NAME)_bin$(DEBUG_PART)-symbols.tar.gz +JRE_SYMBOLS_BUNDLE_NAME := jre-$(BASE_NAME)_bin$(DEBUG_PART)-symbols.tar.gz +ifeq ($(OPENJDK_TARGET_OS), windows) + DEMOS_BUNDLE_NAME := jdk-$(BASE_NAME)_demo$(DEBUG_PART).zip +else + DEMOS_BUNDLE_NAME := jdk-$(BASE_NAME)_demo$(DEBUG_PART).tar.gz +endif +TEST_BUNDLE_NAME := jdk-$(BASE_NAME)_bin-tests$(DEBUG_PART).tar.gz +DOCS_BUNDLE_NAME := jdk-$(BASE_NAME)_doc-api-spec$(DEBUG_PART).tar.gz + +JDK_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(JDK_BUNDLE_NAME) +JRE_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(JRE_BUNDLE_NAME) +JDK_SYMBOLS_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(JDK_SYMBOLS_BUNDLE_NAME) +JRE_SYMBOLS_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(JRE_SYMBOLS_BUNDLE_NAME) +DEMOS_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DEMOS_BUNDLE_NAME) +TEST_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(TEST_BUNDLE_NAME) +DOCS_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DOCS_BUNDLE_NAME) # This macro is called to allow inclusion of closed source counterparts. # Unless overridden in closed sources, it expands to nothing. diff --git a/common/bin/compare.sh b/common/bin/compare.sh index db73426481d..0126b9c23ce 100644 --- a/common/bin/compare.sh +++ b/common/bin/compare.sh @@ -274,14 +274,19 @@ compare_file_types() { $MKDIR -p $WORK_DIR + FILE_TYPES_FILTER="$SED \ + -e 's/BuildID[^,]*//' \ + -e 's/last modified: .*//' \ + " + echo -n File types... found="" for f in `cd $OTHER_DIR && $FIND . ! -type d` do if [ ! -f ${OTHER_DIR}/$f ]; then continue; fi if [ ! -f ${THIS_DIR}/$f ]; then continue; fi - OF=`cd ${OTHER_DIR} && $FILE -h $f | $SED 's/BuildID[^,]*//g'` - TF=`cd ${THIS_DIR} && $FILE -h $f | $SED 's/BuildID[^,]*//g'` + OF=$(cd ${OTHER_DIR} && $FILE -h $f | eval $FILE_TYPES_FILTER) + TF=$(cd ${THIS_DIR} && $FILE -h $f | eval $FILE_TYPES_FILTER) if [ "$OF" != "$TF" ] then if [ "`echo $OF | $GREP -c 'Zip archive data'`" -gt 0 ] \ @@ -320,7 +325,7 @@ compare_general_files() { ! -name "*.obj" ! -name "*.o" ! -name "JavaControlPanelHelper" \ ! -name "JavaUpdater" ! -name "JavaWSApplicationStub" \ ! -name "jspawnhelper" ! -name "JavawsLauncher" ! -name "*.a" \ - ! -name "finish_installation" ! -name "Sparkle" \ + ! -name "finish_installation" ! -name "Sparkle" ! -name "*.tar.gz" \ | $GREP -v "./bin/" | $SORT | $FILTER) echo Other files with binary differences... @@ -423,6 +428,10 @@ compare_zip_file() { then (cd $THIS_UNZIPDIR && $UNARCHIVE $THIS_ZIP) (cd $OTHER_UNZIPDIR && $UNARCHIVE $OTHER_ZIP) + elif [ "$TYPE" = "gz" ] + then + (cd $THIS_UNZIPDIR && $GUNZIP -c $THIS_ZIP | $TAR xf -) + (cd $OTHER_UNZIPDIR && $GUNZIP -c $OTHER_ZIP | $TAR xf -) else (cd $THIS_UNZIPDIR && $JIMAGE extract $THIS_ZIP) (cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP) @@ -526,10 +535,11 @@ compare_all_zip_files() { OTHER_DIR=$2 WORK_DIR=$3 - ZIPS=$(cd $THIS_DIR && $FIND . -type f -name "*.zip" | $SORT | $FILTER ) + ZIPS=$(cd $THIS_DIR && $FIND . -type f -name "*.zip" -o -name "*.tar.gz" \ + | $SORT | $FILTER ) if [ -n "$ZIPS" ]; then - echo Zip files... + echo Zip/tar.gz files... return_value=0 for f in $ZIPS; do @@ -913,7 +923,7 @@ compare_bin_file() { FULLDUMP_MSG=" " DIFF_FULLDUMP= if [[ "$KNOWN_FULLDUMP_DIFF $ACCEPTED_FULLDUMP_DIFF" = *"$BIN_FILE"* ]]; then - FULLDUMP_MSG=" ! " + FULLDUMP_MSG=" ! " fi fi fi diff --git a/common/bin/idea.sh b/common/bin/idea.sh index 911d309c070..2cd6f92bbb9 100644 --- a/common/bin/idea.sh +++ b/common/bin/idea.sh @@ -155,6 +155,14 @@ addBuildDir() { printf "%s\n" "$mn" >> $IDEA_ANT } +JTREG_HOME=" " + +addJtregHome() { + DIR=`dirname $SPEC` + mn="`echo "$JTREG_HOME" | sed -e s@"\(.*\)####\(.*\)"@"\1$JT_HOME\2"@`" + printf "%s\n" "$mn" >> $IDEA_ANT +} + ### Generate ant.xml rm -f $IDEA_ANT @@ -162,6 +170,8 @@ while IFS= read -r line do if echo "$line" | egrep "^ .* /dev/null ; then addModuleName + elif echo "$line" | egrep "^ .* /dev/null ; then + addJtregHome elif echo "$line" | egrep "^ .* /dev/null ; then addBuildDir else diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index 2b7164741b1..2d752fd1074 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -215,11 +215,11 @@ var getJibProfilesCommon = function (input) { var common = {}; common.dependencies = ["boot_jdk", "gnumake", "jtreg"], - common.default_make_targets = ["product-images", "test-image"], + common.default_make_targets = ["product-bundles", "test-bundles"], common.default_make_targets_debug = common.default_make_targets; common.default_make_targets_slowdebug = common.default_make_targets; common.configure_args = ["--enable-jtreg-failure-handler"], - common.configure_args_32bit = ["--with-target-bits=32", "--with-jvm-variants=client,server"], + common.configure_args_32bit = ["--with-target-bits=32"], common.configure_args_debug = ["--enable-debug"], common.configure_args_slowdebug = ["--with-debug-level=slowdebug"], common.organization = "jpg.infra.builddeps" @@ -245,7 +245,7 @@ var getJibProfilesProfiles = function (input, common) { target_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), configure_args: concat(common.configure_args, "--with-zlib=system"), - default_make_targets: concat(common.default_make_targets, "docs-image") + default_make_targets: concat(common.default_make_targets, "docs-bundles") }, "linux-x86": { @@ -254,7 +254,7 @@ var getJibProfilesProfiles = function (input, common) { build_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), configure_args: concat(common.configure_args, common.configure_args_32bit, - "--with-zlib=system"), + "--with-jvm-variants=minimal,client,server", "--with-zlib=system"), default_make_targets: common.default_make_targets }, @@ -295,7 +295,8 @@ var getJibProfilesProfiles = function (input, common) { target_cpu: "x86", build_cpu: "x64", dependencies: concat(common.dependencies, "devkit", "freetype"), - configure_args: concat(common.configure_args, common.configure_args_32bit), + configure_args: concat(common.configure_args, + "--with-jvm-variants=client,server", common.configure_args_32bit), default_make_targets: common.default_make_targets } }; diff --git a/corba/.hgtags b/corba/.hgtags index feea5f070eb..284ccf7a0d8 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -361,3 +361,5 @@ cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113 7dfa7377a5e601b8f740741a9a80e04c72dd04d6 jdk-9+116 7a1b36bf2fe55a9a7732489ccdd326c910329a7e jdk-9+117 8c2c2d17f7ce92a31c9ccb44a122ec62f5a85ace jdk-9+118 +daf533920b1266603b5cbdab31908d2a931c5361 jdk-9+119 +5943b791e131e79b969d4cea053aecda34801723 jdk-9+120 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 754ebb60e4b..c500fce7e12 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -522,3 +522,4 @@ b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114 88170d3642905b9e6cac03e8efcc976885a7e6da jdk-9+117 9b1075cac08dc836ec32e7b368415cbe3aceaf8c jdk-9+118 15f3fe264872766bcb205696198f0c1502420e17 jdk-9+119 +0be6f4f5d18671184e62583668cb1d783dffa128 jdk-9+120 diff --git a/hotspot/LICENSE b/hotspot/LICENSE index b40a0f457d7..8b400c7ab81 100644 --- a/hotspot/LICENSE +++ b/hotspot/LICENSE @@ -3,7 +3,7 @@ The GNU General Public License (GPL) Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -287,8 +287,8 @@ pointer to where the full notice is found. more details. You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp index 002f5133234..813580542e1 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1547,6 +1547,10 @@ class Assembler : public AbstractAssembler { inline void ld( Register d, int si16, Register s1); inline void ldu( Register d, int si16, Register s1); + // For convenience. Load pointer into d from b+s1. + inline void ld_ptr(Register d, int b, Register s1); + DEBUG_ONLY(inline void ld_ptr(Register d, ByteSize b, Register s1);) + // PPC 1, section 3.3.3 Fixed-Point Store Instructions inline void stwx( Register d, Register s1, Register s2); inline void stw( Register d, int si16, Register s1); @@ -2215,7 +2219,8 @@ class Assembler : public AbstractAssembler { void add( Register d, RegisterOrConstant roc, Register s1); void subf(Register d, RegisterOrConstant roc, Register s1); void cmpd(ConditionRegister d, RegisterOrConstant roc, Register s1); - + // Load pointer d from s1+roc. + void ld_ptr(Register d, RegisterOrConstant roc, Register s1 = noreg) { ld(d, roc, s1); } // Emit several instructions to load a 64 bit constant. This issues a fixed // instruction pattern so that the constant can be patched later on. diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp index 220e3a727c8..ca126170157 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -328,6 +328,9 @@ inline void Assembler::ld( Register d, int si16, Register s1) { emit_int32( inline void Assembler::ldx( Register d, Register s1, Register s2) { emit_int32(LDX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::ldu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LDU_OPCODE | rt(d) | ds(si16) | rta0mem(s1));} +inline void Assembler::ld_ptr(Register d, int b, Register s1) { ld(d, b, s1); } +DEBUG_ONLY(inline void Assembler::ld_ptr(Register d, ByteSize b, Register s1) { ld(d, in_bytes(b), s1); }) + // PPC 1, section 3.3.3 Fixed-Point Store Instructions inline void Assembler::stwx( Register d, Register s1, Register s2) { emit_int32(STWX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stw( Register d, int si16, Register s1) { emit_int32(STW_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp index 559f68709bf..afc000317a3 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1242,7 +1242,7 @@ void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type, void LIR_Assembler::return_op(LIR_Opr result) { - const Register return_pc = R11; + const Register return_pc = R31; // Must survive C-call to enable_stack_reserved_zone(). const Register polling_page = R12; // Pop the stack before the safepoint code. @@ -1265,6 +1265,10 @@ void LIR_Assembler::return_op(LIR_Opr result) { // Move return pc to LR. __ mtlr(return_pc); + if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) { + __ reserved_stack_check(return_pc); + } + // We need to mark the code position where the load from the safepoint // polling page was emitted as relocInfo::poll_return_type here. __ relocate(relocInfo::poll_return_type); diff --git a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp index f8fe437547d..941a65fa041 100644 --- a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,4 +52,6 @@ const bool CCallingConventionRequiresIntsAsLongs = true; #define INCLUDE_RTM_OPT 1 #endif +#define SUPPORT_RESERVED_STACK_AREA + #endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index b69e4058507..a442f17f4b8 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -43,7 +43,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs pas #define DEFAULT_STACK_YELLOW_PAGES (6) #define DEFAULT_STACK_RED_PAGES (1) #define DEFAULT_STACK_SHADOW_PAGES (6 DEBUG_ONLY(+2)) -#define DEFAULT_STACK_RESERVED_PAGES (0) +#define DEFAULT_STACK_RESERVED_PAGES (1) #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES #define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index cedc1e08c1c..d3c60b74944 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -480,6 +480,7 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register void InterpreterMacroAssembler::generate_stack_overflow_check_with_compare_and_throw(Register Rmem_frame_size, Register Rscratch1) { Label done; + BLOCK_COMMENT("stack_overflow_check_with_compare_and_throw {"); sub(Rmem_frame_size, R1_SP, Rmem_frame_size); ld(Rscratch1, thread_(stack_overflow_limit)); cmpld(CCR0/*is_stack_overflow*/, Rmem_frame_size, Rscratch1); @@ -501,6 +502,7 @@ void InterpreterMacroAssembler::generate_stack_overflow_check_with_compare_and_t align(32, 12); bind(done); + BLOCK_COMMENT("} stack_overflow_check_with_compare_and_throw"); } // Separate these two to allow for delay slot in middle. @@ -805,16 +807,41 @@ void InterpreterMacroAssembler::narrow(Register result) { void InterpreterMacroAssembler::remove_activation(TosState state, bool throw_monitor_exception, bool install_monitor_exception) { + BLOCK_COMMENT("remove_activation {"); unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception); // Save result (push state before jvmti call and pop it afterwards) and notify jvmti. notify_method_exit(false, state, NotifyJVMTI, true); + BLOCK_COMMENT("reserved_stack_check:"); + if (StackReservedPages > 0) { + // Test if reserved zone needs to be enabled. + Label no_reserved_zone_enabling; + + // Compare frame pointers. There is no good stack pointer, as with stack + // frame compression we can get different SPs when we do calls. A subsequent + // call could have a smaller SP, so that this compare succeeds for an + // inner call of the method annotated with ReservedStack. + ld_ptr(R0, JavaThread::reserved_stack_activation_offset(), R16_thread); + ld_ptr(R11_scratch1, _abi(callers_sp), R1_SP); // Load frame pointer. + cmpld(CCR0, R11_scratch1, R0); + blt_predict_taken(CCR0, no_reserved_zone_enabling); + + // Enable reserved zone again, throw stack overflow exception. + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), R16_thread); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_delayed_StackOverflowError)); + + should_not_reach_here(); + + bind(no_reserved_zone_enabling); + } + verify_oop(R17_tos, state); verify_thread(); merge_frames(/*top_frame_sp*/ R21_sender_SP, /*return_pc*/ R0, R11_scratch1, R12_scratch2); mtlr(R0); + BLOCK_COMMENT("} remove_activation"); } // Lock object diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index b8ad532bc3c..d0b0fa8dbda 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -1400,6 +1400,28 @@ address MacroAssembler::get_stack_bang_address(int instruction, void *ucontext) #endif } +void MacroAssembler::reserved_stack_check(Register return_pc) { + // Test if reserved zone needs to be enabled. + Label no_reserved_zone_enabling; + + ld_ptr(R0, JavaThread::reserved_stack_activation_offset(), R16_thread); + cmpld(CCR0, R1_SP, R0); + blt_predict_taken(CCR0, no_reserved_zone_enabling); + + // Enable reserved zone again, throw stack overflow exception. + push_frame_reg_args(0, R0); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), R16_thread); + pop_frame(); + mtlr(return_pc); + load_const_optimized(R0, StubRoutines::throw_delayed_StackOverflowError_entry()); + mtctr(R0); + bctr(); + + should_not_reach_here(); + + bind(no_reserved_zone_enabling); +} + // CmpxchgX sets condition register to cmpX(current, compare). void MacroAssembler::cmpxchgw(ConditionRegister flag, Register dest_current_value, Register compare_value, Register exchange_value, diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp index 0f39e4a3003..003c27b4333 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp @@ -411,6 +411,10 @@ class MacroAssembler: public Assembler { // stdux, return the banged address. Otherwise, return 0. static address get_stack_bang_address(int instruction, void* ucontext); + // Check for reserved stack access in method being exited. If the reserved + // stack area was accessed, protect it again and throw StackOverflowError. + void reserved_stack_check(Register return_pc); + // Atomics // CmpxchgX sets condition register to cmpX(current, compare). // (flag == ne) => (dest_current_value != compare_value), (!swapped) diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index d8c36a34f5d..a62eef493b4 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -1432,7 +1432,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { const bool method_needs_polling = do_polling() && C->is_method_compilation(); const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/; - const Register return_pc = R11; + const Register return_pc = R31; // Must survive C-call to enable_stack_reserved_zone(). const Register polling_page = R12; if (!method_is_frameless) { @@ -1456,6 +1456,10 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { __ addi(R1_SP, R1_SP, (int)framesize); } + if (StackReservedPages > 0 && C->has_reserved_stack_access()) { + __ reserved_stack_check(return_pc); + } + if (method_needs_polling) { // We need to mark the code position where the load from the safepoint // polling page was emitted as relocInfo::poll_return_type here. diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index 7ae89abd38f..e845d2872ed 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -3123,6 +3123,9 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false); + StubRoutines::_throw_delayed_StackOverflowError_entry = + generate_throw_exception("delayed StackOverflowError throw_exception", + CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError), false); // CRC32 Intrinsics. if (UseCRC32Intrinsics) { diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index 386990690a7..11690a1ddf7 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015 SAP SE. All rights reserved. + * Copyright (c) 2015, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -562,10 +562,16 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { return NULL; } -// Actually we should never reach here since we do stack overflow checks before pushing any frame. address TemplateInterpreterGenerator::generate_StackOverflowError_handler() { address entry = __ pc(); - __ unimplemented("generate_StackOverflowError_handler"); + + // Expression stack must be empty before entering the VM if an + // exception happened. + __ empty_expression_stack(); + // Throw exception. + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_StackOverflowError)); return entry; } @@ -944,7 +950,7 @@ void TemplateInterpreterGenerator::lock_method(Register Rflags, Register Rscratc // The top most frame needs an abi space of 112 bytes. This space is needed, // since we call to c. The c function may spill their arguments to the caller // frame. When we call to java, we don't need these spill slots. In order to save -// space on the stack, we resize the caller. However, java local reside in +// space on the stack, we resize the caller. However, java locals reside in // the caller frame and the frame has to be increased. The frame_size for the // current frame was calculated based on max_stack as size for the expression // stack. At the call, just a part of the expression stack might be used. @@ -1007,7 +1013,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist // parent_frame_resize = (locals-parameters) - (ESP-SP-ABI48) Rounded to frame alignment size. // Enlarge by locals-parameters (not in case of native_call), shrink by ESP-SP-ABI48. - { + if (!native_call) { // -------------------------------------------------------------------------- // Stack overflow check @@ -1047,7 +1053,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist __ addi(R26_monitor, R1_SP, - frame::ijava_state_size); __ addi(R15_esp, R26_monitor, - Interpreter::stackElementSize); - // Get mirror and store it in the frame as GC root for this Method* + // Get mirror and store it in the frame as GC root for this Method*. __ load_mirror(R12_scratch2, R19_method); // Store values. @@ -1133,6 +1139,29 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M return entry; } +void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { + // Quick & dirty stack overflow checking: bang the stack & handle trap. + // Note that we do the banging after the frame is setup, since the exception + // handling code expects to find a valid interpreter frame on the stack. + // Doing the banging earlier fails if the caller frame is not an interpreter + // frame. + // (Also, the exception throwing code expects to unlock any synchronized + // method receiever, so do the banging after locking the receiver.) + + // Bang each page in the shadow zone. We can't assume it's been done for + // an interpreter frame with greater than a page of locals, so each page + // needs to be checked. Only true for non-native. + if (UseStackBanging) { + const int page_size = os::vm_page_size(); + const int n_shadow_pages = ((int)JavaThread::stack_shadow_zone_size()) / page_size; + const int start_page = native_call ? n_shadow_pages : 1; + BLOCK_COMMENT("bang_stack_shadow_pages:"); + for (int pages = start_page; pages <= n_shadow_pages; pages++) { + __ bang_stack_with_offset(pages*page_size); + } + } +} + // Interpreter stub for calling a native method. (asm interpreter) // This sets up a somewhat different looking stack for calling the // native method than the typical interpreter frame setup. @@ -1156,7 +1185,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // This is not a full-blown interpreter frame, but in particular, the // following registers are valid after this: // - R19_method - // - R18_local (points to start of argumuments to native function) + // - R18_local (points to start of arguments to native function) // // abstract stack (grows up) // [ IJava (caller of JNI callee) ] <-- ASP @@ -1207,6 +1236,11 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { generate_counter_incr(&invocation_counter_overflow, NULL, NULL); BIND(continue_after_compile); + } + + bang_stack_shadow_pages(true); + + if (inc_counter) { // Reset the _do_not_unlock_if_synchronized flag. if (synchronized) { __ li(R0, 0); @@ -1595,6 +1629,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { Register Rsize_of_parameters = R4_ARG2, // Written by generate_fixed_frame. Rsize_of_locals = R5_ARG3; // Written by generate_fixed_frame. + // Does also a stack check to assure this frame fits on the stack. generate_fixed_frame(false, Rsize_of_parameters, Rsize_of_locals); // -------------------------------------------------------------------------- @@ -1651,7 +1686,11 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { } __ bind(profile_method_continue); + } + bang_stack_shadow_pages(false); + + if (inc_counter || ProfileInterpreter) { // Reset the _do_not_unlock_if_synchronized flag. if (synchronized) { __ li(R0, 0); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java index 5374a5a40e6..916cb445387 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -1712,7 +1712,8 @@ public class CommandProcessor { // called after debuggee attach private void postAttach() { // create JavaScript engine and start it - jsengine = new JSJavaScriptEngine() { + try { + jsengine = new JSJavaScriptEngine() { private ObjectReader reader = new ObjectReader(); private JSJavaFactory factory = new JSJavaFactoryImpl(); public ObjectReader getObjectReader() { @@ -1735,17 +1736,24 @@ public class CommandProcessor { return err; } }; - try { - jsengine.defineFunction(this, + try { + jsengine.defineFunction(this, this.getClass().getMethod("registerCommand", new Class[] { String.class, String.class, String.class })); - } catch (NoSuchMethodException exp) { - // should not happen, see below...!! - exp.printStackTrace(); + } catch (NoSuchMethodException exp) { + // should not happen, see below...!! + exp.printStackTrace(); + } + jsengine.start(); + } + catch (Exception ex) { + System.out.println("Warning! JS Engine can't start, some commands will not be available."); + if (verboseExceptions) { + ex.printStackTrace(out); + } } - jsengine.start(); } public void registerCommand(String cmd, String usage, final String func) { diff --git a/hotspot/src/os/aix/vm/os_aix.hpp b/hotspot/src/os/aix/vm/os_aix.hpp index cc4337070c8..db8c38aca5e 100644 --- a/hotspot/src/os/aix/vm/os_aix.hpp +++ b/hotspot/src/os/aix/vm/os_aix.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, 2015 SAP SE. All rights reserved. + * Copyright (c) 2013, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,6 +128,8 @@ class Aix { // Set PC into context. Needed for continuation after signal. static void ucontext_set_pc(ucontext_t* uc, address pc); + static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr); + // This boolean allows users to forward their own non-matching signals // to JVM_handle_aix_signal, harmlessly. static bool signal_handlers_are_installed; diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp index 211a2dc3323..84ae1ab1dc5 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 SAP SE. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ */ // no precompiled headers -#include "assembler_ppc.inline.hpp" +#include "asm/assembler.inline.hpp" #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" @@ -145,6 +145,41 @@ frame os::fetch_frame_from_context(const void* ucVoid) { return fr; } +bool os::Aix::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { + address pc = (address) os::Aix::ucontext_get_pc(uc); + if (Interpreter::contains(pc)) { + // Interpreter performs stack banging after the fixed frame header has + // been generated while the compilers perform it before. To maintain + // semantic consistency between interpreted and compiled frames, the + // method returns the Java sender of the current frame. + *fr = os::fetch_frame_from_context(uc); + if (!fr->is_first_java_frame()) { + assert(fr->safe_for_sender(thread), "Safety check"); + *fr = fr->java_sender(); + } + } else { + // More complex code with compiled code. + assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above"); + CodeBlob* cb = CodeCache::find_blob(pc); + if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) { + // Not sure where the pc points to, fallback to default + // stack overflow handling. In compiled code, we bang before + // the frame is complete. + return false; + } else { + intptr_t* sp = os::Aix::ucontext_get_sp(uc); + *fr = frame(sp, (address)*sp); + if (!fr->is_java_frame()) { + assert(fr->safe_for_sender(thread), "Safety check"); + assert(!fr->is_first_frame(), "Safety check"); + *fr = fr->java_sender(); + } + } + } + assert(fr->is_java_frame(), "Safety check"); + return true; +} + frame os::get_sender_for_C_frame(frame* fr) { if (*fr->sp() == NULL) { // fr is the last C frame @@ -246,14 +281,32 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec // to continue with yellow zone disabled, but that doesn't buy us much and prevents // hs_err_pid files. if (thread->in_stack_yellow_reserved_zone(addr)) { - thread->disable_stack_yellow_reserved_zone(); if (thread->thread_state() == _thread_in_Java) { + if (thread->in_stack_reserved_zone(addr)) { + frame fr; + if (os::Aix::get_frame_at_stack_banging_point(thread, uc, &fr)) { + assert(fr.is_java_frame(), "Must be a Javac frame"); + frame activation = + SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); + if (activation.sp() != NULL) { + thread->disable_stack_reserved_zone(); + if (activation.is_interpreted_frame()) { + thread->set_reserved_stack_activation((address)activation.fp()); + } else { + thread->set_reserved_stack_activation((address)activation.unextended_sp()); + } + return 1; + } + } + } // Throw a stack overflow exception. // Guard pages will be reenabled while unwinding the stack. + thread->disable_stack_yellow_reserved_zone(); stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); goto run_stub; } else { // Thread was in the vm or native code. Return and try to finish. + thread->disable_stack_yellow_reserved_zone(); return 1; } } else if (thread->in_stack_red_zone(addr)) { diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp index 8cd04dce290..18cd557741d 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ */ // no precompiled headers -#include "assembler_ppc.inline.hpp" +#include "asm/assembler.inline.hpp" #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" @@ -157,6 +157,42 @@ frame os::fetch_frame_from_context(const void* ucVoid) { return frame(sp, epc.pc()); } +bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { + address pc = (address) os::Linux::ucontext_get_pc(uc); + if (Interpreter::contains(pc)) { + // Interpreter performs stack banging after the fixed frame header has + // been generated while the compilers perform it before. To maintain + // semantic consistency between interpreted and compiled frames, the + // method returns the Java sender of the current frame. + *fr = os::fetch_frame_from_context(uc); + if (!fr->is_first_java_frame()) { + assert(fr->safe_for_sender(thread), "Safety check"); + *fr = fr->java_sender(); + } + } else { + // More complex code with compiled code. + assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above"); + CodeBlob* cb = CodeCache::find_blob(pc); + if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) { + // Not sure where the pc points to, fallback to default + // stack overflow handling. In compiled code, we bang before + // the frame is complete. + return false; + } else { + intptr_t* fp = os::Linux::ucontext_get_fp(uc); + intptr_t* sp = os::Linux::ucontext_get_sp(uc); + *fr = frame(sp, (address)*sp); + if (!fr->is_java_frame()) { + assert(fr->safe_for_sender(thread), "Safety check"); + assert(!fr->is_first_frame(), "Safety check"); + *fr = fr->java_sender(); + } + } + } + assert(fr->is_java_frame(), "Safety check"); + return true; +} + frame os::get_sender_for_C_frame(frame* fr) { if (*fr->sp() == 0) { // fr is the last C frame @@ -243,13 +279,31 @@ JVM_handle_linux_signal(int sig, if (thread->on_local_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { - thread->disable_stack_yellow_reserved_zone(); if (thread->thread_state() == _thread_in_Java) { + if (thread->in_stack_reserved_zone(addr)) { + frame fr; + if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) { + assert(fr.is_java_frame(), "Must be a Javac frame"); + frame activation = + SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); + if (activation.sp() != NULL) { + thread->disable_stack_reserved_zone(); + if (activation.is_interpreted_frame()) { + thread->set_reserved_stack_activation((address)activation.fp()); + } else { + thread->set_reserved_stack_activation((address)activation.unextended_sp()); + } + return 1; + } + } + } // Throw a stack overflow exception. // Guard pages will be reenabled while unwinding the stack. + thread->disable_stack_yellow_reserved_zone(); stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); } else { // Thread was in the vm or native code. Return and try to finish. + thread->disable_stack_yellow_reserved_zone(); return 1; } } else if (thread->in_stack_red_zone(addr)) { diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 001c7fd13ea..7bb8f759ffe 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -704,13 +704,14 @@ Method* ciEnv::lookup_method(InstanceKlass* accessor, InstanceKlass* holder, Symbol* name, Symbol* sig, - Bytecodes::Code bc) { + Bytecodes::Code bc, + constantTag tag) { EXCEPTION_CONTEXT; KlassHandle h_accessor(THREAD, accessor); KlassHandle h_holder(THREAD, holder); LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL)); methodHandle dest_method; - LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true); + LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag); switch (bc) { case Bytecodes::_invokestatic: dest_method = @@ -796,7 +797,9 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool, if (holder_is_accessible) { // Our declared holder is loaded. InstanceKlass* lookup = declared_holder->get_instanceKlass(); - Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc); + constantTag tag = cpool->tag_ref_at(index); + assert(accessor->get_instanceKlass() == cpool->pool_holder(), "not the pool holder?"); + Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc, tag); if (m != NULL && (bc == Bytecodes::_invokestatic ? m->method_holder()->is_not_initialized() diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index cd7138d33b2..e5a99e1a96a 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -156,7 +156,8 @@ private: InstanceKlass* holder, Symbol* name, Symbol* sig, - Bytecodes::Code bc); + Bytecodes::Code bc, + constantTag tag); // Get a ciObject from the object factory. Ensures uniqueness // of ciObjects. diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 8294024ac9e..2a4484850bb 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -789,7 +789,8 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); - LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access); + LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, + check_access ? LinkInfo::needs_access_check : LinkInfo::skip_access_check); methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index d77aef277eb..12858cccf28 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -657,7 +657,7 @@ void ClassLoader::setup_xpatch_entries() { int num_of_entries = xpatch_args->length(); // Set up the boot loader's xpatch_entries list - _xpatch_entries = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(num_of_entries, true); + _xpatch_entries = new (ResourceObj::C_HEAP, mtModule) GrowableArray(num_of_entries, true); for (int i = 0; i < num_of_entries; i++) { const char* module_name = (xpatch_args->at(i))->module_name(); @@ -1069,9 +1069,9 @@ void ClassLoader::initialize_module_loader_map(JImageFile* jimage) { char* begin_ptr = char_buf; char* end_ptr = strchr(begin_ptr, '\n'); bool process_boot_modules = false; - _boot_modules_array = new (ResourceObj::C_HEAP, mtInternal) + _boot_modules_array = new (ResourceObj::C_HEAP, mtModule) GrowableArray(INITIAL_BOOT_MODULES_ARRAY_SIZE, true); - _platform_modules_array = new (ResourceObj::C_HEAP, mtInternal) + _platform_modules_array = new (ResourceObj::C_HEAP, mtModule) GrowableArray(INITIAL_PLATFORM_MODULES_ARRAY_SIZE, true); while (end_ptr != NULL && (end_ptr - char_buf) < buflen) { // Allocate a buffer from the C heap to be appended to the _boot_modules_array diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index a9829a0393e..7635879a49a 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -67,6 +67,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.hpp" #include "runtime/mutex.hpp" +#include "runtime/orderAccess.hpp" #include "runtime/safepoint.hpp" #include "runtime/synchronizer.hpp" #include "utilities/growableArray.hpp" @@ -76,6 +77,11 @@ #include "trace/tracing.hpp" #endif +// helper function to avoid in-line casts +template static T* load_ptr_acquire(T* volatile *p) { + return static_cast(OrderAccess::load_ptr_acquire(p)); +} + ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL; ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies) : @@ -147,20 +153,23 @@ void ClassLoaderData::Dependencies::oops_do(OopClosure* f) { } void ClassLoaderData::classes_do(KlassClosure* klass_closure) { - for (Klass* k = _klasses; k != NULL; k = k->next_link()) { + // Lock-free access requires load_ptr_acquire + for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) { klass_closure->do_klass(k); assert(k != k->next_link(), "no loops!"); } } void ClassLoaderData::classes_do(void f(Klass * const)) { + assert_locked_or_safepoint(_metaspace_lock); for (Klass* k = _klasses; k != NULL; k = k->next_link()) { f(k); } } void ClassLoaderData::methods_do(void f(Method*)) { - for (Klass* k = _klasses; k != NULL; k = k->next_link()) { + // Lock-free access requires load_ptr_acquire + for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) { if (k->is_instance_klass()) { InstanceKlass::cast(k)->methods_do(f); } @@ -179,7 +188,8 @@ void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) { } void ClassLoaderData::classes_do(void f(InstanceKlass*)) { - for (Klass* k = _klasses; k != NULL; k = k->next_link()) { + // Lock-free access requires load_ptr_acquire + for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) { if (k->is_instance_klass()) { f(InstanceKlass::cast(k)); } @@ -188,6 +198,7 @@ void ClassLoaderData::classes_do(void f(InstanceKlass*)) { } void ClassLoaderData::modules_do(void f(ModuleEntry*)) { + assert_locked_or_safepoint(Module_lock); if (_modules != NULL) { for (int i = 0; i < _modules->table_size(); i++) { for (ModuleEntry* entry = _modules->bucket(i); @@ -200,9 +211,11 @@ void ClassLoaderData::modules_do(void f(ModuleEntry*)) { } void ClassLoaderData::packages_do(void f(PackageEntry*)) { - if (_packages != NULL) { - for (int i = 0; i < _packages->table_size(); i++) { - for (PackageEntry* entry = _packages->bucket(i); + // Lock-free access requires load_ptr_acquire + PackageEntryTable* packages = load_ptr_acquire(&_packages); + if (packages != NULL) { + for (int i = 0; i < packages->table_size(); i++) { + for (PackageEntry* entry = packages->bucket(i); entry != NULL; entry = entry->next()) { f(entry); @@ -325,10 +338,9 @@ void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) { MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); Klass* old_value = _klasses; k->set_next_link(old_value); - // Make sure linked class is stable, since the class list is walked without a lock - OrderAccess::storestore(); - // link the new item into the list - _klasses = k; + // Link the new item into the list, making sure the linked class is stable + // since the list can be walked without a lock + OrderAccess::release_store_ptr(&_klasses, k); } if (publicize && k->class_loader_data() != NULL) { @@ -343,11 +355,10 @@ void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) { } } -// This is called by InstanceKlass::deallocate_contents() to remove the -// scratch_class for redefine classes. We need a lock because there it may not -// be called at a safepoint if there's an error. +// Remove a klass from the _klasses list for scratch_class during redefinition +// or parsed class in the case of an error. void ClassLoaderData::remove_class(Klass* scratch_class) { - MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); Klass* prev = NULL; for (Klass* k = _klasses; k != NULL; k = k->next_link()) { if (k == scratch_class) { @@ -390,42 +401,46 @@ void ClassLoaderData::unload() { PackageEntryTable* ClassLoaderData::packages() { // Lazily create the package entry table at first request. - if (_packages == NULL) { + // Lock-free access requires load_ptr_acquire. + PackageEntryTable* packages = load_ptr_acquire(&_packages); + if (packages == NULL) { MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); // Check if _packages got allocated while we were waiting for this lock. - if (_packages == NULL) { - _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); + if ((packages = _packages) == NULL) { + packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); + // Ensure _packages is stable, since it is examined without a lock + OrderAccess::release_store_ptr(&_packages, packages); } } - return _packages; + return packages; } ModuleEntryTable* ClassLoaderData::modules() { // Lazily create the module entry table at first request. - if (_modules == NULL) { + // Lock-free access requires load_ptr_acquire. + ModuleEntryTable* modules = load_ptr_acquire(&_modules); + if (modules == NULL) { MutexLocker m1(Module_lock); - // Check again if _modules has been allocated while we were getting this lock. - if (_modules != NULL) { - return _modules; - } + // Check if _modules got allocated while we were waiting for this lock. + if ((modules = _modules) == NULL) { + modules = new ModuleEntryTable(ModuleEntryTable::_moduletable_entry_size); + // Each loader has one unnamed module entry. Create it before + // any classes, loaded by this loader, are defined in case + // they end up being defined in loader's unnamed module. + modules->create_unnamed_module(this); - ModuleEntryTable* temp_table = new ModuleEntryTable(ModuleEntryTable::_moduletable_entry_size); - // Each loader has one unnamed module entry. Create it before - // any classes, loaded by this loader, are defined in case - // they end up being defined in loader's unnamed module. - temp_table->create_unnamed_module(this); - - { - MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); - // Ensure _modules is stable, since it is examined without a lock - OrderAccess::storestore(); - _modules = temp_table; + { + MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); + // Ensure _modules is stable, since it is examined without a lock + OrderAccess::release_store_ptr(&_modules, modules); + } } } - return _modules; + return modules; } oop ClassLoaderData::keep_alive_object() const { + assert_locked_or_safepoint(_metaspace_lock); assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive"); return is_anonymous() ? _klasses->java_mirror() : class_loader(); } @@ -499,30 +514,33 @@ Metaspace* ClassLoaderData::metaspace_non_null() { // to create smaller arena for Reflection class loaders also. // The reason for the delayed allocation is because some class loaders are // simply for delegating with no metadata of their own. - if (_metaspace == NULL) { - MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); - // Check again if metaspace has been allocated while we were getting this lock. - if (_metaspace != NULL) { - return _metaspace; - } - if (this == the_null_class_loader_data()) { - assert (class_loader() == NULL, "Must be"); - set_metaspace(new Metaspace(_metaspace_lock, Metaspace::BootMetaspaceType)); - } else if (is_anonymous()) { - if (class_loader() != NULL) { - log_trace(class, loader, data)("is_anonymous: %s", class_loader()->klass()->internal_name()); + // Lock-free access requires load_ptr_acquire. + Metaspace* metaspace = load_ptr_acquire(&_metaspace); + if (metaspace == NULL) { + MutexLockerEx ml(_metaspace_lock, Mutex::_no_safepoint_check_flag); + // Check if _metaspace got allocated while we were waiting for this lock. + if ((metaspace = _metaspace) == NULL) { + if (this == the_null_class_loader_data()) { + assert (class_loader() == NULL, "Must be"); + metaspace = new Metaspace(_metaspace_lock, Metaspace::BootMetaspaceType); + } else if (is_anonymous()) { + if (class_loader() != NULL) { + log_trace(class, loader, data)("is_anonymous: %s", class_loader()->klass()->internal_name()); + } + metaspace = new Metaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType); + } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) { + if (class_loader() != NULL) { + log_trace(class, loader, data)("is_reflection: %s", class_loader()->klass()->internal_name()); + } + metaspace = new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType); + } else { + metaspace = new Metaspace(_metaspace_lock, Metaspace::StandardMetaspaceType); } - set_metaspace(new Metaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType)); - } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) { - if (class_loader() != NULL) { - log_trace(class, loader, data)("is_reflection: %s", class_loader()->klass()->internal_name()); - } - set_metaspace(new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType)); - } else { - set_metaspace(new Metaspace(_metaspace_lock, Metaspace::StandardMetaspaceType)); + // Ensure _metaspace is stable, since it is examined without a lock + OrderAccess::release_store_ptr(&_metaspace, metaspace); } } - return _metaspace; + return metaspace; } JNIHandleBlock* ClassLoaderData::handles() const { return _handles; } @@ -638,6 +656,7 @@ void ClassLoaderData::dump(outputStream * const out) { #endif // PRODUCT void ClassLoaderData::verify() { + assert_locked_or_safepoint(_metaspace_lock); oop cl = class_loader(); guarantee(this == class_loader_data(cl) || is_anonymous(), "Must be the same"); @@ -656,7 +675,8 @@ void ClassLoaderData::verify() { } bool ClassLoaderData::contains_klass(Klass* klass) { - for (Klass* k = _klasses; k != NULL; k = k->next_link()) { + // Lock-free access requires load_ptr_acquire + for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) { if (k == klass) return true; } return false; @@ -1046,6 +1066,7 @@ ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic // Find the first klass in the CLDG. while (cld != NULL) { + assert_locked_or_safepoint(cld->metaspace_lock()); klass = cld->_klasses; if (klass != NULL) { _next_klass = klass; @@ -1063,6 +1084,7 @@ Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass_in_cldg(Klass* klass) // No more klasses in the current CLD. Time to find a new CLD. ClassLoaderData* cld = klass->class_loader_data(); + assert_locked_or_safepoint(cld->metaspace_lock()); while (next == NULL) { cld = cld->next(); if (cld == NULL) { diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index b1a136a77c1..9fc9839b7cf 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -171,8 +171,8 @@ class ClassLoaderData : public CHeapObj { Dependencies _dependencies; // holds dependencies from this class loader // data to others. - Metaspace * _metaspace; // Meta-space where meta-data defined by the - // classes in the class loader are allocated. + Metaspace * volatile _metaspace; // Meta-space where meta-data defined by the + // classes in the class loader are allocated. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. bool _unloading; // true if this class loader goes away bool _is_anonymous; // if this CLD is for an anonymous class @@ -186,9 +186,9 @@ class ClassLoaderData : public CHeapObj { JNIHandleBlock* _handles; // Handles to constant pool arrays, Modules, etc, which // have the same life cycle of the corresponding ClassLoader. - Klass* _klasses; // The classes defined by the class loader. - PackageEntryTable* _packages; // The packages defined by the class loader. - ModuleEntryTable* _modules; // The modules defined by the class loader. + Klass* volatile _klasses; // The classes defined by the class loader. + PackageEntryTable* volatile _packages; // The packages defined by the class loader. + ModuleEntryTable* volatile _modules; // The modules defined by the class loader. // These method IDs are created for the class loader and set to NULL when the // class loader is unloaded. They are rarely freed, only for redefine classes @@ -216,8 +216,6 @@ class ClassLoaderData : public CHeapObj { ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies); ~ClassLoaderData(); - void set_metaspace(Metaspace* m) { _metaspace = m; } - JNIHandleBlock* handles() const; void set_handles(JNIHandleBlock* handles); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index b99c918996d..4c24c7349c0 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -848,7 +848,7 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, if (!ModuleEntryTable::javabase_defined()) { if (fixup_module_field_list() == NULL) { GrowableArray* list = - new (ResourceObj::C_HEAP, mtClass) GrowableArray(500, true); + new (ResourceObj::C_HEAP, mtModule) GrowableArray(500, true); set_fixup_module_field_list(list); } k->class_loader_data()->inc_keep_alive(); diff --git a/hotspot/src/share/vm/classfile/moduleEntry.cpp b/hotspot/src/share/vm/classfile/moduleEntry.cpp index f26b95ab690..6d31b8210b6 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.cpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp @@ -113,7 +113,7 @@ void ModuleEntry::add_read(ModuleEntry* m) { } else { if (_reads == NULL) { // Lazily create a module's reads list - _reads = new (ResourceObj::C_HEAP, mtClass)GrowableArray(MODULE_READS_SIZE, true); + _reads = new (ResourceObj::C_HEAP, mtModule)GrowableArray(MODULE_READS_SIZE, true); } _reads->append_if_missing(m); } @@ -159,7 +159,7 @@ void ModuleEntry::delete_reads() { } ModuleEntryTable::ModuleEntryTable(int table_size) - : Hashtable(table_size, sizeof(ModuleEntry)), _unnamed_module(NULL) + : Hashtable(table_size, sizeof(ModuleEntry)), _unnamed_module(NULL) { } @@ -228,7 +228,7 @@ ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle Symbol* version, Symbol* location, ClassLoaderData* loader_data) { assert_locked_or_safepoint(Module_lock); - ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtClass); + ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtModule); // Initialize everything BasicHashtable would entry->set_next(NULL); @@ -259,7 +259,7 @@ ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle void ModuleEntryTable::add_entry(int index, ModuleEntry* new_entry) { assert_locked_or_safepoint(Module_lock); - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable::add_entry(index, (HashtableEntry*)new_entry); } ModuleEntry* ModuleEntryTable::locked_create_entry_or_null(Handle module_handle, diff --git a/hotspot/src/share/vm/classfile/moduleEntry.hpp b/hotspot/src/share/vm/classfile/moduleEntry.hpp index 87accbeab41..9b68c01d424 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.hpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp @@ -49,7 +49,7 @@ class ModuleClosure; // // The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either // data structure. -class ModuleEntry : public HashtableEntry { +class ModuleEntry : public HashtableEntry { private: jobject _module; // java.lang.reflect.Module jobject _pd; // java.security.ProtectionDomain, cached @@ -127,10 +127,10 @@ public: } ModuleEntry* next() const { - return (ModuleEntry*)HashtableEntry::next(); + return (ModuleEntry*)HashtableEntry::next(); } ModuleEntry** next_addr() { - return (ModuleEntry**)HashtableEntry::next_addr(); + return (ModuleEntry**)HashtableEntry::next_addr(); } // iteration support for readability @@ -166,7 +166,7 @@ class ModuleClosure: public StackObj { // // The ModuleEntryTable's lookup is lock free. // -class ModuleEntryTable : public Hashtable { +class ModuleEntryTable : public Hashtable { friend class VMStructs; public: enum Constants { @@ -181,10 +181,10 @@ private: Symbol* location, ClassLoaderData* class_loader); void add_entry(int index, ModuleEntry* new_entry); - int entry_size() const { return BasicHashtable::entry_size(); } + int entry_size() const { return BasicHashtable::entry_size(); } ModuleEntry** bucket_addr(int i) { - return (ModuleEntry**)Hashtable::bucket_addr(i); + return (ModuleEntry**)Hashtable::bucket_addr(i); } static unsigned int compute_hash(Symbol* name) { return ((name == NULL) ? 0 : (unsigned int)(name->identity_hash())); } @@ -195,7 +195,7 @@ public: ~ModuleEntryTable(); ModuleEntry* bucket(int i) { - return (ModuleEntry*)Hashtable::bucket(i); + return (ModuleEntry*)Hashtable::bucket(i); } // Create module in loader's module entry table, if already exists then diff --git a/hotspot/src/share/vm/classfile/modules.cpp b/hotspot/src/share/vm/classfile/modules.cpp index 7c510bc9315..313310047b3 100644 --- a/hotspot/src/share/vm/classfile/modules.cpp +++ b/hotspot/src/share/vm/classfile/modules.cpp @@ -145,7 +145,7 @@ static void add_to_exploded_build_list(char *module_name, TRAPS) { const char* home = Arguments::get_java_home(); size_t len = strlen(home) + module_len + 32; - char* path = NEW_C_HEAP_ARRAY(char, len, mtInternal); + char* path = NEW_C_HEAP_ARRAY(char, len, mtModule); jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name); struct stat st; // See if exploded module path exists @@ -237,35 +237,40 @@ static void define_javabase_module(jobject module, jstring version, // Ensure java.base's ModuleEntry has been created assert(ModuleEntryTable::javabase_module() != NULL, "No ModuleEntry for java.base"); + bool duplicate_javabase = false; { MutexLocker m1(Module_lock, THREAD); if (ModuleEntryTable::javabase_defined()) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "Module java.base is already defined"); - } + duplicate_javabase = true; + } else { - // Verify that all java.base packages created during bootstrapping are in - // pkg_list. If any are not in pkg_list, than a non-java.base class was - // loaded erroneously pre java.base module definition. - package_table->verify_javabase_packages(pkg_list); + // Verify that all java.base packages created during bootstrapping are in + // pkg_list. If any are not in pkg_list, than a non-java.base class was + // loaded erroneously pre java.base module definition. + package_table->verify_javabase_packages(pkg_list); - // loop through and add any new packages for java.base - PackageEntry* pkg; - for (int x = 0; x < pkg_list->length(); x++) { - // Some of java.base's packages were added early in bootstrapping, ignore duplicates. - if (package_table->lookup_only(pkg_list->at(x)) == NULL) { - pkg = package_table->locked_create_entry_or_null(pkg_list->at(x), ModuleEntryTable::javabase_module()); - assert(pkg != NULL, "Unable to create a java.base package entry"); + // loop through and add any new packages for java.base + PackageEntry* pkg; + for (int x = 0; x < pkg_list->length(); x++) { + // Some of java.base's packages were added early in bootstrapping, ignore duplicates. + if (package_table->lookup_only(pkg_list->at(x)) == NULL) { + pkg = package_table->locked_create_entry_or_null(pkg_list->at(x), ModuleEntryTable::javabase_module()); + assert(pkg != NULL, "Unable to create a java.base package entry"); + } + // Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of + // the Symbol* that was created above for each package. The refcount was incremented + // by SymbolTable::new_symbol and as well by the PackageEntry creation. + pkg_list->at(x)->decrement_refcount(); } - // Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of - // the Symbol* that was created above for each package. The refcount was incremented - // by SymbolTable::new_symbol and as well by the PackageEntry creation. - pkg_list->at(x)->decrement_refcount(); - } - // Finish defining java.base's ModuleEntry - ModuleEntryTable::finalize_javabase(module_handle, version_symbol, location_symbol); + // Finish defining java.base's ModuleEntry + ModuleEntryTable::finalize_javabase(module_handle, version_symbol, location_symbol); + } + } + if (duplicate_javabase) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Module java.base is already defined"); } log_debug(modules)("define_javabase_module(): Definition of module: java.base," diff --git a/hotspot/src/share/vm/classfile/packageEntry.cpp b/hotspot/src/share/vm/classfile/packageEntry.cpp index ec6d4d08428..b7d18756fe1 100644 --- a/hotspot/src/share/vm/classfile/packageEntry.cpp +++ b/hotspot/src/share/vm/classfile/packageEntry.cpp @@ -34,15 +34,13 @@ #include "utilities/hashtable.inline.hpp" #include "utilities/ostream.hpp" -// Return true if this package is exported to m. +// Returns true if this package specifies m as a qualified export, including through an unnamed export bool PackageEntry::is_qexported_to(ModuleEntry* m) const { assert(m != NULL, "No module to lookup in this package's qualified exports list"); MutexLocker m1(Module_lock); - if (!_is_exported) { - return false; - } else if (_is_exported_allUnnamed && !m->is_named()) { + if (is_exported_allUnnamed() && !m->is_named()) { return true; - } else if (_qualified_exports == NULL) { + } else if (!has_qual_exports_list()) { return false; } else { return _qualified_exports->contains(m); @@ -52,17 +50,16 @@ bool PackageEntry::is_qexported_to(ModuleEntry* m) const { // Add a module to the package's qualified export list. void PackageEntry::add_qexport(ModuleEntry* m) { assert_locked_or_safepoint(Module_lock); - assert(_is_exported == true, "Adding a qualified export to a package that is not exported"); - if (_qualified_exports == NULL) { + if (!has_qual_exports_list()) { // Lazily create a package's qualified exports list. // Initial size is small, do not anticipate export lists to be large. _qualified_exports = - new (ResourceObj::C_HEAP, mtClass) GrowableArray(QUAL_EXP_SIZE, true); + new (ResourceObj::C_HEAP, mtModule) GrowableArray(QUAL_EXP_SIZE, true); } _qualified_exports->append_if_missing(m); } -// Set the package's exported state based on the value of the ModuleEntry. +// Set the package's exported states based on the value of the ModuleEntry. void PackageEntry::set_exported(ModuleEntry* m) { MutexLocker m1(Module_lock); if (is_unqual_exported()) { @@ -73,7 +70,7 @@ void PackageEntry::set_exported(ModuleEntry* m) { if (m == NULL) { // NULL indicates the package is being unqualifiedly exported - if (_is_exported && _qualified_exports != NULL) { + if (has_qual_exports_list()) { // Legit to transition a package from being qualifiedly exported // to unqualified. Clean up the qualified lists at the next // safepoint. @@ -85,11 +82,17 @@ void PackageEntry::set_exported(ModuleEntry* m) { } else { // Add the exported module - _is_exported = true; add_qexport(m); } } +void PackageEntry::set_is_exported_allUnnamed() { + MutexLocker m1(Module_lock); + if (!is_unqual_exported()) { + _is_exported_allUnnamed = true; + } +} + // Remove dead module entries within the package's exported list. void PackageEntry::purge_qualified_exports() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); @@ -124,7 +127,7 @@ void PackageEntry::delete_qualified_exports() { } PackageEntryTable::PackageEntryTable(int table_size) - : Hashtable(table_size, sizeof(PackageEntry)) + : Hashtable(table_size, sizeof(PackageEntry)) { } @@ -155,7 +158,7 @@ PackageEntryTable::~PackageEntryTable() { PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) { assert_locked_or_safepoint(Module_lock); - PackageEntry* entry = (PackageEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtClass); + PackageEntry* entry = (PackageEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtModule); // Initialize everything BasicHashtable would entry->set_next(NULL); @@ -170,7 +173,7 @@ PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, Modu if (!module->is_named()) { // Set the exported state to true because all packages // within the unnamed module are unqualifiedly exported - entry->set_exported(true); + entry->set_unqual_exported(); } entry->set_module(module); return entry; @@ -178,7 +181,7 @@ PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, Modu void PackageEntryTable::add_entry(int index, PackageEntry* new_entry) { assert_locked_or_safepoint(Module_lock); - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable::add_entry(index, (HashtableEntry*)new_entry); } // Create package in loader's package entry table and return the entry. @@ -248,6 +251,20 @@ void PackageEntryTable::verify_javabase_packages(GrowableArray *pkg_lis } +// iteration of qualified exports +void PackageEntry::package_exports_do(ModuleClosure* const f) { + assert_locked_or_safepoint(Module_lock); + assert(f != NULL, "invariant"); + + if (has_qual_exports_list()) { + int qe_len = _qualified_exports->length(); + + for (int i = 0; i < qe_len; ++i) { + f->do_module(_qualified_exports->at(i)); + } + } +} + // Remove dead entries from all packages' exported list void PackageEntryTable::purge_all_package_exports() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); @@ -281,10 +298,10 @@ void PackageEntryTable::print(outputStream* st) { void PackageEntry::print(outputStream* st) { ResourceMark rm; st->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index " - INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT, + INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next "PTR_FORMAT, p2i(this), name()->as_C_string(), (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE), - _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next())); + _classpath_index, _is_exported_unqualified, _is_exported_allUnnamed, p2i(next())); } void PackageEntryTable::verify() { @@ -305,17 +322,3 @@ void PackageEntryTable::verify() { void PackageEntry::verify() { guarantee(name() != NULL, "A package entry must have a corresponding symbol name."); } - -// iteration of qualified exports -void PackageEntry::package_exports_do(ModuleClosure* const f) { - assert_locked_or_safepoint(Module_lock); - assert(f != NULL, "invariant"); - - if (is_qual_exported()) { - int qe_len = _qualified_exports->length(); - - for (int i = 0; i < qe_len; ++i) { - f->do_module(_qualified_exports->at(i)); - } - } -} diff --git a/hotspot/src/share/vm/classfile/packageEntry.hpp b/hotspot/src/share/vm/classfile/packageEntry.hpp index 00b7b9d160f..7e19908af07 100644 --- a/hotspot/src/share/vm/classfile/packageEntry.hpp +++ b/hotspot/src/share/vm/classfile/packageEntry.hpp @@ -34,20 +34,36 @@ // A PackageEntry basically represents a Java package. It contains: // - Symbol* containing the package's name. // - ModuleEntry* for this package's containing module. -// - a flag indicating if package is exported, either qualifiedly or -// unqualifiedly. +// - a flag indicating if package is exported unqualifiedly // - a flag indicating if this package is exported to all unnamed modules. // - a growable array containing other module entries that this // package is exported to. // -// Packages that are: -// - not exported: _qualified_exports = NULL && _is_exported is false -// - qualified exports: (_qualified_exports != NULL || _is_exported_allUnnamed is true) && _is_exported is true -// - unqualified exports: (_qualified_exports = NULL && _is_exported_allUnnamed is false) && _is_exported is true +// Packages can be exported in the following 3 ways: +// - not exported: the package has not been explicitly qualified to a +// particular module nor has it been specified to be +// unqualifiedly exported to all modules. If all states +// of exportedness are false, the package is considered +// not exported. +// - qualified exports: the package has been explicitly qualified to at least +// one particular module or has been qualifiedly exported +// to all unnamed modules. +// Note: _is_exported_allUnnamed is a form of a qualified +// export. It is equivalent to the package being +// explicitly exported to all current and future unnamed modules. +// - unqualified exports: the package is exported to all modules. +// +// A package can transition from: +// - being not exported, to being exported either in a qualified or unqualified manner +// - being qualifiedly exported, to unqualifiedly exported. Its exported scope is widened. +// +// A package cannot transition from: +// - being unqualifiedly exported, to exported qualifiedly to a specific module. +// This transition attempt is silently ignored in set_exported. // // The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either // data structure. -class PackageEntry : public HashtableEntry { +class PackageEntry : public HashtableEntry { private: ModuleEntry* _module; // Used to indicate for packages with classes loaded by the boot loader that @@ -55,7 +71,7 @@ private: // loaded by the boot loader from -Xbootclasspath/a in an unnamed module, it // indicates from which class path entry. s2 _classpath_index; - bool _is_exported; + bool _is_exported_unqualified; bool _is_exported_allUnnamed; GrowableArray* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint GrowableArray* _qualified_exports; @@ -68,7 +84,7 @@ public: void init() { _module = NULL; _classpath_index = -1; - _is_exported = false; + _is_exported_unqualified = false; _is_exported_allUnnamed = false; _exported_pending_delete = NULL; _qualified_exports = NULL; @@ -83,34 +99,41 @@ public: void set_module(ModuleEntry* m) { _module = m; } // package's export state - bool is_exported() const { return _is_exported; } // qualifiedly or unqualifiedly exported + bool is_exported() const { // qualifiedly or unqualifiedly exported + return (is_unqual_exported() || has_qual_exports_list() || is_exported_allUnnamed()); + } + // Returns true if the package has any explicit qualified exports or is exported to all unnamed bool is_qual_exported() const { - return (_is_exported && (_qualified_exports != NULL || _is_exported_allUnnamed)); + return (has_qual_exports_list() || is_exported_allUnnamed()); + } + // Returns true if there are any explicit qualified exports + bool has_qual_exports_list() const { + assert(!(_qualified_exports != NULL && _is_exported_unqualified), + "_qualified_exports set at same time as _is_exported_unqualified"); + return (_qualified_exports != NULL); + } + bool is_exported_allUnnamed() const { + assert(!(_is_exported_allUnnamed && _is_exported_unqualified), + "_is_exported_allUnnamed set at same time as _is_exported_unqualified"); + return _is_exported_allUnnamed; } bool is_unqual_exported() const { - return (_is_exported && (_qualified_exports == NULL && !_is_exported_allUnnamed)); + assert(!(_qualified_exports != NULL && _is_exported_unqualified), + "_qualified_exports set at same time as _is_exported_unqualified"); + assert(!(_is_exported_allUnnamed && _is_exported_unqualified), + "_is_exported_allUnnamed set at same time as _is_exported_unqualified"); + return _is_exported_unqualified; } void set_unqual_exported() { - _is_exported = true; + _is_exported_unqualified = true; _is_exported_allUnnamed = false; _qualified_exports = NULL; } bool exported_pending_delete() const { return (_exported_pending_delete != NULL); } - void set_exported(bool e) { _is_exported = e; } void set_exported(ModuleEntry* m); - void set_is_exported_allUnnamed() { - if (!is_unqual_exported()) { - _is_exported_allUnnamed = true; - _is_exported = true; - } - } - bool is_exported_allUnnamed() const { - assert(_is_exported || !_is_exported_allUnnamed, - "is_allUnnamed set without is_exported being set"); - return _is_exported_allUnnamed; - } + void set_is_exported_allUnnamed(); void set_classpath_index(s2 classpath_index) { _classpath_index = classpath_index; @@ -122,18 +145,18 @@ public: // returns true if the package is defined in the unnamed module bool in_unnamed_module() const { return !_module->is_named(); } - // returns true if the package specifies m as a qualified export + // returns true if the package specifies m as a qualified export, including through an unnamed export bool is_qexported_to(ModuleEntry* m) const; // add the module to the package's qualified exports void add_qexport(ModuleEntry* m); PackageEntry* next() const { - return (PackageEntry*)HashtableEntry::next(); + return (PackageEntry*)HashtableEntry::next(); } PackageEntry** next_addr() { - return (PackageEntry**)HashtableEntry::next_addr(); + return (PackageEntry**)HashtableEntry::next_addr(); } // iteration of qualified exports @@ -153,7 +176,7 @@ public: // by a particular class loader. Each package is represented as a PackageEntry node. // The PackageEntryTable's lookup is lock free. // -class PackageEntryTable : public Hashtable { +class PackageEntryTable : public Hashtable { friend class VMStructs; public: enum Constants { @@ -164,10 +187,10 @@ private: PackageEntry* new_entry(unsigned int hash, Symbol* name, ModuleEntry* module); void add_entry(int index, PackageEntry* new_entry); - int entry_size() const { return BasicHashtable::entry_size(); } + int entry_size() const { return BasicHashtable::entry_size(); } PackageEntry** bucket_addr(int i) { - return (PackageEntry**)Hashtable::bucket_addr(i); + return (PackageEntry**)Hashtable::bucket_addr(i); } static unsigned int compute_hash(Symbol* name) { return (unsigned int)(name->identity_hash()); } @@ -178,7 +201,7 @@ public: ~PackageEntryTable(); PackageEntry* bucket(int i) { - return (PackageEntry*)Hashtable::bucket(i); + return (PackageEntry*)Hashtable::bucket(i); } // Create package in loader's package entry table and return the entry. diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 7dcd740f8a5..28b79768fa5 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1336,9 +1336,12 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, return nh; } - // Found the class, now load the superclass and interfaces. If they - // are shared, add them to the main system dictionary and reset - // their hierarchy references (supers, subs, and interfaces). + // Resolve the superclass and interfaces. They must be the same + // as in dump time, because the layout of depends on + // the specific layout of ik->super() and ik->local_interfaces(). + // + // If unexpected superclass or interfaces are found, we cannot + // load from the shared archive. if (ik->super() != NULL) { Symbol* cn = ik->super()->name(); @@ -1348,6 +1351,8 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, // The dynamically resolved super class is not the same as the one we used during dump time, // so we cannot use ik. return nh; + } else { + assert(s->is_shared(), "must be"); } } @@ -1366,6 +1371,8 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, // The dynamically resolved interface class is not the same as the one we used during dump time, // so we cannot use ik. return nh; + } else { + assert(i->is_shared(), "must be"); } } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index ca637011c4d..3626d881736 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -420,9 +420,9 @@ public: // Initialization static void initialize(TRAPS); - // Fast access to commonly used classes (preloaded) + // Checked fast access to commonly used classes - mostly preloaded static InstanceKlass* check_klass(InstanceKlass* k) { - assert(k != NULL, "preloaded klass not initialized"); + assert(k != NULL, "klass not loaded"); return k; } diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 86e88d4b516..11290f2bf76 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -386,15 +386,16 @@ class Bytecodes: AllStatic { static Code non_breakpoint_code_at(const Method* method, address bcp); // Bytecode attributes - static bool is_defined (int code) { return 0 <= code && code < number_of_codes && flags(code, false) != 0; } + static bool is_valid (int code) { return 0 <= code && code < number_of_codes; } + static bool is_defined (int code) { return is_valid(code) && flags(code, false) != 0; } static bool wide_is_defined(int code) { return is_defined(code) && flags(code, true) != 0; } static const char* name (Code code) { check(code); return _name [code]; } static BasicType result_type (Code code) { check(code); return _result_type [code]; } static int depth (Code code) { check(code); return _depth [code]; } // Note: Length functions must return <=0 for invalid bytecodes. // Calling check(code) in length functions would throw an unwanted assert. - static int length_for (Code code) { /*no check*/ return _lengths [code] & 0xF; } - static int wide_length_for(Code code) { /*no check*/ return _lengths [code] >> 4; } + static int length_for (Code code) { return is_valid(code) ? _lengths[code] & 0xF : -1; } + static int wide_length_for(Code code) { return is_valid(code) ? _lengths[code] >> 4 : -1; } static bool can_trap (Code code) { check(code); return has_all_flags(code, _bc_can_trap, false); } static Code java_code (Code code) { check(code); return _java_code [code]; } static bool can_rewrite (Code code) { check(code); return has_all_flags(code, _bc_can_rewrite, false); } diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 0544e1ca476..f0337146a82 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -231,6 +231,7 @@ LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) { // Get name, signature, and static klass _name = pool->name_ref_at(index); _signature = pool->signature_ref_at(index); + _tag = pool->tag_ref_at(index); _current_klass = KlassHandle(THREAD, pool->pool_holder()); // Coming from the constant pool always checks access @@ -573,7 +574,7 @@ methodHandle LinkResolver::resolve_method_statically(Bytecodes::Code code, Symbol* method_signature = pool->signature_ref_at(index); KlassHandle current_klass(THREAD, pool->pool_holder()); LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass); - return resolve_method(link_info, /*require_methodref*/false, THREAD); + return resolve_method(link_info, code, THREAD); } LinkInfo link_info(pool, index, CHECK_NULL); @@ -591,9 +592,9 @@ methodHandle LinkResolver::resolve_method_statically(Bytecodes::Code code, if (code == Bytecodes::_invokeinterface) { return resolve_interface_method(link_info, code, THREAD); } else if (code == Bytecodes::_invokevirtual) { - return resolve_method(link_info, /*require_methodref*/true, THREAD); + return resolve_method(link_info, code, THREAD); } else if (!resolved_klass->is_interface()) { - return resolve_method(link_info, /*require_methodref*/false, THREAD); + return resolve_method(link_info, code, THREAD); } else { return resolve_interface_method(link_info, code, THREAD); } @@ -663,13 +664,13 @@ void LinkResolver::check_field_loader_constraints(Symbol* field, Symbol* sig, } methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, - bool require_methodref, TRAPS) { + Bytecodes::Code code, TRAPS) { Handle nested_exception; KlassHandle resolved_klass = link_info.resolved_klass(); - // 1. check if methodref required, that resolved_klass is not interfacemethodref - if (require_methodref && resolved_klass->is_interface()) { + // 1. For invokevirtual, cannot call an interface method + if (code == Bytecodes::_invokevirtual && resolved_klass->is_interface()) { ResourceMark rm(THREAD); char buf[200]; jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", @@ -677,11 +678,20 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } - // 2. lookup method in resolved klass and its super klasses + // 2. check constant pool tag for called method - must be JVM_CONSTANT_Methodref + if (!link_info.tag().is_invalid() && !link_info.tag().is_method()) { + ResourceMark rm(THREAD); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Method %s must be Methodref constant", link_info.method_string()); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + } + + + // 3. lookup method in resolved klass and its super klasses methodHandle resolved_method = lookup_method_in_klasses(link_info, true, false, CHECK_NULL); + // 4. lookup method in all the interfaces implemented by the resolved klass if (resolved_method.is_null() && !resolved_klass->is_array_klass()) { // not found in the class hierarchy - // 3. lookup method in all the interfaces implemented by the resolved klass resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL); if (resolved_method.is_null()) { @@ -694,8 +704,8 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, } } + // 5. method lookup failed if (resolved_method.is_null()) { - // 4. method lookup failed ResourceMark rm(THREAD); THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(), Method::name_and_sig_as_C_string(resolved_klass(), @@ -704,7 +714,7 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, nested_exception, NULL); } - // 5. access checks, access checking may be turned off when calling from within the VM. + // 6. access checks, access checking may be turned off when calling from within the VM. KlassHandle current_klass = link_info.current_klass(); if (link_info.check_access()) { assert(current_klass.not_null() , "current_klass should not be null"); @@ -766,6 +776,14 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } + // check constant pool tag for called method - must be JVM_CONSTANT_InterfaceMethodref + if (!link_info.tag().is_invalid() && !link_info.tag().is_interface_method()) { + ResourceMark rm(THREAD); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Method %s must be InterfaceMethodref constant", link_info.method_string()); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + } + // lookup method in this interface or its super, java.lang.Object // JDK8: also look for static methods methodHandle resolved_method = lookup_method_in_klasses(link_info, false, true, CHECK_NULL); @@ -948,19 +966,18 @@ void LinkResolver::resolve_static_call(CallInfo& result, methodHandle resolved_method = linktime_resolve_static_method(link_info, CHECK); // The resolved class can change as a result of this resolution. - KlassHandle resolved_klass = KlassHandle(THREAD, resolved_method->method_holder()); + KlassHandle resolved_klass(THREAD, resolved_method->method_holder()); - Method* save_resolved_method = resolved_method(); // Initialize klass (this should only happen if everything is ok) if (initialize_class && resolved_klass->should_be_initialized()) { resolved_klass->initialize(CHECK); - // Use updated LinkInfo (to reresolve with resolved_klass as method_holder?) + // Use updated LinkInfo to reresolve with resolved method holder LinkInfo new_info(resolved_klass, link_info.name(), link_info.signature(), - link_info.current_klass(), link_info.check_access()); + link_info.current_klass(), + link_info.check_access() ? LinkInfo::needs_access_check : LinkInfo::skip_access_check); resolved_method = linktime_resolve_static_method(new_info, CHECK); } - assert(save_resolved_method == resolved_method(), "does this change?"); // setup result result.set_static(resolved_klass, resolved_method, CHECK); } @@ -971,7 +988,7 @@ methodHandle LinkResolver::linktime_resolve_static_method(const LinkInfo& link_i KlassHandle resolved_klass = link_info.resolved_klass(); methodHandle resolved_method; if (!resolved_klass->is_interface()) { - resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL); + resolved_method = resolve_method(link_info, Bytecodes::_invokestatic, CHECK_NULL); } else { resolved_method = resolve_interface_method(link_info, Bytecodes::_invokestatic, CHECK_NULL); } @@ -1014,7 +1031,7 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_ methodHandle resolved_method; if (!resolved_klass->is_interface()) { - resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL); + resolved_method = resolve_method(link_info, Bytecodes::_invokespecial, CHECK_NULL); } else { resolved_method = resolve_interface_method(link_info, Bytecodes::_invokespecial, CHECK_NULL); } @@ -1164,7 +1181,7 @@ void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHand methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_info, TRAPS) { // normal method resolution - methodHandle resolved_method = resolve_method(link_info, /*require_methodref*/true, CHECK_NULL); + methodHandle resolved_method = resolve_method(link_info, Bytecodes::_invokevirtual, CHECK_NULL); assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); @@ -1173,6 +1190,7 @@ methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_ KlassHandle resolved_klass = link_info.resolved_klass(); KlassHandle current_klass = link_info.current_klass(); + // This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method if (resolved_klass->is_interface() && resolved_method->is_private()) { ResourceMark rm(THREAD); char buf[200]; @@ -1482,7 +1500,7 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle& recv, KlassHandle defc = attached_method->method_holder(); Symbol* name = attached_method->name(); Symbol* type = attached_method->signature(); - LinkInfo link_info(defc, name, type, KlassHandle(), /*check_access=*/false); + LinkInfo link_info(defc, name, type); switch(byte) { case Bytecodes::_invokevirtual: resolve_virtual_call(result, recv, recv->klass(), link_info, diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index b319be9b3b6..263365b56bf 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -137,20 +137,35 @@ class LinkInfo : public StackObj { KlassHandle _resolved_klass; // class that the constant pool entry points to KlassHandle _current_klass; // class that owns the constant pool bool _check_access; + constantTag _tag; public: + enum AccessCheck { + needs_access_check, + skip_access_check + }; + LinkInfo(const constantPoolHandle& pool, int index, TRAPS); + // Condensed information from other call sites within the vm. - LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature, - KlassHandle current_klass, bool check_access = true) : + LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature, KlassHandle current_klass, + AccessCheck check_access = needs_access_check, + constantTag tag = JVM_CONSTANT_Invalid) : _resolved_klass(resolved_klass), _name(name), _signature(signature), _current_klass(current_klass), - _check_access(check_access) {} + _check_access(check_access == needs_access_check), _tag(tag) {} + + // Case where we just find the method and don't check access against the current class + LinkInfo(KlassHandle resolved_klass, Symbol*name, Symbol* signature) : + _resolved_klass(resolved_klass), + _name(name), _signature(signature), _current_klass(NULL), + _check_access(false), _tag(JVM_CONSTANT_Invalid) {} // accessors Symbol* name() const { return _name; } Symbol* signature() const { return _signature; } KlassHandle resolved_klass() const { return _resolved_klass; } KlassHandle current_klass() const { return _current_klass; } + constantTag tag() const { return _tag; } bool check_access() const { return _check_access; } char* method_string() const; @@ -192,7 +207,7 @@ class LinkResolver: AllStatic { KlassHandle sel_klass, TRAPS); static methodHandle resolve_interface_method(const LinkInfo& link_info, Bytecodes::Code code, TRAPS); - static methodHandle resolve_method (const LinkInfo& link_info, bool require_methodref, TRAPS); + static methodHandle resolve_method (const LinkInfo& link_info, Bytecodes::Code code, TRAPS); static methodHandle linktime_resolve_static_method (const LinkInfo& link_info, TRAPS); static methodHandle linktime_resolve_special_method (const LinkInfo& link_info, TRAPS); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index bc56b370358..63387feb6fb 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -661,8 +661,7 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t Symbol* h_name = method->name(); Symbol* h_signature = method->signature(); - bool check_access = true; - LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access); + LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass); methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp index 502b2f7c011..994220ff006 100644 --- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp @@ -286,11 +286,12 @@ methodHandle JVMCIEnv::lookup_method(instanceKlassHandle h_accessor, instanceKlassHandle h_holder, Symbol* name, Symbol* sig, - Bytecodes::Code bc) { + Bytecodes::Code bc, + constantTag tag) { JVMCI_EXCEPTION_CONTEXT; LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL)); methodHandle dest_method; - LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true); + LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag); switch (bc) { case Bytecodes::_invokestatic: dest_method = @@ -363,7 +364,8 @@ methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool, if (holder_is_accessible) { // Our declared holder is loaded. instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder); - methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc); + constantTag tag = cpool->tag_ref_at(index); + methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc, tag); if (!m.is_null() && (bc == Bytecodes::_invokestatic ? InstanceKlass::cast(m->method_holder())->is_not_initialized() diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp index 833074326bf..2c884494db8 100644 --- a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,7 +130,8 @@ private: instanceKlassHandle holder, Symbol* name, Symbol* sig, - Bytecodes::Code bc); + Bytecodes::Code bc, + constantTag tag); private: diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index f09b3b56596..922d4b53c06 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -415,7 +415,9 @@ void LogConfiguration::describe_available(outputStream* out){ void LogConfiguration::describe_current_configuration(outputStream* out){ out->print_cr("Log output configuration:"); for (size_t i = 0; i < _n_outputs; i++) { - out->print("#" SIZE_FORMAT ": %s %s ", i, _outputs[i]->name(), _outputs[i]->config_string()); + out->print("#" SIZE_FORMAT ": %s ", i, _outputs[i]->name()); + out->print_raw(_outputs[i]->config_string()); + out->print(" "); char delimiter[2] = {0}; for (size_t d = 0; d < LogDecorators::Count; d++) { LogDecorators::Decorator decorator = static_cast(d); diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index ec0e53977d6..5d9e7c830f6 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,8 +144,9 @@ enum MemoryType { mtTracing = 0x0E, // memory used for Tracing mtLogging = 0x0F, // memory for logging mtArguments = 0x10, // memory for argument processing - mtNone = 0x11, // undefined - mt_number_of_types = 0x12 // number of memory types (mtDontTrack + mtModule = 0x11, // memory for module processing + mtNone = 0x12, // undefined + mt_number_of_types = 0x13 // number of memory types (mtDontTrack // is not included as validate type) }; diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index b975e9e1327..02f025a9630 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -191,7 +191,12 @@ static void rewrite_nofast_bytecode(Method* method) { case Bytecodes::_getfield: *bcs.bcp() = Bytecodes::_nofast_getfield; break; case Bytecodes::_putfield: *bcs.bcp() = Bytecodes::_nofast_putfield; break; case Bytecodes::_aload_0: *bcs.bcp() = Bytecodes::_nofast_aload_0; break; - case Bytecodes::_iload: *bcs.bcp() = Bytecodes::_nofast_iload; break; + case Bytecodes::_iload: { + if (!bcs.is_wide()) { + *bcs.bcp() = Bytecodes::_nofast_iload; + } + break; + } default: break; } } diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index a291dc5d3f8..29110089d3b 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -417,6 +417,19 @@ int ConstantPool::impl_name_and_type_ref_index_at(int which, bool uncached) { return extract_high_short_from_int(ref_index); } +constantTag ConstantPool::impl_tag_ref_at(int which, bool uncached) { + int pool_index = which; + if (!uncached && cache() != NULL) { + if (ConstantPool::is_invokedynamic_index(which)) { + // Invokedynamic index is index into resolved_references + pool_index = invokedynamic_cp_cache_entry_at(which)->constant_pool_index(); + } else { + // change byte-ordering and go via cache + pool_index = remap_instruction_operand_from_cache(which); + } + } + return tag_at(pool_index); +} int ConstantPool::impl_klass_ref_index_at(int which, bool uncached) { guarantee(!ConstantPool::is_invokedynamic_index(which), @@ -672,6 +685,7 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in int callee_index = this_cp->method_handle_klass_index_at(index); Symbol* name = this_cp->method_handle_name_ref_at(index); Symbol* signature = this_cp->method_handle_signature_ref_at(index); + constantTag m_tag = this_cp->tag_at(this_cp->method_handle_index_at(index)); { ResourceMark rm(THREAD); log_debug(class, resolve)("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s", ref_kind, index, this_cp->method_handle_index_at(index), @@ -681,6 +695,15 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in { Klass* k = klass_at_impl(this_cp, callee_index, true, CHECK_NULL); callee = KlassHandle(THREAD, k); } + if ((callee->is_interface() && m_tag.is_method()) || + (!callee->is_interface() && m_tag.is_interface_method())) { + ResourceMark rm(THREAD); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Inconsistent constant data for %s.%s%s at index %d", + callee->name()->as_C_string(), name->as_C_string(), signature->as_C_string(), index); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + } + KlassHandle klass(THREAD, this_cp->pool_holder()); Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind, callee, name, signature, diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 75bca62917b..38a71f525d2 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -643,6 +643,8 @@ class ConstantPool : public Metadata { int remap_instruction_operand_from_cache(int operand); // operand must be biased by CPCACHE_INDEX_TAG + constantTag tag_ref_at(int cp_cache_index) { return impl_tag_ref_at(cp_cache_index, false); } + // Lookup for entries consisting of (name_index, signature_index) int name_ref_index_at(int which_nt); // == low-order jshort of name_and_type_at(which_nt) int signature_ref_index_at(int which_nt); // == high-order jshort of name_and_type_at(which_nt) @@ -763,6 +765,7 @@ class ConstantPool : public Metadata { Symbol* impl_signature_ref_at(int which, bool uncached); int impl_klass_ref_index_at(int which, bool uncached); int impl_name_and_type_ref_index_at(int which, bool uncached); + constantTag impl_tag_ref_at(int which, bool uncached); // Used while constructing constant pool (only by ClassFileParser) jint klass_index_at(int which) { diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 074fc0039d0..02161471b01 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1104,21 +1104,21 @@ void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_k, TRAP void InstanceKlass::mask_for(const methodHandle& method, int bci, InterpreterOopMap* entry_for) { - // Dirty read, then double-check under a lock. - if (_oop_map_cache == NULL) { - // Otherwise, allocate a new one. + // Lazily create the _oop_map_cache at first request + // Lock-free access requires load_ptr_acquire. + OopMapCache* oop_map_cache = + static_cast(OrderAccess::load_ptr_acquire(&_oop_map_cache)); + if (oop_map_cache == NULL) { MutexLocker x(OopMapCacheAlloc_lock); - // First time use. Allocate a cache in C heap - if (_oop_map_cache == NULL) { - // Release stores from OopMapCache constructor before assignment - // to _oop_map_cache. C++ compilers on ppc do not emit the - // required memory barrier only because of the volatile - // qualifier of _oop_map_cache. - OrderAccess::release_store_ptr(&_oop_map_cache, new OopMapCache()); + // Check if _oop_map_cache was allocated while we were waiting for this lock + if ((oop_map_cache = _oop_map_cache) == NULL) { + oop_map_cache = new OopMapCache(); + // Ensure _oop_map_cache is stable, since it is examined without a lock + OrderAccess::release_store_ptr(&_oop_map_cache, oop_map_cache); } } - // _oop_map_cache is constant after init; lookup below does is own locking. - _oop_map_cache->lookup(method, bci, entry_for); + // _oop_map_cache is constant after init; lookup below does its own locking. + oop_map_cache->lookup(method, bci, entry_for); } diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 7b1782a2904..d21c0fa30e4 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -713,12 +713,16 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS TempNewSymbol type = lookup_signature(type_str(), (mh_invoke_id != vmIntrinsics::_none), CHECK_(empty)); if (type == NULL) return empty; // no such signature exists in the VM + LinkInfo::AccessCheck access_check = caller.not_null() ? + LinkInfo::needs_access_check : + LinkInfo::skip_access_check; + // Time to do the lookup. switch (flags & ALL_KINDS) { case IS_METHOD: { CallInfo result; - LinkInfo link_info(defc, name, type, caller, caller.not_null()); + LinkInfo link_info(defc, name, type, caller, access_check); { assert(!HAS_PENDING_EXCEPTION, ""); if (ref_kind == JVM_REF_invokeStatic) { @@ -755,7 +759,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS case IS_CONSTRUCTOR: { CallInfo result; - LinkInfo link_info(defc, name, type, caller, caller.not_null()); + LinkInfo link_info(defc, name, type, caller, access_check); { assert(!HAS_PENDING_EXCEPTION, ""); if (name == vmSymbols::object_initializer_name()) { @@ -776,7 +780,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS fieldDescriptor result; // find_field initializes fd if found { assert(!HAS_PENDING_EXCEPTION, ""); - LinkInfo link_info(defc, name, type, caller, /*check_access*/false); + LinkInfo link_info(defc, name, type, caller, LinkInfo::skip_access_check); LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD); if (HAS_PENDING_EXCEPTION) { return empty; diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 71116760c07..e129fbafc41 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -356,19 +356,6 @@ UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, return JNIHandles::make_local(env, v); } UNSAFE_END -UNSAFE_ENTRY(jclass, Unsafe_GetJavaMirror(JNIEnv *env, jobject unsafe, jlong metaspace_klass)) { - Klass* klass = (Klass*) (address) metaspace_klass; - - return (jclass) JNIHandles::make_local(klass->java_mirror()); -} UNSAFE_END - -UNSAFE_ENTRY(jlong, Unsafe_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject obj)) { - oop o = JNIHandles::resolve(obj); - jlong klass = (jlong) (address) o->klass(); - - return klass; -} UNSAFE_END - #ifndef SUPPORTS_NATIVE_CX8 // VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'. @@ -1152,8 +1139,6 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutObjectVolatile)}, {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)}, - {CC "getJavaMirror", CC "(" ADR ")" CLS, FN_PTR(Unsafe_GetJavaMirror)}, - {CC "getKlassPointer", CC "(" OBJ ")" ADR, FN_PTR(Unsafe_GetKlassPointer)}, DECLARE_GETPUTOOP(Boolean, Z), DECLARE_GETPUTOOP(Byte, B), diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index dc354b40ffb..a55fd6340c6 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -278,6 +278,49 @@ WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o, (size_t) magnitude, (size_t) iterations); WB_END +static const jint serial_code = 1; +static const jint parallel_code = 2; +static const jint cms_code = 4; +static const jint g1_code = 8; + +WB_ENTRY(jint, WB_CurrentGC(JNIEnv* env, jobject o, jobject obj)) + if (UseSerialGC) { + return serial_code; + } else if (UseParallelGC || UseParallelOldGC) { + return parallel_code; + } if (UseConcMarkSweepGC) { + return cms_code; + } else if (UseG1GC) { + return g1_code; + } + ShouldNotReachHere(); + return 0; +WB_END + +WB_ENTRY(jint, WB_AllSupportedGC(JNIEnv* env, jobject o, jobject obj)) +#if INCLUDE_ALL_GCS + return serial_code | parallel_code | cms_code | g1_code; +#else + return serial_code; +#endif // INCLUDE_ALL_GCS +WB_END + +WB_ENTRY(jboolean, WB_GCSelectedByErgo(JNIEnv* env, jobject o, jobject obj)) + if (UseSerialGC) { + return FLAG_IS_ERGO(UseSerialGC); + } else if (UseParallelGC) { + return FLAG_IS_ERGO(UseParallelGC); + } else if (UseParallelOldGC) { + return FLAG_IS_ERGO(UseParallelOldGC); + } else if (UseConcMarkSweepGC) { + return FLAG_IS_ERGO(UseConcMarkSweepGC); + } else if (UseG1GC) { + return FLAG_IS_ERGO(UseG1GC); + } + ShouldNotReachHere(); + return false; +WB_END + WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj)) oop p = JNIHandles::resolve(obj); #if INCLUDE_ALL_GCS @@ -1833,7 +1876,10 @@ static JNINativeMethod methods[] = { {CC"clearInlineCaches0", CC"(Z)V", (void*)&WB_ClearInlineCaches }, {CC"addCompilerDirective", CC"(Ljava/lang/String;)I", (void*)&WB_AddCompilerDirective }, - {CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective }, + {CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective }, + {CC"currentGC", CC"()I", (void*)&WB_CurrentGC}, + {CC"allSupportedGC", CC"()I", (void*)&WB_AllSupportedGC}, + {CC"gcSelectedByErgo", CC"()Z", (void*)&WB_GCSelectedByErgo}, }; #undef CC diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp index 686a2c566ab..34a0787eaac 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.cpp +++ b/hotspot/src/share/vm/runtime/javaCalls.cpp @@ -183,7 +183,7 @@ void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* CallInfo callinfo; Handle receiver = args->receiver(); KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass()); - LinkInfo link_info(spec_klass, name, signature, KlassHandle(), /*check_access*/false); + LinkInfo link_info(spec_klass, name, signature); LinkResolver::resolve_virtual_call( callinfo, receiver, recvrKlass, link_info, true, CHECK); methodHandle method = callinfo.selected_method(); @@ -220,7 +220,7 @@ void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spe void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { CallInfo callinfo; - LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false); + LinkInfo link_info(klass, name, signature); LinkResolver::resolve_special_call(callinfo, link_info, CHECK); methodHandle method = callinfo.selected_method(); assert(method.not_null(), "should have thrown exception"); @@ -255,7 +255,7 @@ void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle kla void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { CallInfo callinfo; - LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false); + LinkInfo link_info(klass, name, signature); LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK); methodHandle method = callinfo.selected_method(); assert(method.not_null(), "should have thrown exception"); diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index ec103436269..8acc60b24b2 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1336,12 +1336,10 @@ bool os::stack_shadow_pages_available(Thread *thread, const methodHandle& method const int framesize_in_bytes = Interpreter::size_top_interpreter_activation(method()) * wordSize; - assert((thread->stack_base() - thread->stack_size()) + - (JavaThread::stack_guard_zone_size() + - JavaThread::stack_shadow_zone_size() + framesize_in_bytes) == - ((JavaThread*)thread)->stack_overflow_limit() + framesize_in_bytes, "sanity"); + address limit = ((JavaThread*)thread)->stack_end() + + (JavaThread::stack_guard_zone_size() + JavaThread::stack_shadow_zone_size()); - return (sp > ((JavaThread*)thread)->stack_overflow_limit() + framesize_in_bytes); + return sp > (limit + framesize_in_bytes); } size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) { diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index f81deb6a374..867c831a165 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -998,7 +998,7 @@ static methodHandle resolve_interface_call(instanceKlassHandle klass, Symbol* signature = method->signature(); Symbol* name = method->name(); LinkResolver::resolve_interface_call(info, receiver, recv_klass, - LinkInfo(klass, name, signature, KlassHandle(), false), + LinkInfo(klass, name, signature), true, CHECK_(methodHandle())); return info.selected_method(); diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index a2e5a6e848b..46828d4cab2 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -1371,10 +1371,10 @@ class JavaThread: public Thread { // | reserved pages | // | | // -- <-- stack_reserved_zone_base() --- --- - // /|\ shadow + // /|\ shadow <-- stack_overflow_limit() (somewhere in here) // | zone // \|/ size - // some untouched memory --- <-- stack_overflow_limit() + // some untouched memory --- // // // -- @@ -1522,9 +1522,8 @@ class JavaThread: public Thread { address stack_overflow_limit() { return _stack_overflow_limit; } void set_stack_overflow_limit() { - _stack_overflow_limit = stack_end() + - (JavaThread::stack_guard_zone_size() + - JavaThread::stack_shadow_zone_size()); + _stack_overflow_limit = + stack_end() + MAX2(JavaThread::stack_guard_zone_size(), JavaThread::stack_shadow_zone_size()); } // Misc. accessors/mutators diff --git a/hotspot/src/share/vm/runtime/vm_operations.cpp b/hotspot/src/share/vm/runtime/vm_operations.cpp index 3ac2816775a..26a8cbe647b 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.cpp +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -201,10 +201,12 @@ void VM_Verify::doit() { } bool VM_PrintThreads::doit_prologue() { - assert(Thread::current()->is_Java_thread(), "just checking"); - // Make sure AbstractOwnableSynchronizer is loaded - java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(JavaThread::current()); + JavaThread* jt = JavaThread::current(); + java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(jt); + if (jt->has_pending_exception()) { + return false; + } // Get Heap_lock if concurrent locks will be dumped if (_print_concurrent_locks) { @@ -240,11 +242,13 @@ VM_FindDeadlocks::~VM_FindDeadlocks() { } bool VM_FindDeadlocks::doit_prologue() { - assert(Thread::current()->is_Java_thread(), "just checking"); - - // Load AbstractOwnableSynchronizer class if (_concurrent_locks) { - java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(JavaThread::current()); + // Make sure AbstractOwnableSynchronizer is loaded + JavaThread* jt = JavaThread::current(); + java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(jt); + if (jt->has_pending_exception()) { + return false; + } } return true; @@ -298,10 +302,12 @@ VM_ThreadDump::VM_ThreadDump(ThreadDumpResult* result, } bool VM_ThreadDump::doit_prologue() { - assert(Thread::current()->is_Java_thread(), "just checking"); - - // Load AbstractOwnableSynchronizer class before taking thread snapshots - java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(JavaThread::current()); + // Make sure AbstractOwnableSynchronizer is loaded + JavaThread* jt = JavaThread::current(); + java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(jt); + if (jt->has_pending_exception()) { + return false; + } if (_with_locked_synchronizers) { // Acquire Heap_lock to dump concurrent locks diff --git a/hotspot/src/share/vm/services/nmtCommon.cpp b/hotspot/src/share/vm/services/nmtCommon.cpp index 8633bbe301e..c1ec5c6971e 100644 --- a/hotspot/src/share/vm/services/nmtCommon.cpp +++ b/hotspot/src/share/vm/services/nmtCommon.cpp @@ -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 @@ -42,6 +42,7 @@ const char* NMTUtil::_memory_type_names[] = { "Tracing", "Logging", "Arguments", + "Module", "Unknown" }; diff --git a/hotspot/src/share/vm/services/virtualMemoryTracker.cpp b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp index 16f249b82e9..964af28bf5b 100644 --- a/hotspot/src/share/vm/services/virtualMemoryTracker.cpp +++ b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp @@ -23,7 +23,10 @@ */ #include "precompiled.hpp" +#include "runtime/atomic.inline.hpp" +#include "runtime/os.hpp" #include "runtime/threadCritical.hpp" +#include "services/memTracker.hpp" #include "services/virtualMemoryTracker.hpp" size_t VirtualMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(VirtualMemorySnapshot, size_t)]; @@ -52,46 +55,41 @@ bool ReservedMemoryRegion::add_committed_region(address addr, size_t size, const if (all_committed()) return true; CommittedMemoryRegion committed_rgn(addr, size, stack); - LinkedListNode* node = _committed_regions.find_node(committed_rgn); - if (node != NULL) { + LinkedListNode* node = _committed_regions.head(); + + while (node != NULL) { CommittedMemoryRegion* rgn = node->data(); if (rgn->same_region(addr, size)) { return true; } if (rgn->adjacent_to(addr, size)) { - // check if the next region covers this committed region, - // the regions may not be merged due to different call stacks - LinkedListNode* next = - node->next(); - if (next != NULL && next->data()->contain_region(addr, size)) { - if (next->data()->same_region(addr, size)) { - next->data()->set_call_stack(stack); - } - return true; - } - if (rgn->call_stack()->equals(stack)) { + // special case to expand prior region if there is no next region + LinkedListNode* next = node->next(); + if (next == NULL && rgn->call_stack()->equals(stack)) { VirtualMemorySummary::record_uncommitted_memory(rgn->size(), flag()); // the two adjacent regions have the same call stack, merge them rgn->expand_region(addr, size); VirtualMemorySummary::record_committed_memory(rgn->size(), flag()); return true; } - VirtualMemorySummary::record_committed_memory(size, flag()); - if (rgn->base() > addr) { - return _committed_regions.insert_before(committed_rgn, node) != NULL; - } else { - return _committed_regions.insert_after(committed_rgn, node) != NULL; } + + if (rgn->overlap_region(addr, size)) { + // Clear a space for this region in the case it overlaps with any regions. + remove_uncommitted_region(addr, size); + break; // commit below } - assert(rgn->contain_region(addr, size), "Must cover this region"); - return true; - } else { + if (rgn->end() >= addr + size){ + break; + } + node = node->next(); + } + // New committed region VirtualMemorySummary::record_committed_memory(size, flag()); return add_committed_region(committed_rgn); } -} void ReservedMemoryRegion::set_all_committed(bool b) { if (all_committed() != b) { @@ -175,48 +173,52 @@ bool ReservedMemoryRegion::remove_uncommitted_region(address addr, size_t sz) { } } } else { - // we have to walk whole list to remove the committed regions in - // specified range - LinkedListNode* head = - _committed_regions.head(); - LinkedListNode* prev = NULL; - VirtualMemoryRegion uncommitted_rgn(addr, sz); + CommittedMemoryRegion del_rgn(addr, sz, *call_stack()); + address end = addr + sz; - while (head != NULL && !uncommitted_rgn.is_empty()) { - CommittedMemoryRegion* crgn = head->data(); - // this committed region overlaps to region to uncommit - if (crgn->overlap_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { - if (crgn->same_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { - // find matched region, remove the node will do - VirtualMemorySummary::record_uncommitted_memory(uncommitted_rgn.size(), flag()); + LinkedListNode* head = _committed_regions.head(); + LinkedListNode* prev = NULL; + CommittedMemoryRegion* crgn; + + while (head != NULL) { + crgn = head->data(); + + if (crgn->same_region(addr, sz)) { + VirtualMemorySummary::record_uncommitted_memory(crgn->size(), flag()); _committed_regions.remove_after(prev); return true; - } else if (crgn->contain_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { - // this committed region contains whole uncommitted region - VirtualMemorySummary::record_uncommitted_memory(uncommitted_rgn.size(), flag()); - return remove_uncommitted_region(head, uncommitted_rgn.base(), uncommitted_rgn.size()); - } else if (uncommitted_rgn.contain_region(crgn->base(), crgn->size())) { - // this committed region has been uncommitted - size_t exclude_size = crgn->end() - uncommitted_rgn.base(); - uncommitted_rgn.exclude_region(uncommitted_rgn.base(), exclude_size); + } + + // del_rgn contains crgn + if (del_rgn.contain_region(crgn->base(), crgn->size())) { VirtualMemorySummary::record_uncommitted_memory(crgn->size(), flag()); - LinkedListNode* tmp = head; head = head->next(); _committed_regions.remove_after(prev); - continue; - } else if (crgn->contain_address(uncommitted_rgn.base())) { - size_t toUncommitted = crgn->end() - uncommitted_rgn.base(); - crgn->exclude_region(uncommitted_rgn.base(), toUncommitted); - uncommitted_rgn.exclude_region(uncommitted_rgn.base(), toUncommitted); - VirtualMemorySummary::record_uncommitted_memory(toUncommitted, flag()); - } else if (uncommitted_rgn.contain_address(crgn->base())) { - size_t toUncommitted = uncommitted_rgn.end() - crgn->base(); - crgn->exclude_region(crgn->base(), toUncommitted); - uncommitted_rgn.exclude_region(uncommitted_rgn.end() - toUncommitted, - toUncommitted); - VirtualMemorySummary::record_uncommitted_memory(toUncommitted, flag()); + continue; // don't update head or prev } + + // Found addr in the current crgn. There are 2 subcases: + if (crgn->contain_address(addr)) { + + // (1) Found addr+size in current crgn as well. (del_rgn is contained in crgn) + if (crgn->contain_address(end - 1)) { + VirtualMemorySummary::record_uncommitted_memory(sz, flag()); + return remove_uncommitted_region(head, addr, sz); // done! + } else { + // (2) Did not find del_rgn's end in crgn. + size_t size = crgn->end() - del_rgn.base(); + crgn->exclude_region(addr, size); + VirtualMemorySummary::record_uncommitted_memory(size, flag()); } + + } else if (crgn->contain_address(end - 1)) { + // Found del_rgn's end, but not its base addr. + size_t size = del_rgn.end() - crgn->base(); + crgn->exclude_region(crgn->base(), size); + VirtualMemorySummary::record_uncommitted_memory(size, flag()); + return true; // should be done if the list is sorted properly! + } + prev = head; head = head->next(); } @@ -386,7 +388,8 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, assert(reserved_rgn != NULL, "No reserved region"); assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); - return reserved_rgn->add_committed_region(addr, size, stack); + bool result = reserved_rgn->add_committed_region(addr, size, stack); + return result; } bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) { @@ -398,7 +401,8 @@ bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); assert(reserved_rgn != NULL, "No reserved region"); assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); - return reserved_rgn->remove_uncommitted_region(addr, size); + bool result = reserved_rgn->remove_uncommitted_region(addr, size); + return result; } bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { @@ -488,5 +492,3 @@ bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel return true; } - - diff --git a/hotspot/src/share/vm/services/virtualMemoryTracker.hpp b/hotspot/src/share/vm/services/virtualMemoryTracker.hpp index d2f8abdcaeb..02d21bd53bb 100644 --- a/hotspot/src/share/vm/services/virtualMemoryTracker.hpp +++ b/hotspot/src/share/vm/services/virtualMemoryTracker.hpp @@ -261,8 +261,7 @@ class CommittedMemoryRegion : public VirtualMemoryRegion { VirtualMemoryRegion(addr, size), _stack(stack) { } inline int compare(const CommittedMemoryRegion& rgn) const { - if (overlap_region(rgn.base(), rgn.size()) || - adjacent_to (rgn.base(), rgn.size())) { + if (overlap_region(rgn.base(), rgn.size())) { return 0; } else { if (base() == rgn.base()) { diff --git a/hotspot/src/share/vm/services/writeableFlags.cpp b/hotspot/src/share/vm/services/writeableFlags.cpp index 3541fddaece..fab21ba346c 100644 --- a/hotspot/src/share/vm/services/writeableFlags.cpp +++ b/hotspot/src/share/vm/services/writeableFlags.cpp @@ -93,12 +93,12 @@ static void print_flag_error_message_if_needed(Flag::Error error, const char* na // set a boolean global flag Flag::Error WriteableFlags::set_bool_flag(const char* name, const char* arg, Flag::Flags origin, FormatBuffer<80>& err_msg) { - int value = true; - - if (sscanf(arg, "%d", &value)) { - return set_bool_flag(name, value != 0, origin, err_msg); + if ((strcasecmp(arg, "true") == 0) || (*arg == '1' && *(arg + 1) == 0)) { + return set_bool_flag(name, true, origin, err_msg); + } else if ((strcasecmp(arg, "false") == 0) || (*arg == '0' && *(arg + 1) == 0)) { + return set_bool_flag(name, false, origin, err_msg); } - err_msg.print("flag value must be a boolean (1 or 0)"); + err_msg.print("flag value must be a boolean (1/0 or true/false)"); return Flag::WRONG_FORMAT; } diff --git a/hotspot/src/share/vm/utilities/hashtable.cpp b/hotspot/src/share/vm/utilities/hashtable.cpp index 8af6156ed45..2d4bd0b83e4 100644 --- a/hotspot/src/share/vm/utilities/hashtable.cpp +++ b/hotspot/src/share/vm/utilities/hashtable.cpp @@ -383,6 +383,7 @@ template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; +template class BasicHashtable; #if INCLUDE_TRACE template class Hashtable; template class HashtableEntry; diff --git a/hotspot/src/share/vm/utilities/linkedlist.hpp b/hotspot/src/share/vm/utilities/linkedlist.hpp index a76c15cca0e..33e416e0e26 100644 --- a/hotspot/src/share/vm/utilities/linkedlist.hpp +++ b/hotspot/src/share/vm/utilities/linkedlist.hpp @@ -259,6 +259,11 @@ template * node) { LinkedListNode* p = this->head(); + if (p == node) { + this->set_head(p->next()); + delete_node(node); + return true; + } while (p != NULL && p->next() != node) { p = p->next(); } diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile index c967434425f..2f2f810f37b 100644 --- a/hotspot/test/Makefile +++ b/hotspot/test/Makefile @@ -306,7 +306,10 @@ ifdef TESTDIRS endif ifdef CONCURRENCY - EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY) + JTREG_BASIC_OPTIONS += -concurrency:$(CONCURRENCY) +endif +ifdef EXTRA_JTREG_OPTIONS + JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS) endif # Default JTREG to run @@ -326,8 +329,6 @@ JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION) # Multiply by 4 the timeout factor JTREG_TIMEOUT_OPTION = -timeoutFactor:4 JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION) -# Add any extra options -JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS) # Set other vm and test options JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_OPTIONS:%=-vmoption:%) $(JAVA_VM_ARGS:%=-vmoption:%) diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java index 28463d71e75..c9826c857e3 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java @@ -138,17 +138,6 @@ public class GetConstantPoolTest { return CompilerToVMHelper.getConstantPool(cpInst, ptr); } }, - OBJECT_TYPE_BASE { - @Override - ConstantPool getConstantPool() { - HotSpotResolvedObjectType type - = HotSpotResolvedObjectType.fromObjectClass( - OBJECT_TYPE_BASE.getClass()); - long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE); - return CompilerToVMHelper.getConstantPool(type, - getPtrToCpAddress() - ptrToClass); - } - }, ; abstract ConstantPool getConstantPool(); } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java index 1dde0850aad..a648caaac67 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java @@ -24,6 +24,7 @@ /* * @test * @bug 8136421 + * @ignore 8158860 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") * @library / /testlibrary /test/lib * @library ../common/patches @@ -149,25 +150,12 @@ public class GetResolvedJavaTypeTest { ptr, COMPRESSED); } }, - OBJECT_TYPE_BASE { - @Override - HotSpotResolvedObjectType getResolvedJavaType() { - HotSpotResolvedObjectType type - = HotSpotResolvedObjectType.fromObjectClass( - OBJECT_TYPE_BASE.getClass()); - long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE); - return CompilerToVMHelper.getResolvedJavaType(type, - getPtrToKlass() - ptrToClass, COMPRESSED); - } - }, ; abstract HotSpotResolvedObjectType getResolvedJavaType(); } private static final Unsafe UNSAFE = Utils.getUnsafe(); private static final WhiteBox WB = WhiteBox.getWhiteBox(); - private static final long PTR = UNSAFE.getKlassPointer( - new GetResolvedJavaTypeTest()); private static final Class TEST_CLASS = GetResolvedJavaTypeTest.class; /* a compressed parameter for tested method is set to false because unsafe.getKlassPointer always returns uncompressed pointer */ diff --git a/hotspot/test/gc/TestSmallHeap.java b/hotspot/test/gc/TestSmallHeap.java index 9c0dba31fc0..a58fa8c4e28 100644 --- a/hotspot/test/gc/TestSmallHeap.java +++ b/hotspot/test/gc/TestSmallHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,22 +23,15 @@ /** * @test TestSmallHeap - * @bug 8067438 + * @bug 8067438 8152239 * @requires vm.gc=="null" - * @requires (vm.opt.AggressiveOpts=="null") | (vm.opt.AggressiveOpts=="false") - * @requires vm.compMode != "Xcomp" - * @requires vm.opt.UseCompressedOops != false * @summary Verify that starting the VM with a small heap works - * @library /testlibrary /test/lib + * @library /testlibrary /test/lib /test/lib/share/classes * @modules java.base/jdk.internal.misc * @modules java.management/sun.management - * @ignore 8076621 * @build TestSmallHeap * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseParallelGC TestSmallHeap - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseSerialGC TestSmallHeap - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseG1GC TestSmallHeap - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseConcMarkSweepGC TestSmallHeap + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestSmallHeap */ /* Note: It would be nice to verify the minimal supported heap size (2m) here, @@ -60,23 +53,55 @@ * So, the expected heap size is page_size * 512. */ -import jdk.test.lib.*; -import com.sun.management.HotSpotDiagnosticMXBean; -import java.lang.management.ManagementFactory; -import static jdk.test.lib.Asserts.*; +import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.util.LinkedList; import sun.hotspot.WhiteBox; public class TestSmallHeap { - public static void main(String[] args) { + public static void main(String[] args) throws Exception { + // Do all work in the VM driving the test, the VM + // with the small heap size should do as little as + // possible to avoid hitting an OOME. WhiteBox wb = WhiteBox.getWhiteBox(); int pageSize = wb.getVMPageSize(); int heapBytesPerCard = 512; long expectedMaxHeap = pageSize * heapBytesPerCard; - String maxHeap - = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("MaxHeapSize").getValue(); - assertEQ(Long.parseLong(maxHeap), expectedMaxHeap); + + verifySmallHeapSize("-XX:+UseParallelGC", expectedMaxHeap); + verifySmallHeapSize("-XX:+UseSerialGC", expectedMaxHeap); + verifySmallHeapSize("-XX:+UseG1GC", expectedMaxHeap); + verifySmallHeapSize("-XX:+UseConcMarkSweepGC", expectedMaxHeap); + } + + private static void verifySmallHeapSize(String gc, long expectedMaxHeap) throws Exception { + LinkedList vmOptions = new LinkedList<>(); + vmOptions.add(gc); + vmOptions.add("-Xmx2m"); + vmOptions.add("-XX:+PrintFlagsFinal"); + vmOptions.add(VerifyHeapSize.class.getName()); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[0])); + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + analyzer.shouldHaveExitValue(0); + + long maxHeapSize = Long.parseLong(analyzer.firstMatch("MaxHeapSize.+=\\s+(\\d+)",1)); + long actualHeapSize = Long.parseLong(analyzer.firstMatch(VerifyHeapSize.actualMsg + "(\\d+)",1)); + Asserts.assertEQ(maxHeapSize, expectedMaxHeap); + Asserts.assertLessThanOrEqual(actualHeapSize, maxHeapSize); + } +} + +class VerifyHeapSize { + public static final String actualMsg = "Actual heap size: "; + + public static void main(String args[]) { + // Avoid string concatenation + System.out.print(actualMsg); + System.out.println(Runtime.getRuntime().maxMemory()); } } diff --git a/hotspot/test/gc/g1/ihop/TestIHOPErgo.java b/hotspot/test/gc/g1/ihop/TestIHOPErgo.java index 95609b84d4d..f77d4584fa9 100644 --- a/hotspot/test/gc/g1/ihop/TestIHOPErgo.java +++ b/hotspot/test/gc/g1/ihop/TestIHOPErgo.java @@ -28,6 +28,7 @@ * @requires vm.gc=="G1" | vm.gc=="null" * @requires vm.opt.FlightRecorder != true * @requires vm.opt.ExplicitGCInvokesConcurrent != true + * @requires vm.opt.MaxGCPauseMillis == "null" * @library /testlibrary /test/lib / * @modules java.base/jdk.internal.misc * @modules java.management diff --git a/hotspot/test/gc/g1/mixedgc/TestLogging.java b/hotspot/test/gc/g1/mixedgc/TestLogging.java index f99fdbd21a4..0e232a6f174 100644 --- a/hotspot/test/gc/g1/mixedgc/TestLogging.java +++ b/hotspot/test/gc/g1/mixedgc/TestLogging.java @@ -25,6 +25,7 @@ * @test TestLogging * @summary Check that a mixed GC is reflected in the gc logs * @requires vm.gc=="G1" | vm.gc=="null" + * @requires vm.opt.MaxGCPauseMillis == "null" * @library /testlibrary /test/lib * @modules java.base/jdk.internal.misc * @modules java.management diff --git a/hotspot/test/gc/g1/plab/TestPLABPromotion.java b/hotspot/test/gc/g1/plab/TestPLABPromotion.java index 3664897ea83..cefff072c32 100644 --- a/hotspot/test/gc/g1/plab/TestPLABPromotion.java +++ b/hotspot/test/gc/g1/plab/TestPLABPromotion.java @@ -122,10 +122,7 @@ public class TestPLABPromotion { List options = PLABUtils.prepareOptions(testCase.toOptions()); options.add(AppPLABPromotion.class.getName()); OutputAnalyzer out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()])); - if (out.getExitValue() != 0) { - System.out.println(out.getOutput()); - throw new RuntimeException("Expect exit code 0."); - } + PLABUtils.commonCheck(out); output = out.getOutput(); checkResults(testCase); } diff --git a/hotspot/test/gc/g1/plab/TestPLABResize.java b/hotspot/test/gc/g1/plab/TestPLABResize.java index f3ac2aad802..039ef53e8ed 100644 --- a/hotspot/test/gc/g1/plab/TestPLABResize.java +++ b/hotspot/test/gc/g1/plab/TestPLABResize.java @@ -94,10 +94,7 @@ public class TestPLABResize { List options = PLABUtils.prepareOptions(testCase.toOptions()); options.add(AppPLABResize.class.getName()); OutputAnalyzer out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()])); - if (out.getExitValue() != 0) { - System.out.println(out.getOutput()); - throw new RuntimeException("Exit code is not 0"); - } + PLABUtils.commonCheck(out); checkResults(out.getOutput(), testCase); } } @@ -124,6 +121,11 @@ public class TestPLABResize { // The test case does 3 rounds of allocations. The second round of N allocations and GC's // has a decreasing size of allocations so that iterations N to 2*N -1 will be of decreasing size. // The third round with iterations 2*N to 3*N -1 has increasing sizes of allocation. + if ( plabSizes.size() != testCase.iterations * 3 ) { + System.out.println(output); + throw new RuntimeException ("Expects for " + testCase.iterations * 3 + " PLAB entries in log, found " + plabSizes.size()); + } + long startDesiredPLABSize = plabSizes.get(testCase.getIterations()); long endDesiredPLABSize = plabSizes.get(testCase.getIterations() * 2 - 1); diff --git a/hotspot/test/gc/g1/plab/lib/LogParser.java b/hotspot/test/gc/g1/plab/lib/LogParser.java index 8b70c20573f..f4e9735e63b 100644 --- a/hotspot/test/gc/g1/plab/lib/LogParser.java +++ b/hotspot/test/gc/g1/plab/lib/LogParser.java @@ -169,7 +169,12 @@ final public class LogParser { * @return **/ public PlabInfo getSpecifiedStats(long specifiedGcId, LogParser.ReportType type, List fieldsName) { - return getSpecifiedStats(Arrays.asList(specifiedGcId), type, fieldsName, true).get(specifiedGcId); + PlabInfo info = getSpecifiedStats(Arrays.asList(specifiedGcId), type, fieldsName, true).get(specifiedGcId); + if (info == null) { + System.out.println(log); + throw new RuntimeException("Cannot find PLAB statistics in log ( GC_ID=" + specifiedGcId + " type=" + type + " )"); + } + return info; } /** diff --git a/hotspot/test/gc/g1/plab/lib/PLABUtils.java b/hotspot/test/gc/g1/plab/lib/PLABUtils.java index ee13f0a2fa2..096441c14cb 100644 --- a/hotspot/test/gc/g1/plab/lib/PLABUtils.java +++ b/hotspot/test/gc/g1/plab/lib/PLABUtils.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.Utils; /** @@ -50,7 +51,7 @@ public class PLABUtils { * GC logging options list. */ private final static String G1_PLAB_LOGGING_OPTIONS[] = { - "-Xlog:gc=debug,gc+plab=debug" + "-Xlog:gc=debug,gc+plab=debug,gc+heap=debug" }; /** @@ -81,4 +82,18 @@ public class PLABUtils { executionOtions.addAll(options); return executionOtions; } + + /** + * Common check for test PLAB application's results. + * @param out OutputAnalyzer for checking + * @throws RuntimeException + */ + public static void commonCheck(OutputAnalyzer out) throws RuntimeException { + if (out.getExitValue() != 0) { + System.out.println(out.getOutput()); + throw new RuntimeException("Exit code is not 0"); + } + // Test expects only WhiteBox initiated GC. + out.shouldNotContain("Pause Young (G1 Evacuation Pause)"); + } } diff --git a/hotspot/test/gc/stress/TestMultiThreadStressRSet.java b/hotspot/test/gc/stress/TestMultiThreadStressRSet.java index 5a69888a502..336b0614bd7 100644 --- a/hotspot/test/gc/stress/TestMultiThreadStressRSet.java +++ b/hotspot/test/gc/stress/TestMultiThreadStressRSet.java @@ -33,6 +33,7 @@ import sun.hotspot.WhiteBox; * @key stress * @requires vm.gc=="G1" | vm.gc=="null" * @requires os.maxMemory > 2G + * @requires vm.opt.MaxGCPauseMillis == "null" * * @summary Stress G1 Remembered Set using multiple threads * @modules java.base/jdk.internal.misc diff --git a/hotspot/test/gc/stress/TestStressRSetCoarsening.java b/hotspot/test/gc/stress/TestStressRSetCoarsening.java index 7ab74a4d2d1..a0d581b0656 100644 --- a/hotspot/test/gc/stress/TestStressRSetCoarsening.java +++ b/hotspot/test/gc/stress/TestStressRSetCoarsening.java @@ -30,6 +30,7 @@ import sun.hotspot.WhiteBox; * @bug 8146984 8147087 * @requires vm.gc=="G1" | vm.gc=="null" * @requires os.maxMemory > 3G + * @requires vm.opt.MaxGCPauseMillis == "null" * * @summary Stress G1 Remembered Set by creating a lot of cross region links * @modules java.base/jdk.internal.misc @@ -102,7 +103,7 @@ public class TestStressRSetCoarsening { private static final WhiteBox WB = WhiteBox.getWhiteBox(); - public final Object[][] storage; + public final ObjStorage storage; /** * Number of objects per region. This is a test parameter. @@ -161,6 +162,8 @@ public class TestStressRSetCoarsening { long totalFree = rt.maxMemory() - used; regionCount = (int) ((totalFree / regionSize) * heapFractionToAllocate); long toAllocate = regionCount * regionSize; + long freeMemoryLimit = totalFree - toAllocate; + System.out.println("%% Test parameters"); System.out.println("%% Objects per region : " + K); System.out.println("%% Heap fraction to allocate : " + (int) (heapFractionToAllocate * 100) + "%"); @@ -212,9 +215,15 @@ public class TestStressRSetCoarsening { " (sizeOf(new Object[" + N + "])"); System.out.println("%% Reference size : " + refSize); - storage = new Object[regionCount * K][]; - for (int i = 0; i < storage.length; i++) { - storage[i] = new Object[N]; + // Maximum number of objects to allocate is regionCount * K. + storage = new ObjStorage(regionCount * K); + + // Add objects as long as there is space in the storage + // and we haven't used more memory than planned. + while (!storage.isFull() && (rt.maxMemory() - used) > freeMemoryLimit) { + storage.addArray(new Object[N]); + // Update used memory + used = rt.totalMemory() - rt.freeMemory(); } } @@ -255,7 +264,7 @@ public class TestStressRSetCoarsening { // The celebrity will be referred from all other regions. // If the number of references after should be less than they // were before, select NULL. - Object celebrity = cur > pre ? storage[to * K] : null; + Object celebrity = cur > pre ? storage.getArrayAt(to * K) : null; for (int from = 0; from < regionCount; from++) { if (to == from) { continue; // no need to refer to itself @@ -263,7 +272,8 @@ public class TestStressRSetCoarsening { int step = cur > pre ? +1 : -1; for (int rn = pre; rn != cur; rn += step) { - storage[getY(to, from, rn)][getX(to, from, rn)] = celebrity; + Object[] rnArray = storage.getArrayAt(getY(to, from, rn)); + rnArray[getX(to, from, rn)] = celebrity; if (System.currentTimeMillis() > finishAt) { throw new TimeoutException(); } @@ -290,14 +300,15 @@ public class TestStressRSetCoarsening { continue; // no need to refer to itself } for (int rn = 0; rn <= cur; rn++) { - storage[getY(to, from, rn)][getX(to, from, rn)] = null; + Object[] rnArray = storage.getArrayAt(getY(to, from, rn)); + rnArray[getX(to, from, rn)] = null; } } // 'Refresh' storage elements for the region 'to' // After that loop all 'old' objects in the region 'to' // should become unreachable. for (int k = 0; k < K; k++) { - storage[(to * K + k) % storage.length] = new Object[N]; + storage.setArrayAt(to * K + k, new Object[N]); } } } @@ -340,3 +351,36 @@ public class TestStressRSetCoarsening { } } +//Helper class to encapsulate the object array storage. +class ObjStorage { + public final Object[][] storage; + public int usedCount; + + ObjStorage(int size) { + storage = new Object[size][]; + usedCount = 0; + } + + public boolean isFull() { + return usedCount >= storage.length; + } + + public void addArray(Object[] objects) { + if (isFull()) { + throw new IllegalStateException("Storage full maximum number of allowed elements: " + usedCount); + } + storage[usedCount++] = objects; + } + + // Limit by usedCount since memory limits can cause the storage + // to have unused slots in the end. + public void setArrayAt(int i, Object[] objects) { + storage[i % usedCount] = objects; + } + + // Limit by usedCount since memory limits can cause the storage + // to have unused slots in the end. + public Object[] getArrayAt(int i) { + return storage[i % usedCount]; + } +} diff --git a/hotspot/test/native/GTestWrapper.java b/hotspot/test/native/GTestWrapper.java new file mode 100644 index 00000000000..cedf63e4aa4 --- /dev/null +++ b/hotspot/test/native/GTestWrapper.java @@ -0,0 +1,82 @@ +/* + * 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 + * @summary a jtreg wrapper for gtest tests + * @library /test/lib/share/classes + * @modules java.base/jdk.internal.misc + * @run main/native GTestWrapper + */ + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Collectors; + +import java.nio.file.Paths; +import java.nio.file.Path; + +import jdk.test.lib.Platform; +import jdk.test.lib.Utils; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class GTestWrapper { + public static void main(String[] args) throws Throwable { + // gtestLauncher is located in /hotspot/gtest// + // nativePath points either to /hotspot/jtreg/native or to /hotspot/gtest + Path nativePath = Paths.get(System.getProperty("test.nativepath")); + String jvmVariantDir = getJVMVariantSubDir(); + // let's assume it's /hotspot/gtest + Path path = nativePath.resolve(jvmVariantDir); + if (!path.toFile().exists()) { + // maybe it is /hotspot/jtreg/native + path = nativePath.getParent() + .getParent() + .resolve("gtest") + .resolve(jvmVariantDir); + } + if (!path.toFile().exists()) { + throw new Error("TESTBUG: the library has not been found in " + nativePath); + } + path = path.resolve("gtestLauncher" + (Platform.isWindows() ? ".exe" : "")); + ProcessTools.executeCommand(new String[] { + path.toString(), + "-jdk", + System.getProperty("test.jdk") + }).shouldHaveExitValue(0); + } + + private static String getJVMVariantSubDir() { + if (Platform.isServer()) { + return "server"; + } else if (Platform.isClient()) { + return "client"; + } else if (Platform.isMinimal()) { + return "minimal"; + } else { + throw new Error("TESTBUG: unsuppported vm variant"); + } + } +} diff --git a/hotspot/test/runtime/ConstantPool/BadMethodHandles.java b/hotspot/test/runtime/ConstantPool/BadMethodHandles.java new file mode 100644 index 00000000000..6345166e022 --- /dev/null +++ b/hotspot/test/runtime/ConstantPool/BadMethodHandles.java @@ -0,0 +1,254 @@ +/* + * 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 8087223 + * @summary Adding constantTag to keep method call consistent with it. + * @library /testlibrary + * @modules java.base/jdk.internal.org.objectweb.asm + * java.base/jdk.internal.misc + * java.management + * @compile -XDignore.symbol.file BadMethodHandles.java + * @run main/othervm BadMethodHandles + */ + +import jdk.internal.org.objectweb.asm.*; +import java.io.FileOutputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +public class BadMethodHandles { + + static byte[] dumpBadInterfaceMethodref() { + ClassWriter cw = new ClassWriter(0); + cw.visit(52, ACC_PUBLIC | ACC_SUPER, "BadInterfaceMethodref", null, "java/lang/Object", null); + Handle handle1 = + new Handle(Opcodes.H_INVOKEINTERFACE, "BadInterfaceMethodref", "m", "()V"); + Handle handle2 = + new Handle(Opcodes.H_INVOKEINTERFACE, "BadInterfaceMethodref", "staticM", "()V"); + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "m", "()V", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("hello from m"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false/*intf*/); + mv.visitInsn(RETURN); + mv.visitMaxs(3, 1); + mv.visitEnd(); + } + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "staticM", "()V", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("hello from staticM"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false/*intf*/); + mv.visitInsn(RETURN); + mv.visitMaxs(3, 1); + mv.visitEnd(); + } + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "runm", "()V", null, null); + mv.visitCode(); + // REF_invokeStatic + mv.visitLdcInsn(handle1); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invoke", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "runStaticM", "()V", null, null); + mv.visitCode(); + // REF_invokeStatic + mv.visitLdcInsn(handle2); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invoke", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + cw.visitEnd(); + return cw.toByteArray(); + } + + static byte[] dumpIBad() { + ClassWriter cw = new ClassWriter(0); + cw.visit(52, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "IBad", null, "java/lang/Object", null); + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "m", "()V", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("hello from m"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false/*intf*/); + mv.visitInsn(RETURN); + mv.visitMaxs(3, 1); + mv.visitEnd(); + } + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "staticM", "()V", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("hello from staticM"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false/*intf*/); + mv.visitInsn(RETURN); + mv.visitMaxs(3, 1); + mv.visitEnd(); + } + cw.visitEnd(); + return cw.toByteArray(); + } + + static byte[] dumpBadMethodref() { + ClassWriter cw = new ClassWriter(0); + cw.visit(52, ACC_PUBLIC | ACC_SUPER, "BadMethodref", null, "java/lang/Object", new String[]{"IBad"}); + Handle handle1 = + new Handle(Opcodes.H_INVOKEINTERFACE, "BadMethodref", "m", "()V"); + Handle handle2 = + new Handle(Opcodes.H_INVOKEINTERFACE, "BadMethodref", "staticM", "()V"); + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "runm", "()V", null, null); + mv.visitCode(); + // REF_invokeStatic + mv.visitLdcInsn(handle1); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invoke", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "runStaticM", "()V", null, null); + mv.visitCode(); + // REF_invokeStatic + mv.visitLdcInsn(handle2); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invoke", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + cw.visitEnd(); + return cw.toByteArray(); + } + static class CL extends ClassLoader { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] classBytes = null; + switch (name) { + case "BadInterfaceMethodref": classBytes = dumpBadInterfaceMethodref(); break; + case "BadMethodref" : classBytes = dumpBadMethodref(); break; + case "IBad" : classBytes = dumpIBad(); break; + default : throw new ClassNotFoundException(name); + } + return defineClass(name, classBytes, 0, classBytes.length); + } + } + + public static void main(String[] args) throws Throwable { + try (FileOutputStream fos = new FileOutputStream("BadInterfaceMethodref.class")) { + fos.write(dumpBadInterfaceMethodref()); + } + try (FileOutputStream fos = new FileOutputStream("IBad.class")) { + fos.write(dumpIBad()); + } + try (FileOutputStream fos = new FileOutputStream("BadMethodref.class")) { + fos.write(dumpBadMethodref()); + } + + Class cls = (new CL()).loadClass("BadInterfaceMethodref"); + String[] methods = {"runm", "runStaticM"}; + System.out.println("Test BadInterfaceMethodref:"); + int success = 0; + for (String name : methods) { + try { + System.out.printf("invoke %s: \n", name); + cls.getMethod(name).invoke(cls.newInstance()); + System.out.println("FAILED - ICCE should be thrown"); + } catch (Throwable e) { + if (e instanceof InvocationTargetException && e.getCause() != null && + e.getCause() instanceof IncompatibleClassChangeError) { + System.out.println("PASSED - expected ICCE thrown"); + success++; + continue; + } else { + System.out.println("FAILED with wrong exception" + e); + throw e; + } + } + } + if (success != methods.length) { + throw new Exception("BadInterfaceMethodRef Failed to catch IncompatibleClassChangeError"); + } + System.out.println("Test BadMethodref:"); + cls = (new CL()).loadClass("BadMethodref"); + success = 0; + for (String name : methods) { + try { + System.out.printf("invoke %s: \n", name); + cls.getMethod(name).invoke(cls.newInstance()); + System.out.println("FAILED - ICCE should be thrown"); + } catch (Throwable e) { + if (e instanceof InvocationTargetException && e.getCause() != null && + e.getCause() instanceof IncompatibleClassChangeError) { + System.out.println("PASSED - expected ICCE thrown"); + success++; + continue; + } else { + System.out.println("FAILED with wrong exception" + e); + throw e; + } + } + } + if (success != methods.length) { + throw new Exception("BadMethodRef Failed to catch IncompatibleClassChangeError"); + } + + } +} diff --git a/hotspot/test/runtime/ConstantPool/IntfMethod.java b/hotspot/test/runtime/ConstantPool/IntfMethod.java new file mode 100644 index 00000000000..9602ff59979 --- /dev/null +++ b/hotspot/test/runtime/ConstantPool/IntfMethod.java @@ -0,0 +1,160 @@ +/* + * 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 8087223 + * @summary Adding constantTag to keep method call consistent with it. + * @library /testlibrary + * @modules java.base/jdk.internal.org.objectweb.asm + * java.base/jdk.internal.misc + * java.management + * @compile -XDignore.symbol.file IntfMethod.java + * @run main/othervm IntfMethod + * @run main/othervm -Xint IntfMethod + * @run main/othervm -Xcomp IntfMethod + */ + + +import jdk.internal.org.objectweb.asm.*; +import java.io.FileOutputStream; +import java.lang.reflect.InvocationTargetException; +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +public class IntfMethod { + static byte[] dumpC() { + ClassWriter cw = new ClassWriter(0); + cw.visit(52, ACC_PUBLIC | ACC_SUPER, "C", null, "java/lang/Object", new String[]{"I"}); + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testSpecialIntf", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "I", "f1", "()V", /*itf=*/false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testStaticIntf", "()V", null, null); + mv.visitCode(); + mv.visitMethodInsn(INVOKESTATIC, "I", "f2", "()V", /*itf=*/false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testSpecialClass", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "C", "f1", "()V", /*itf=*/true); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f2", "()V", null, null); + mv.visitCode(); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 1); + mv.visitEnd(); + } + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testStaticClass", "()V", null, null); + mv.visitCode(); + mv.visitMethodInsn(INVOKESTATIC, "C", "f2", "()V", /*itf=*/true); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + cw.visitEnd(); + return cw.toByteArray(); + } + + static byte[] dumpI() { + ClassWriter cw = new ClassWriter(0); + cw.visit(52, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "I", null, "java/lang/Object", null); + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "f1", "()V", null, null); + mv.visitCode(); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 1); + mv.visitEnd(); + } + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f2", "()V", null, null); + mv.visitCode(); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 1); + mv.visitEnd(); + } + cw.visitEnd(); + return cw.toByteArray(); + } + + static class CL extends ClassLoader { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] classFile; + switch (name) { + case "I": classFile = dumpI(); break; + case "C": classFile = dumpC(); break; + default: + throw new ClassNotFoundException(name); + } + return defineClass(name, classFile, 0, classFile.length); + } + } + + public static void main(String[] args) throws Throwable { + Class cls = (new CL()).loadClass("C"); + try (FileOutputStream fos = new FileOutputStream("I.class")) { fos.write(dumpI()); } + try (FileOutputStream fos = new FileOutputStream("C.class")) { fos.write(dumpC()); } + + int success = 0; + for (String name : new String[] { "testSpecialIntf", "testStaticIntf", "testSpecialClass", "testStaticClass"}) { + System.out.printf("%s: ", name); + try { + cls.getMethod(name).invoke(cls.newInstance()); + System.out.println("FAILED - ICCE not thrown"); + } catch (Throwable e) { + if (e instanceof InvocationTargetException && + e.getCause() != null && e.getCause() instanceof IncompatibleClassChangeError) { + System.out.println("PASSED - expected ICCE thrown"); + success++; + continue; + } + } + } + if (success != 4) throw new Exception("Failed to catch ICCE"); + } +} diff --git a/hotspot/test/runtime/NMT/CommitOverlappingRegions.java b/hotspot/test/runtime/NMT/CommitOverlappingRegions.java new file mode 100644 index 00000000000..212a9930fd3 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommitOverlappingRegions.java @@ -0,0 +1,144 @@ +/* + * 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 + * @summary Test commits of overlapping regions of memory. + * @key nmt jcmd + * @library /testlibrary /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build CommitOverlappingRegions + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail CommitOverlappingRegions + */ + +import jdk.test.lib.*; +import sun.hotspot.WhiteBox; + +public class CommitOverlappingRegions { + public static WhiteBox wb = WhiteBox.getWhiteBox(); + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + long size = 32 * 1024; + long addr = wb.NMTReserveMemory(8*size); + + String pid = Long.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); + System.out.println("Address is " + Long.toHexString(addr)); + + // Start: . . . . . . . . + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=0KB)"); + + // Committing: * * * . . . . . + // Region: * * * . . . . . + // Expected Total: 3 x 32KB = 96KB + wb.NMTCommitMemory(addr + 0*size, 3*size); + + // Committing: . . . . * * * . + // Region: * * * . * * * . + // Expected Total: 6 x 32KB = 192KB + wb.NMTCommitMemory(addr + 4*size, 3*size); + + // Check output after first 2 commits. + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=192KB)"); + + // Committing: . . * * * . . . + // Region: * * * * * * * . + // Expected Total: 7 x 32KB = 224KB + wb.NMTCommitMemory(addr + 2*size, 3*size); + + // Check output after overlapping commit. + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=224KB)"); + + // Uncommitting: * * * * * * * * + // Region: . . . . . . . . + // Expected Total: 0 x 32KB = 0KB + wb.NMTUncommitMemory(addr + 0*size, 8*size); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=0KB)"); + + // Committing: * * . . . . . . + // Region: * * . . . . . . + // Expected Total: 2 x 32KB = 64KB + wb.NMTCommitMemory(addr + 0*size, 2*size); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=64KB)"); + + // Committing: . * * * . . . . + // Region: * * * * . . . . + // Expected Total: 4 x 32KB = 128KB + wb.NMTCommitMemory(addr + 1*size, 3*size); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=128KB)"); + + // Uncommitting: * * * . . . . . + // Region: . . . * . . . . + // Expected Total: 1 x 32KB = 32KB + wb.NMTUncommitMemory(addr + 0*size, 3*size); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=32KB)"); + + // Committing: . . . * * . . . + // Region: . . . * * . . . + // Expected Total: 2 x 32KB = 64KB + wb.NMTCommitMemory(addr + 3*size, 2*size); + System.out.println("Address is " + Long.toHexString(addr + 3*size)); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=64KB)"); + + // Committing: . . . . * * . . + // Region: . . . * * * . . + // Expected Total: 3 x 32KB = 96KB + wb.NMTCommitMemory(addr + 4*size, 2*size); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=96KB)"); + + // Committing: . . . . . * * . + // Region: . . . * * * * . + // Expected Total: 4 x 32KB = 128KB + wb.NMTCommitMemory(addr + 5*size, 2*size); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=128KB)"); + + // Committing: . . . . . . * * + // Region: . . . * * * * * + // Expected Total: 5 x 32KB = 160KB + wb.NMTCommitMemory(addr + 6*size, 2*size); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=160KB)"); + + // Uncommitting: * * * * * * * * + // Region: . . . . . . . . + // Expected Total: 0 x 32KB = 32KB + wb.NMTUncommitMemory(addr + 0*size, 8*size); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=0KB)"); + } +} diff --git a/hotspot/test/runtime/NMT/PrintNMTStatistics.java b/hotspot/test/runtime/NMT/PrintNMTStatistics.java index 413ade55e80..11138ec0d48 100644 --- a/hotspot/test/runtime/NMT/PrintNMTStatistics.java +++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, 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 @@ -48,6 +48,9 @@ public class PrintNMTStatistics { output_detail.shouldNotContain("error"); output_detail.shouldHaveExitValue(0); + // Make sure memory reserved for Module processing is recorded. + output_detail.shouldContain(" Module (reserved="); + ProcessBuilder pb1 = ProcessTools.createJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintNMTStatistics", diff --git a/hotspot/test/runtime/ReservedStack/ReservedStackTest.java b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java index 3c60d4709ce..a608077dfe1 100644 --- a/hotspot/test/runtime/ReservedStack/ReservedStackTest.java +++ b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java @@ -27,6 +27,7 @@ * @modules java.base/jdk.internal.misc * @modules java.base/jdk.internal.vm.annotation * @build jdk.test.lib.* + * @run main/othervm -Xint ReservedStackTest * @run main/othervm -XX:-Inline -XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread ReservedStackTest */ @@ -196,9 +197,12 @@ public class ReservedStackTest { System.out.println("Test started execution at frame = " + (counter - deframe)); String result = test.getResult(); // The feature is not fully implemented on all platforms, - // corruptions are still possible - boolean supportedPlatform = Platform.isSolaris() || Platform.isOSX() - || (Platform.isLinux() && (Platform.isX86() || Platform.isX64())); + // corruptions are still possible. + boolean supportedPlatform = + Platform.isAix() || + (Platform.isLinux() && (Platform.isPPC() || Platform.isX64() || Platform.isX86())) || + Platform.isOSX() || + Platform.isSolaris(); if (supportedPlatform && !result.contains("PASSED")) { System.out.println(result); throw new Error(result); diff --git a/hotspot/test/runtime/ReservedStack/ReservedStackTestCompiler.java b/hotspot/test/runtime/ReservedStack/ReservedStackTestCompiler.java new file mode 100644 index 00000000000..fa7ba474612 --- /dev/null +++ b/hotspot/test/runtime/ReservedStack/ReservedStackTestCompiler.java @@ -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. + */ + +/* + * @test ReservedStackTestCompiler + * @summary Run ReservedStackTest with dedicated compilers C1 and C2. + * @requires vm.flavor == "server" + * @library /testlibrary + * @modules java.base/jdk.internal.misc + * @modules java.base/jdk.internal.vm.annotation + * @build jdk.test.lib.* ReservedStackTest + * @run main/othervm -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-Inline -XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread ReservedStackTest + * @run main/othervm -XX:-TieredCompilation -XX:-Inline -XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread ReservedStackTest + */ + +// Intentionally left blank. Just runs ReservedStackTest with @requires annotation. diff --git a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Clazz.java b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Clazz.java index 42b96b6b0d4..1b6e8afc803 100644 --- a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Clazz.java +++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Clazz.java @@ -72,6 +72,6 @@ class Clazz extends ClassConstruct { public Clazz(String name, String extending, int access, int classFileVersion, int index, String... implementing) { super(name, extending == null ? "java/lang/Object" : extending, access + ACC_SUPER, classFileVersion, index, implementing); // Add the default constructor - addMethod("", "()V", ACC_PUBLIC).makeConstructor(extending); + addMethod("", "()V", ACC_PUBLIC).makeConstructor(extending, false); } } diff --git a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Method.java b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Method.java index c09ce0fcc7d..428475dfd8a 100644 --- a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Method.java +++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Method.java @@ -59,14 +59,12 @@ class Method { private final String ownerClassName; private final ClassVisitor cv; private final MethodVisitor mv; - private final boolean isInterface; private final ClassBuilder.ExecutionMode execMode; public Method(ClassConstruct ownerClass, ClassVisitor cv, String name, String descriptor, int access, ClassBuilder.ExecutionMode execMode) { this.ownerClassName = ownerClass.getName(); this.ownerClass = ownerClass; - this.isInterface = ownerClass.isInterface(); this.execMode = execMode; this.cv = cv; mv = cv.visitMethod(access, name, descriptor, null, null); @@ -91,12 +89,12 @@ class Method { public void makeSuperCallMethod(int invokeInstruction, String className) { mv.visitVarInsn(ALOAD, 0); - makeCall(invokeInstruction, className); + makeCall(invokeInstruction, className, false); mv.visitInsn(POP); done(); } - public void defaultInvoke(int instr, String className, String objectRef) { + public void defaultInvoke(int instr, String className, String objectRef, boolean isInterface) { switch (instr) { case INVOKEVIRTUAL: defaultInvokeVirtual(className, objectRef); @@ -105,10 +103,10 @@ class Method { defaultInvokeInterface(className, objectRef); break; case INVOKESTATIC: - defaultInvokeStatic(className); + defaultInvokeStatic(className, isInterface); break; case INVOKESPECIAL: - defaultInvokeSpecial(className, objectRef); + defaultInvokeSpecial(className, objectRef, isInterface); break; default: break; @@ -118,30 +116,26 @@ class Method { mv.visitEnd(); } - public void defaultInvokeVirtual(String className, String objectRef) { + private void defaultInvokeVirtual(String className, String objectRef) { String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/")); makeNewObject(objectRef, objectRefPackageName); makeCall(INVOKEVIRTUAL, className, false); } - public void defaultInvokeInterface(String className, String objectRef) { + private void defaultInvokeInterface(String className, String objectRef) { String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/")); makeNewObject(objectRef, objectRefPackageName); makeCall(INVOKEINTERFACE, className, true); } - public void defaultInvokeSpecial(String className, String objectRef) { + private void defaultInvokeSpecial(String className, String objectRef, boolean isInterface) { String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/")); makeNewObject(objectRef, objectRefPackageName); - makeCall(INVOKESPECIAL, className, false); + makeCall(INVOKESPECIAL, className, isInterface); } - public void defaultInvokeStatic(String className) { - makeCall(INVOKESTATIC, className); - } - - private Method makeCall(int invokeInstruction, String className) { - return makeCall(invokeInstruction, className, isInterface); + private void defaultInvokeStatic(String className, boolean isInterface) { + makeCall(INVOKESTATIC, className, isInterface); } private Method makeCall(int invokeInstruction, String className, boolean isInterface) { @@ -219,7 +213,7 @@ class Method { String className = objectRef.substring(objectRef.lastIndexOf("/") + 1); makeStaticCall( objectRefPackageName + "/Helper", "get" + className, - "()L" + objectRef + ";"); + "()L" + objectRef + ";", false); mv.visitVarInsn(ASTORE, 1); mv.visitVarInsn(ALOAD, 1); } @@ -236,12 +230,12 @@ class Method { mv.visitEnd(); } - public Method makeStaticCall(String classname, String method, String descriptor) { + public Method makeStaticCall(String classname, String method, String descriptor, boolean isInterface) { mv.visitMethodInsn(INVOKESTATIC, classname, method, descriptor, isInterface); return this; } - public void makeConstructor(String extending) { + public void makeConstructor(String extending, boolean isInterface) { mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, extending == null ? "java/lang/Object" : extending, "", "()V", isInterface); mv.visitInsn(RETURN); diff --git a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java index a24a91fe0a2..894d053e0cc 100644 --- a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java +++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java @@ -53,9 +53,10 @@ class TestBuilder extends Builder { Method m = clazz.addMethod("test", "()Ljava/lang/Integer;", ACC_PUBLIC + ACC_STATIC, execMode); m.defaultInvoke(getInvokeInstruction(testcase.invoke), getName(testcase.methodref), - getName(testcase.objectref)); + getName(testcase.objectref), + testcase.hier.isInterface(testcase.methodref)); - mainMethod.makeStaticCall(clazz.getName(), "test", "()Ljava/lang/Integer;").done(); + mainMethod.makeStaticCall(clazz.getName(), "test", "()Ljava/lang/Integer;", false).done(); } private static int getInvokeInstruction(SelectionResolutionTestCase.InvokeInstruction instr) { diff --git a/hotspot/test/runtime/modules/AccessCheck/CheckRead.java b/hotspot/test/runtime/modules/AccessCheck/CheckRead.java index bfe8a0fc823..71435b1718f 100644 --- a/hotspot/test/runtime/modules/AccessCheck/CheckRead.java +++ b/hotspot/test/runtime/modules/AccessCheck/CheckRead.java @@ -103,7 +103,7 @@ public class CheckRead { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java index 10196ded9fe..3342d8f9073 100644 --- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java +++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java @@ -103,7 +103,7 @@ public class DiffCL_CheckRead { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java index 5310abc1974..3d2bb9eda86 100644 --- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java +++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java @@ -105,7 +105,7 @@ public class DiffCL_ExpQualOther { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java index 71359b019dc..5854c4530ea 100644 --- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java +++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java @@ -91,7 +91,7 @@ public class DiffCL_ExpQualToM1 { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java index 4d8db6bf1b8..57490768b2f 100644 --- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java +++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java @@ -92,7 +92,7 @@ public class DiffCL_ExpUnqual { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java index fafb2aeb738..9b1bd9613cc 100644 --- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java +++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java @@ -91,7 +91,7 @@ public class DiffCL_PkgNotExp { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java index d3c746fde31..09488b60327 100644 --- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java +++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java @@ -92,7 +92,7 @@ public class DiffCL_Umod { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); MyDiffClassLoader.loader1 = new MyDiffClassLoader(); MyDiffClassLoader.loader2 = new MyDiffClassLoader(); @@ -141,7 +141,7 @@ public class DiffCL_Umod { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); MyDiffClassLoader.loader1 = new MyDiffClassLoader(); MyDiffClassLoader.loader2 = new MyDiffClassLoader(); @@ -190,7 +190,7 @@ public class DiffCL_Umod { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); MyDiffClassLoader.loader1 = new MyDiffClassLoader(); MyDiffClassLoader.loader2 = new MyDiffClassLoader(); diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java index 8c9629b16b8..3ce98422ec6 100644 --- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java +++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java @@ -87,7 +87,7 @@ public class DiffCL_UmodUpkg { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); MyDiffClassLoader.loader1 = new MyDiffClassLoader(); MyDiffClassLoader.loader2 = new MyDiffClassLoader(); @@ -136,7 +136,7 @@ public class DiffCL_UmodUpkg { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); MyDiffClassLoader.loader1 = new MyDiffClassLoader(); MyDiffClassLoader.loader2 = new MyDiffClassLoader(); diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java index c9003ad2cd5..5cf5132ece9 100644 --- a/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java +++ b/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java @@ -105,7 +105,7 @@ public class ExpQualOther { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java b/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java index 755ffe15133..4a7822fb4d7 100644 --- a/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java +++ b/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java @@ -81,7 +81,7 @@ public class ExpQualToM1 { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to the same class loader for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java index 7f1c1d918a1..67e69ea42e0 100644 --- a/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java +++ b/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java @@ -81,7 +81,7 @@ public class ExpUnqual { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to the same class loader for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java index 97133f3ebaa..3762f13b696 100644 --- a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java +++ b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java @@ -93,7 +93,7 @@ public class ExportAllUnnamed { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java index 04fbbead02d..0b044974fa8 100644 --- a/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java +++ b/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java @@ -91,7 +91,7 @@ public class PkgNotExp { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to the same class loader for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod.java b/hotspot/test/runtime/modules/AccessCheck/Umod.java index 4610da62954..c61bcf45896 100644 --- a/hotspot/test/runtime/modules/AccessCheck/Umod.java +++ b/hotspot/test/runtime/modules/AccessCheck/Umod.java @@ -92,7 +92,7 @@ public class Umod { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map module m1 to class loader. // class c2 will be loaded in an unnamed module/loader. @@ -138,7 +138,7 @@ public class Umod { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); MySameClassLoader loader = new MySameClassLoader(); // map module m1 to class loader. @@ -184,7 +184,7 @@ public class Umod { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); MySameClassLoader loader = new MySameClassLoader(); // map module m1 to class loader. diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java index d9e578c750b..cde2644146d 100644 --- a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java +++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java @@ -92,7 +92,7 @@ public class UmodDiffCL_ExpQualOther { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java index c17e07f959e..93b2f14428a 100644 --- a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java +++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java @@ -92,7 +92,7 @@ public class UmodDiffCL_ExpUnqual { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java index fd5e090c011..aca576bd721 100644 --- a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java +++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java @@ -91,7 +91,7 @@ public class UmodDiffCL_PkgNotExp { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java b/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java index 102236618e1..36035e9c4d2 100644 --- a/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java +++ b/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java @@ -87,7 +87,7 @@ public class UmodUPkg { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map module m1 to class loader. // class c4 will be loaded in an unnamed module/loader. @@ -133,7 +133,7 @@ public class UmodUPkg { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); MySameClassLoader loader = new MySameClassLoader(); // map module m1 to class loader. diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java index 15a0e0105bf..ed81b24fc7f 100644 --- a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java +++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java @@ -92,7 +92,7 @@ public class UmodUpkgDiffCL_ExpQualOther { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java index 30ae3fb18c2..11d42b74673 100644 --- a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java +++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java @@ -91,7 +91,7 @@ public class UmodUpkgDiffCL_NotExp { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java index e7a51e3438a..8ea1cdd1daa 100644 --- a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java +++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java @@ -101,7 +101,7 @@ public class UmodUpkg_ExpQualOther { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java index 5bab4fc8bc9..ebf9b5e8a2a 100644 --- a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java +++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java @@ -89,7 +89,7 @@ public class UmodUpkg_NotExp { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to the same class loader for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java index 3f827e93c3c..3c58cdb1a34 100644 --- a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java +++ b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java @@ -101,7 +101,7 @@ public class Umod_ExpQualOther { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java index fe3c88526d7..6f8f83f0e59 100644 --- a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java +++ b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java @@ -91,7 +91,7 @@ public class Umod_ExpUnqual { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to differing class loaders for this test Map map = new HashMap<>(); diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java index d1b2a223f63..90c071cb345 100644 --- a/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java +++ b/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java @@ -89,7 +89,7 @@ public class Umod_PkgNotExp { // Resolves "m1" Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); // map each module to the same class loader for this test Map map = new HashMap<>(); diff --git a/hotspot/test/serviceability/dcmd/vm/SetVMFlagTest.java b/hotspot/test/serviceability/dcmd/vm/SetVMFlagTest.java index 9132aece076..663a7bc6a2f 100644 --- a/hotspot/test/serviceability/dcmd/vm/SetVMFlagTest.java +++ b/hotspot/test/serviceability/dcmd/vm/SetVMFlagTest.java @@ -56,6 +56,25 @@ public class SetVMFlagTest { run(new JMXExecutor()); } + private void setMutableFlagInternal(CommandExecutor executor, String flag, + boolean val, boolean isNumeric) { + String strFlagVal; + if (isNumeric) { + strFlagVal = val ? "1" : "0"; + } else { + strFlagVal = val ? "true" : "false"; + } + + OutputAnalyzer out = executor.execute("VM.set_flag " + flag + " " + strFlagVal); + out.stderrShouldBeEmpty(); + + out = getAllFlags(executor); + + String newFlagVal = out.firstMatch(MANAGEABLE_PATTERN.replace("(\\S+)", flag), 1); + + assertNotEquals(newFlagVal, val ? "1" : "0"); + } + private void setMutableFlag(CommandExecutor executor) { OutputAnalyzer out = getAllFlags(executor); String flagName = out.firstMatch(MANAGEABLE_PATTERN, 1); @@ -69,15 +88,8 @@ public class SetVMFlagTest { } Boolean blnVal = Boolean.parseBoolean(flagVal); - - out = executor.execute("VM.set_flag " + flagName + " " + (blnVal ? 0 : 1)); - out.stderrShouldBeEmpty(); - - out = getAllFlags(executor); - - String newFlagVal = out.firstMatch(MANAGEABLE_PATTERN.replace("(\\S+)", flagName), 1); - - assertNotEquals(newFlagVal, flagVal); + setMutableFlagInternal(executor, flagName, !blnVal, true); + setMutableFlagInternal(executor, flagName, blnVal, false); } private void setMutableFlagWithInvalidValue(CommandExecutor executor) { @@ -95,7 +107,7 @@ public class SetVMFlagTest { // a boolean flag accepts only 0/1 as its value out = executor.execute("VM.set_flag " + flagName + " unexpected_value"); out.stderrShouldBeEmpty(); - out.stdoutShouldContain("flag value must be a boolean (1 or 0)"); + out.stdoutShouldContain("flag value must be a boolean (1/0 or true/false)"); out = getAllFlags(executor); diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 3bef243c570..e447d080f2b 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -361,3 +361,5 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 9d71d20e614777cd23c1a43b38b5c08a9094d27a jdk-9+116 46b57560cd06ebcdd21489250628ff5f9d9d8916 jdk-9+117 a8aa25fc6c5fda0ed7a93b8ffee62da326a752fc jdk-9+118 +f92e8518bb34a9628b11e662bf7308561a55eb3b jdk-9+119 +ecbe72546137cd29cb73d4dcc81cc099e847d543 jdk-9+120 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java index 5563a90c7ec..0750429a33b 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java @@ -427,7 +427,7 @@ public final class TemplatesImpl implements Templates, Serializable { Layer bootLayer = Layer.boot(); Configuration cf = bootLayer.configuration() - .resolveRequires(finder, ModuleFinder.empty(), Set.of(mn)); + .resolveRequires(finder, ModuleFinder.of(), Set.of(mn)); PrivilegedAction pa = () -> bootLayer.defineModules(cf, name -> loader); Layer layer = AccessController.doPrivileged(pa); diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java index 131d87e354f..08e7f417256 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ final class CatalogResolverImpl implements CatalogResolver { publicId = Normalizer.normalizePublicId(Normalizer.decodeURN(Util.getNotNullOrEmpty(publicId))); //check whether systemId is an urn - if (systemId != null && systemId.startsWith("urn:publicid:")) { + if (systemId != null && systemId.startsWith(Util.URN)) { systemId = Normalizer.decodeURN(systemId); if (publicId != null && !publicId.equals(systemId)) { systemId = null; @@ -67,7 +67,7 @@ final class CatalogResolverImpl implements CatalogResolver { } CatalogImpl c = (CatalogImpl)catalog; - String resolvedSystemId = resolve(c, publicId, systemId); + String resolvedSystemId = Util.resolve(c, publicId, systemId); if (resolvedSystemId != null) { return new InputSource(resolvedSystemId); @@ -86,55 +86,4 @@ final class CatalogResolverImpl implements CatalogResolver { return null; } - /** - * Resolves the publicId or systemId using public or system entries in the catalog. - * - * The resolution follows the following rules determined by the prefer setting: - * - * prefer "system": attempts to resolve with a system entry; - * attempts to resolve with a public entry when only - * publicId is specified. - * - * prefer "public": attempts to resolve with a system entry; - * attempts to resolve with a public entry if no matching - * system entry is found. - * @param catalog the catalog - * @param publicId the publicId - * @param systemId the systemId - * @return the resolved systemId if a match is found, null otherwise - */ - String resolve(CatalogImpl catalog, String publicId, String systemId) { - String resolvedSystemId = null; - - //search the current catalog - catalog.reset(); - if (systemId != null) { - /* - If a system identifier is specified, it is used no matter how - prefer is set. - */ - resolvedSystemId = catalog.matchSystem(systemId); - } - - if (resolvedSystemId == null && publicId != null) { - resolvedSystemId = catalog.matchPublic(publicId); - } - - //mark the catalog as having been searched before trying alternatives - catalog.markAsSearched(); - - //search alternative catalogs - if (resolvedSystemId == null) { - Iterator iter = catalog.catalogs().iterator(); - while (iter.hasNext()) { - resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId); - if (resolvedSystemId != null) { - break; - } - - } - } - - return resolvedSystemId; - } } diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogUriResolverImpl.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogUriResolverImpl.java index e7cb9bcf1a7..497aacf18fd 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogUriResolverImpl.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogUriResolverImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,18 +65,30 @@ final class CatalogUriResolverImpl implements CatalogUriResolver { if (href == null) return null; + String result = null; CatalogImpl c = (CatalogImpl)catalog; String uri = Normalizer.normalizeURI(href); - String result; - - //remove fragment if any. - int hashPos = uri.indexOf("#"); - if (hashPos >= 0) { - uri = uri.substring(0, hashPos); + //check whether uri is an urn + if (uri != null && uri.startsWith(Util.URN)) { + String publicId = Normalizer.decodeURN(uri); + if (publicId != null) { + result = Util.resolve(c, publicId, null); + } } - //search the current catalog - result = resolve(c, uri); + //if no match with a public id, continue search for an URI + if (result == null) { + //remove fragment if any. + int hashPos = uri.indexOf("#"); + if (hashPos >= 0) { + uri = uri.substring(0, hashPos); + } + + //search the current catalog + result = resolve(c, uri); + } + + //Report error or return the URI as is when no match is found if (result == null) { GroupEntry.ResolveType resolveType = c.getResolve(); switch (resolveType) { diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java index 0ebf25e4207..2c1a59c360c 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -298,6 +298,9 @@ class GroupEntry extends BaseEntry { case PUBLIC: match = ((PublicEntry) entry).match(publicId); break; + case URI: + match = ((UriEntry) entry).match(publicId); + break; case GROUP: match = ((GroupEntry) entry).matchPublic(publicId); break; diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java index 6beb4a8287d..d5b19930c01 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java @@ -100,7 +100,7 @@ class Normalizer { } catch (UnsupportedEncodingException ex) { CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex); } - return "urn:publicid:" + urn; + return Util.URN + urn; } /** @@ -114,7 +114,7 @@ class Normalizer { static String decodeURN(String urn) { String publicId; - if (urn != null && urn.startsWith("urn:publicid:")) { + if (urn != null && urn.startsWith(Util.URN)) { publicId = urn.substring(13); } else { return urn; diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java index 498b7ae4ce1..0c1aa295c9c 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,11 @@ final class UriEntry extends BaseEntry { */ public void setName(String name) { CatalogMessages.reportNPEOnNull("name", name); - this.name = Normalizer.normalizeURI(name); + if (name.startsWith(Util.PUBLICID_PREFIX) || name.startsWith(Util.PUBLICID_PREFIX_ALT)) { + this.name = Normalizer.normalizePublicId(name); + } else { + this.name = Normalizer.normalizeURI(name); + } } /** @@ -72,6 +76,7 @@ final class UriEntry extends BaseEntry { public String getName() { return name; } + /** * Get the uri attribute. * @return The uri attribute value. diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java index f0fd1fdbf33..b164f674dbd 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java @@ -31,6 +31,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Iterator; import jdk.xml.internal.SecuritySupport; /** @@ -38,6 +39,61 @@ import jdk.xml.internal.SecuritySupport; * @since 9 */ class Util { + final static String URN = "urn:publicid:"; + final static String PUBLICID_PREFIX = "-//"; + final static String PUBLICID_PREFIX_ALT = "+//"; + + /** + * Finds an entry in the catalog that matches with the publicId or systemId. + * + * The resolution follows the following rules determined by the prefer setting: + * + * prefer "system": attempts to resolve with a system entry; + * attempts to resolve with a public entry when only + * publicId is specified. + * + * prefer "public": attempts to resolve with a system entry; + * attempts to resolve with a public entry if no matching + * system entry is found. + * @param catalog the catalog + * @param publicId the publicId + * @param systemId the systemId + * @return the resolved systemId if a match is found, null otherwise + */ + static String resolve(CatalogImpl catalog, String publicId, String systemId) { + String resolvedSystemId = null; + + //search the current catalog + catalog.reset(); + if (systemId != null) { + /* + If a system identifier is specified, it is used no matter how + prefer is set. + */ + resolvedSystemId = catalog.matchSystem(systemId); + } + + if (resolvedSystemId == null && publicId != null) { + resolvedSystemId = catalog.matchPublic(publicId); + } + + //mark the catalog as having been searched before trying alternatives + catalog.markAsSearched(); + + //search alternative catalogs + if (resolvedSystemId == null) { + Iterator iter = catalog.catalogs().iterator(); + while (iter.hasNext()) { + resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId); + if (resolvedSystemId != null) { + break; + } + + } + } + + return resolvedSystemId; + } /** * Resolves the specified file path to an absolute systemId. If it is diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/package.html b/jaxp/src/java.xml/share/classes/org/w3c/dom/package.html index a95de6c6ea7..673366bf326 100644 --- a/jaxp/src/java.xml/share/classes/org/w3c/dom/package.html +++ b/jaxp/src/java.xml/share/classes/org/w3c/dom/package.html @@ -4,9 +4,9 @@ Provides the interfaces for the Document Object Model (DOM). Supports the -Document Object Model Level 2 Core APIi, -Document Object Model (DOM) Level 3 Core, -and Document Object Model (DOM) Level 3 Load and Save. +Document Object Model (DOM) Level 2 Core Specification, +Document Object Model (DOM) Level 3 Core Specification, +and Document Object Model (DOM) Level 3 Load and Save Specification. @since 1.4 diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSS2Properties.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSS2Properties.java index d22de1d5182..56c63fa06d8 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSS2Properties.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSS2Properties.java @@ -92,7 +92,7 @@ import org.w3c.dom.DOMException; * property with a value of "menu", querying for the values of the component * longhand properties should return the empty string. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSS2Properties { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSCharsetRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSCharsetRule.java index 10a64ab98ed..1241cacdf5f 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSCharsetRule.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSCharsetRule.java @@ -59,7 +59,7 @@ import org.w3c.dom.DOMException; * header, has priority (see CSS document representation) but this is not * reflected in the CSSCharsetRule. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSCharsetRule extends CSSRule { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSFontFaceRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSFontFaceRule.java index b4f6892c8a9..1a7e1a1c20c 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSFontFaceRule.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSFontFaceRule.java @@ -46,7 +46,7 @@ package org.w3c.dom.css; * a CSS style sheet. The @font-face rule is used to hold a set * of font descriptions. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSFontFaceRule extends CSSRule { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSImportRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSImportRule.java index a9d321a91a2..e81d9a0f583 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSImportRule.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSImportRule.java @@ -48,7 +48,7 @@ import org.w3c.dom.stylesheets.MediaList; * a CSS style sheet. The @import rule is used to import style * rules from other style sheets. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSImportRule extends CSSRule { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSMediaRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSMediaRule.java index bf153d92321..b102a8a57b8 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSMediaRule.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSMediaRule.java @@ -49,7 +49,7 @@ import org.w3c.dom.stylesheets.MediaList; * style sheet. A @media rule can be used to delimit style * rules for specific media types. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSMediaRule extends CSSRule { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPageRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPageRule.java index 773b7463ce5..fc73252dcb5 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPageRule.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPageRule.java @@ -48,7 +48,7 @@ import org.w3c.dom.DOMException; * CSS style sheet. The @page rule is used to specify the * dimensions, orientation, margins, etc. of a page box for paged media. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSPageRule extends CSSRule { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPrimitiveValue.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPrimitiveValue.java index 3078d724cbf..2646a032d66 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPrimitiveValue.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPrimitiveValue.java @@ -61,7 +61,7 @@ import org.w3c.dom.DOMException; * the range 0-255, a color percentage value can be converted to a number; * (see also the RGBColor interface). *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSPrimitiveValue extends CSSValue { // UnitTypes diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRule.java index f81d0d509f4..338f490eb77 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRule.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRule.java @@ -50,7 +50,7 @@ import org.w3c.dom.DOMException; * sheet, even if the rule is not recognized by the parser. Unrecognized * rules are represented using the CSSUnknownRule interface. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSRule { // RuleType diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRuleList.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRuleList.java index 33840ef3314..dd6f033bfd4 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRuleList.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRuleList.java @@ -47,7 +47,7 @@ package org.w3c.dom.css; *

The items in the CSSRuleList are accessible via an * integral index, starting from 0. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSRuleList { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleDeclaration.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleDeclaration.java index de63268f838..c6bd17f9b2d 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleDeclaration.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleDeclaration.java @@ -60,7 +60,7 @@ import org.w3c.dom.DOMException; * interface. The CSS Object Model doesn't provide an access to the * specified or actual values of the CSS cascade. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSStyleDeclaration { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleRule.java index e165cd18928..5e0e92dcd86 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleRule.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleRule.java @@ -47,7 +47,7 @@ import org.w3c.dom.DOMException; * The CSSStyleRule interface represents a single rule set in a * CSS style sheet. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSStyleRule extends CSSRule { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleSheet.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleSheet.java index d3cf723367e..2c021dc6c45 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleSheet.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleSheet.java @@ -49,7 +49,7 @@ import org.w3c.dom.stylesheets.StyleSheet; * represent a CSS style sheet i.e., a style sheet whose content type is * "text/css". *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSStyleSheet extends StyleSheet { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSUnknownRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSUnknownRule.java index 0b1d87be9c3..8b7b3f6d29e 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSUnknownRule.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSUnknownRule.java @@ -45,7 +45,7 @@ package org.w3c.dom.css; * The CSSUnknownRule interface represents an at-rule not * supported by this user agent. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSUnknownRule extends CSSRule { } diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValue.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValue.java index ae4effa0fa2..54aa703ffe9 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValue.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValue.java @@ -48,7 +48,7 @@ import org.w3c.dom.DOMException; * value. A CSSValue object only occurs in a context of a CSS * property. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSValue { // UnitTypes diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValueList.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValueList.java index 1567399d734..db62e1c7c9e 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValueList.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValueList.java @@ -50,7 +50,7 @@ package org.w3c.dom.css; *

The items in the CSSValueList are accessible via an * integral index, starting from 0. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface CSSValueList extends CSSValue { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Counter.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Counter.java index 44a299307c7..9da6a1980b4 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Counter.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Counter.java @@ -46,7 +46,7 @@ package org.w3c.dom.css; * counters function value. This interface reflects the values in the * underlying style property. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface Counter { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DOMImplementationCSS.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DOMImplementationCSS.java index 2aeb37e3ede..b047fcb0f55 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DOMImplementationCSS.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DOMImplementationCSS.java @@ -49,7 +49,7 @@ import org.w3c.dom.DOMException; * outside the context of a document. There is no way to associate the new * CSSStyleSheet with a document in DOM Level 2. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface DOMImplementationCSS extends DOMImplementation { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DocumentCSS.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DocumentCSS.java index 47399a77716..f68b9e2d458 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DocumentCSS.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DocumentCSS.java @@ -62,7 +62,7 @@ import org.w3c.dom.stylesheets.DocumentStyle; * interface can be obtained by using binding-specific casting methods on an * instance of the Document interface. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface DocumentCSS extends DocumentStyle { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ElementCSSInlineStyle.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ElementCSSInlineStyle.java index c7e70539f1e..2822d91df9b 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ElementCSSInlineStyle.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ElementCSSInlineStyle.java @@ -50,7 +50,7 @@ package org.w3c.dom.css; * binding-specific casting methods on an instance of the Element interface * when the element supports inline CSS style informations. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface ElementCSSInlineStyle { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/RGBColor.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/RGBColor.java index 7d374581264..00bb4514c25 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/RGBColor.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/RGBColor.java @@ -55,7 +55,7 @@ package org.w3c.dom.css; *

A color percentage value can always be converted to a number and vice * versa. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface RGBColor { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Rect.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Rect.java index b9e69563002..e8e0a73db15 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Rect.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Rect.java @@ -47,7 +47,7 @@ package org.w3c.dom.css; * modifications made to the CSSPrimitiveValue objects modify * the style property. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface Rect { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ViewCSS.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ViewCSS.java index 38b22b30d40..caf705c9e61 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ViewCSS.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ViewCSS.java @@ -55,7 +55,7 @@ import org.w3c.dom.views.AbstractView; * CSSStyleDeclaration and CSSValue related to * this declaration are no longer valid. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface ViewCSS extends AbstractView { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAnchorElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAnchorElement.java index 8e4f6e797ce..9eb9f85c167 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAnchorElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAnchorElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * The anchor element. See the A element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLAnchorElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAppletElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAppletElement.java index d1593195640..21ab47b9789 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAppletElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAppletElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * An embedded Java applet. See the APPLET element definition in HTML 4.0. * This element is deprecated in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLAppletElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAreaElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAreaElement.java index f51cc31b0f4..743d3991a18 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAreaElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAreaElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Client-side image map area definition. See the AREA element definition in * HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLAreaElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBRElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBRElement.java index f35212f90b6..3745d48ec6b 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBRElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBRElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Force a line break. See the BR element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLBRElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseElement.java index 69f518b08dd..473b492e66d 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Document base URI. See the BASE element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLBaseElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseFontElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseFontElement.java index 68ed6114faf..327ef9d6e4d 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseFontElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseFontElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Base font. See the BASEFONT element definition in HTML 4.0. This element * is deprecated in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLBaseFontElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBodyElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBodyElement.java index d0f2e450fc6..ad14b86d9fc 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBodyElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBodyElement.java @@ -46,6 +46,8 @@ package org.w3c.dom.html; * even if the tags are not present in the source document. See the BODY * element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLBodyElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLButtonElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLButtonElement.java index 8d45dbf7760..578b68605fb 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLButtonElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLButtonElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Push button. See the BUTTON element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLButtonElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLCollection.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLCollection.java index 1c87fd9624c..f59ae97a804 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLCollection.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLCollection.java @@ -50,6 +50,8 @@ import org.w3c.dom.Node; * to be live meaning that they are automatically updated when the * underlying document is changed. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLCollection { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDListElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDListElement.java index 8e0dad949e8..3b7475817e7 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDListElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDListElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Definition list. See the DL element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLDListElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDOMImplementation.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDOMImplementation.java index 4d155416166..698f097de97 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDOMImplementation.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDOMImplementation.java @@ -47,7 +47,8 @@ import org.w3c.dom.DOMImplementation; * The HTMLDOMImplementation interface extends the * DOMImplementation interface with a method for creating an * HTML document instance. - * @since DOM Level 2 + * + * @since 1.4, DOM Level 2 */ public interface HTMLDOMImplementation extends DOMImplementation { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDirectoryElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDirectoryElement.java index 0fb33900004..19fbc96b023 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDirectoryElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDirectoryElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Directory list. See the DIR element definition in HTML 4.0. This element * is deprecated in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLDirectoryElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDivElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDivElement.java index ee1b727ebce..f204f284a2e 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDivElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDivElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Generic block container. See the DIV element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLDivElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDocument.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDocument.java index 5116fc539b1..06e6eb7c6ae 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDocument.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDocument.java @@ -55,6 +55,8 @@ import org.w3c.dom.NodeList; * getElementById is inherited from the Document * interface where it was moved. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLDocument extends Document { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLElement.java index b5b178a6c94..cc0727ee570 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLElement.java @@ -53,6 +53,8 @@ import org.w3c.dom.Element; * of an HTML element is accessible through the * ElementCSSInlineStyle interface which is defined in the . *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLElement extends Element { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFieldSetElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFieldSetElement.java index cb2c0bd4090..0c650d1d970 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFieldSetElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFieldSetElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Organizes form controls into logical groups. See the FIELDSET element * definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLFieldSetElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFontElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFontElement.java index c8fc157837f..b9a0c7b919c 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFontElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFontElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Local change to font. See the FONT element definition in HTML 4.0. This * element is deprecated in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLFontElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFormElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFormElement.java index 42e2edd2944..0c00bd27334 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFormElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFormElement.java @@ -47,6 +47,8 @@ package org.w3c.dom.html; * as well as the attributes of the form element. See the FORM element * definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLFormElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameElement.java index 5ffa4252484..92891a90c32 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameElement.java @@ -46,6 +46,8 @@ import org.w3c.dom.Document; /** * Create a frame. See the FRAME element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLFrameElement extends HTMLElement { /** @@ -107,7 +109,7 @@ public interface HTMLFrameElement extends HTMLElement { /** * The document this frame contains, if there is any and it is available, * or null otherwise. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public Document getContentDocument(); diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameSetElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameSetElement.java index fb6f7e988aa..60112d7ada8 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameSetElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameSetElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Create a grid of frames. See the FRAMESET element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLFrameSetElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHRElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHRElement.java index 334c04ded25..c0fbfda600e 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHRElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHRElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Create a horizontal rule. See the HR element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLHRElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadElement.java index 8894d32555b..319e6a58741 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Document head information. See the HEAD element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLHeadElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadingElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadingElement.java index 0cd4efebb11..f46bf5b0a95 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadingElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadingElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * For the H1 to H6 elements. See the H1 element * definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLHeadingElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHtmlElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHtmlElement.java index a2fa379dd4f..75a6cfa80f1 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHtmlElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHtmlElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Root of an HTML document. See the HTML element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLHtmlElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIFrameElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIFrameElement.java index 08c198869d8..7a7ffd64d99 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIFrameElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIFrameElement.java @@ -46,6 +46,8 @@ import org.w3c.dom.Document; /** * Inline subwindows. See the IFRAME element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLIFrameElement extends HTMLElement { /** @@ -120,7 +122,7 @@ public interface HTMLIFrameElement extends HTMLElement { /** * The document this frame contains, if there is any and it is available, * or null otherwise. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public Document getContentDocument(); diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLImageElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLImageElement.java index 7fced61b712..238464de945 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLImageElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLImageElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Embedded image. See the IMG element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLImageElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLInputElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLInputElement.java index b58d8b8fe40..15d6d035184 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLInputElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLInputElement.java @@ -48,6 +48,8 @@ package org.w3c.dom.html; * be masked to prevent unauthorized use. See the INPUT element definition * in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLInputElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIsIndexElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIsIndexElement.java index 111edde09a5..2766c9ee8ec 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIsIndexElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIsIndexElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * This element is used for single-line text input. See the ISINDEX element * definition in HTML 4.0. This element is deprecated in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLIsIndexElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLIElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLIElement.java index f4113f1bbca..e368c51797c 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLIElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLIElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * List item. See the LI element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLLIElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLabelElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLabelElement.java index d3fd6bea44f..d9bc78a5d15 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLabelElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLabelElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Form field label text. See the LABEL element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLLabelElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLegendElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLegendElement.java index ffe0816295c..f9b54902d83 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLegendElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLegendElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Provides a caption for a FIELDSET grouping. See the LEGEND * element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLLegendElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLinkElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLinkElement.java index cc03164243f..0824d0c823a 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLinkElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLinkElement.java @@ -47,6 +47,8 @@ package org.w3c.dom.html; * See the LINK element definition in HTML 4.0 (see also the * LinkStyle interface in the module). *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLLinkElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMapElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMapElement.java index f2b42224186..cb834e64872 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMapElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMapElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Client-side image map. See the MAP element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLMapElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMenuElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMenuElement.java index b5798796e3c..cd7ea2b2108 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMenuElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMenuElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Menu list. See the MENU element definition in HTML 4.0. This element is * deprecated in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLMenuElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMetaElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMetaElement.java index 38920e452c3..4b6e2538448 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMetaElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMetaElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * This contains generic meta-information about the document. See the META * element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLMetaElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLModElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLModElement.java index cfd96a1090b..17e36db665d 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLModElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLModElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Notice of modification to part of a document. See the INS and DEL * element definitions in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLModElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOListElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOListElement.java index 728e760faef..9599c48182a 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOListElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOListElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Ordered list. See the OL element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLOListElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLObjectElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLObjectElement.java index 972091bfe9f..2e1e631dfa2 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLObjectElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLObjectElement.java @@ -49,6 +49,8 @@ import org.w3c.dom.Document; * read-only once the underlying object is instantiated. See the OBJECT * element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLObjectElement extends HTMLElement { /** @@ -181,7 +183,7 @@ public interface HTMLObjectElement extends HTMLElement { /** * The document this object contains, if there is any and it is * available, or null otherwise. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public Document getContentDocument(); diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptGroupElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptGroupElement.java index edddf36c7ad..de00e8ca038 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptGroupElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptGroupElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Group options together in logical subdivisions. See the OPTGROUP element * definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLOptGroupElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptionElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptionElement.java index 273658837e8..22e348bdfdf 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptionElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptionElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * A selectable choice. See the OPTION element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLOptionElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParagraphElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParagraphElement.java index a7dc5d6bcdb..c5e43b4d8f6 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParagraphElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParagraphElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Paragraphs. See the P element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLParagraphElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParamElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParamElement.java index 6b18476212c..b7b86648dd3 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParamElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParamElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Parameters fed to the OBJECT element. See the PARAM element * definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLParamElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLPreElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLPreElement.java index 40b199f5341..a8bce79253f 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLPreElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLPreElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Preformatted text. See the PRE element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLPreElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLQuoteElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLQuoteElement.java index 61abf1f6d08..db0b10de891 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLQuoteElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLQuoteElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * For the Q and BLOCKQUOTE elements. See the Q * element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLQuoteElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLScriptElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLScriptElement.java index 5004a41c07a..9931a02817d 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLScriptElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLScriptElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Script statements. See the SCRIPT element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLScriptElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLSelectElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLSelectElement.java index 9611cca1d24..85d6c21ea1d 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLSelectElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLSelectElement.java @@ -48,6 +48,8 @@ import org.w3c.dom.DOMException; * options can be directly accessed through the select element as a * collection. See the SELECT element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLSelectElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLStyleElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLStyleElement.java index d811e854b4e..5e7b99fb38f 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLStyleElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLStyleElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Style information. See the STYLE element definition in HTML 4.0, the * module and the LinkStyle interface in the module. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLStyleElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCaptionElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCaptionElement.java index b800137a3c1..f2126d36091 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCaptionElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCaptionElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Table caption See the CAPTION element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLTableCaptionElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCellElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCellElement.java index b7debbf70ab..53b41023e50 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCellElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCellElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * The object used to represent the TH and TD * elements. See the TD element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLTableCellElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableColElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableColElement.java index d7ece0ff308..fcf413f5270 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableColElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableColElement.java @@ -45,6 +45,8 @@ package org.w3c.dom.html; * Regroups the COL and COLGROUP elements. See the * COL element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLTableColElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableElement.java index f57d51cdfaa..d73421aba5c 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableElement.java @@ -52,6 +52,8 @@ import org.w3c.dom.DOMException; * existing THead or TFoot element. See the TABLE element definition in HTML * 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLTableElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableRowElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableRowElement.java index a24ff429264..fed6b205b2c 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableRowElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableRowElement.java @@ -46,6 +46,8 @@ import org.w3c.dom.DOMException; /** * A row in a table. See the TR element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLTableRowElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableSectionElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableSectionElement.java index f6c3cfa17d3..e68156d35eb 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableSectionElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableSectionElement.java @@ -47,6 +47,8 @@ import org.w3c.dom.DOMException; * The THEAD , TFOOT , and TBODY * elements. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLTableSectionElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTextAreaElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTextAreaElement.java index 1546a7dacf6..85afebaaa21 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTextAreaElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTextAreaElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Multi-line text field. See the TEXTAREA element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLTextAreaElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTitleElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTitleElement.java index 9b3c1cb61da..166f783c0ea 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTitleElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTitleElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * The document title. See the TITLE element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLTitleElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLUListElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLUListElement.java index cd4386afa1e..b58342ed1dc 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLUListElement.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLUListElement.java @@ -44,6 +44,8 @@ package org.w3c.dom.html; /** * Unordered list. See the UL element definition in HTML 4.0. *

See also the Document Object Model (DOM) Level 2 Specification. + * + * @since 1.4, DOM Level 2 */ public interface HTMLUListElement extends HTMLElement { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/DocumentStyle.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/DocumentStyle.java index 2be39e75e6a..2c8ce7059d7 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/DocumentStyle.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/DocumentStyle.java @@ -48,7 +48,7 @@ package org.w3c.dom.stylesheets; * obtained by using binding-specific casting methods on an instance of the * Document interface. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface DocumentStyle { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/LinkStyle.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/LinkStyle.java index 9bd7b68d554..496bc641f9f 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/LinkStyle.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/LinkStyle.java @@ -49,7 +49,7 @@ package org.w3c.dom.stylesheets; * linking node (HTMLLinkElement, HTMLStyleElement * or ProcessingInstruction in DOM Level 2). *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface LinkStyle { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/MediaList.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/MediaList.java index 1a82767d78d..ba571664492 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/MediaList.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/MediaList.java @@ -51,7 +51,7 @@ import org.w3c.dom.DOMException; *

The items in the MediaList are accessible via an integral * index, starting from 0. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface MediaList { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheet.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheet.java index 617c68e0f3b..40df3088818 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheet.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheet.java @@ -51,7 +51,7 @@ import org.w3c.dom.Node; * an inline STYLE element. In XML, this interface represents an external * style sheet, included via a style sheet processing instruction. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface StyleSheet { /** diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheetList.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheetList.java index 6cd52541169..468f0c1815d 100644 --- a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheetList.java +++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheetList.java @@ -47,7 +47,7 @@ package org.w3c.dom.stylesheets; *

The items in the StyleSheetList are accessible via an * integral index, starting from 0. *

See also the Document Object Model (DOM) Level 2 Style Specification. - * @since DOM Level 2 + * @since 1.4, DOM Level 2 */ public interface StyleSheetList { /** diff --git a/jaxp/test/Makefile b/jaxp/test/Makefile index bf94d252889..63f19044ef9 100644 --- a/jaxp/test/Makefile +++ b/jaxp/test/Makefile @@ -265,7 +265,10 @@ jaxp_%: # ------------------------------------------------------------------ ifdef CONCURRENCY - EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY) + JTREG_BASIC_OPTIONS += -concurrency:$(CONCURRENCY) +endif +ifdef EXTRA_JTREG_OPTIONS + JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS) endif # Default JTREG to run @@ -290,8 +293,6 @@ JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION) # Set the max memory for jtreg control vm JTREG_MEMORY_OPTION = -J-Xmx512m JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION) -# Add any extra options -JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS) # Set other vm and test options JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%) # Set the GC options for test vms diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java index 3e157679b9e..74f051ac04d 100644 --- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java @@ -21,7 +21,6 @@ * questions. */ -import static java.lang.module.ModuleFinder.empty; import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; @@ -97,7 +96,7 @@ public class LayerModularXMLParserTest { public void testOneLayer() throws Exception { ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1); Configuration cf1 = Layer.boot().configuration() - .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + .resolveRequiresAndUses(finder1, ModuleFinder.of(), Set.of("test")); ClassLoader scl = ClassLoader.getSystemClassLoader(); Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); ClassLoader cl1 = layer1.findLoader("test"); @@ -127,12 +126,12 @@ public class LayerModularXMLParserTest { public void testTwoLayer() throws Exception { ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1); Configuration cf1 = Layer.boot().configuration() - .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + .resolveRequiresAndUses(finder1, ModuleFinder.of(), Set.of("test")); ClassLoader scl = ClassLoader.getSystemClassLoader(); Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); ModuleFinder finder2 = ModuleFinder.of(MOD_DIR2); - Configuration cf2 = cf1.resolveRequiresAndUses(finder2, empty(), Set.of("test")); + Configuration cf2 = cf1.resolveRequiresAndUses(finder2, ModuleFinder.of(), Set.of("test")); Layer layer2 = layer1.defineModulesWithOneLoader(cf2, layer1.findLoader("test")); ClassLoader cl2 = layer2.findLoader("test"); @@ -161,12 +160,12 @@ public class LayerModularXMLParserTest { public void testTwoLayerWithDuplicate() throws Exception { ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1, MOD_DIR2); Configuration cf1 = Layer.boot().configuration() - .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + .resolveRequiresAndUses(finder1, ModuleFinder.of(), Set.of("test")); ClassLoader scl = ClassLoader.getSystemClassLoader(); Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); ModuleFinder finder2 = ModuleFinder.of(MOD_DIR2); - Configuration cf2 = cf1.resolveRequiresAndUses(finder2, empty(), Set.of("test")); + Configuration cf2 = cf1.resolveRequiresAndUses(finder2, ModuleFinder.of(), Set.of("test")); Layer layer2 = layer1.defineModulesWithOneLoader(cf2, layer1.findLoader("test")); ClassLoader cl2 = layer2.findLoader("test"); diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java index 01bf4f63e89..dc5e8816bfd 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java @@ -34,6 +34,7 @@ import javax.xml.catalog.CatalogUriResolver; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Source; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; @@ -67,6 +68,24 @@ public class CatalogTest { } } + /* + * @bug 8156845 + * Verifies that an URI reference with a urn:publicid is correctly resolved + * with an uri entry with a publicId. + * + * @param expectedFile is not used in this test, it's kept since we're + * copying the JCK test and its dataProvider. This test may be reused for + * other cases in that test. + */ + @Test(dataProvider = "resolveUri") + public void testMatch1(String cFile, String href, String expectedFile, String expectedUri, String msg) { + String catalogFile = getClass().getResource(cFile).getFile(); + CatalogUriResolver cur = CatalogManager.catalogUriResolver(CatalogFeatures.defaults(), catalogFile); + Source source = cur.resolve(href, null); + Assert.assertNotNull(source, "Source returned is null"); + Assert.assertEquals(expectedUri, source.getSystemId(), msg); + } + /* * @bug 8154220 * Verifies that the file input is validated properly. Valid input includes @@ -329,6 +348,21 @@ public class CatalogTest { } } + + /* + DataProvider: used to verify CatalogUriResolver's resolve function. + Data columns: + catalog, uri or publicId, expectedFile, expectedUri, msg + + This DataProvider is copied from JCK ResolveTests' dataMatch1 + */ + @DataProvider(name = "resolveUri") + Object[][] getDataForUriResolver() { + return new Object[][]{ + {"uri.xml", "urn:publicid:-:Acme,+Inc.:DTD+Book+Version+1.0", null, "http://local/base/dtd/book.dtd", "Uri in publicId namespace is incorrectly unwrapped"}, + }; + } + /* DataProvider: used to verify hierarchical catalogs. Refer to JCK test hierarchyOfCatFiles2. diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/uri.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/uri.xml new file mode 100644 index 00000000000..f092ae85df2 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/uri.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 4d92200f4dc..b7d3abb35f7 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -364,3 +364,5 @@ b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114 529f0bf896e58525614d863e283ad155531941cb jdk-9+116 58265b39fc74b932bda4d4f4649c530a89f55c4e jdk-9+117 6ba73d04589ccc0705a5d8ae5111b63632b6ad20 jdk-9+118 +331a825f849afd2e5126c93c88e55bd9ef0c6b8f jdk-9+119 +ecd0d6a71c7ccf93584ba4dacdd4fa8455efd741 jdk-9+120 diff --git a/jdk/.hgtags b/jdk/.hgtags index 2b6d80debed..7ac8e6be416 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -361,3 +361,5 @@ bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114 baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116 4da0f73ce03aaf245b92cc040cc0ab0e3fa54dc2 jdk-9+117 e1eba5cfa5cc8c66d524396a05323dc93568730a jdk-9+118 +bad3f8a33db271a6143ba6eac0c8bd5bbd942417 jdk-9+119 +b9a518bf72516954e57ac2f6e3ef21e13008f1cd jdk-9+120 diff --git a/jdk/make/Import.gmk b/jdk/make/Import.gmk index d479b095514..29e4ce0f19e 100644 --- a/jdk/make/Import.gmk +++ b/jdk/make/Import.gmk @@ -112,7 +112,7 @@ $(BASE_INSTALL_LIBRARIES_HERE)/server/%$(SHARED_LIBRARY_SUFFIX): $(BASE_INSTALL_ $(LN) -s ../$(@F) $@ ifeq ($(OPENJDK_TARGET_OS), macosx) - $(BASE_INSTALL_LIBRARIES_HERE)/server/%.dSYM : $(BASE_INSTALL_LIBRARIES_HERE)/%.dSYM + $(BASE_INSTALL_LIBRARIES_HERE)/server/%.dSYM: $(MKDIR) -p $(@D) $(RM) $@ $(LN) -s ../$(@F) $@ diff --git a/jdk/make/data/currency/CurrencyData.properties b/jdk/make/data/currency/CurrencyData.properties index 808d01d6958..0288b04390b 100644 --- a/jdk/make/data/currency/CurrencyData.properties +++ b/jdk/make/data/currency/CurrencyData.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -26,7 +26,8 @@ # Version of the currency data format. # 1: initial # 2: Change in minor unit (allowing 4-9 digits) -formatVersion=2 +# 3: Change in the order of special case and other currency entries +formatVersion=3 # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index 73b452f43f6..b4c6f5e20a3 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -96,10 +96,7 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) mlib_c_ImageAffine_BL.c \ mlib_c_ImageAffine_BL_S16.c \ mlib_c_ImageAffine_BL_U16.c \ - mlib_c_ImageAffineIndex_BC.c \ - mlib_c_ImageAffineIndex_BL.c \ mlib_c_ImageAffine_NN.c \ - mlib_c_ImageBlendTable.c \ mlib_c_ImageConvClearEdge.c \ mlib_c_ImageConvCopyEdge.c \ mlib_c_ImageConv_f.c \ @@ -107,14 +104,6 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) mlib_c_ImageCopy.c \ mlib_c_ImageLookUp.c \ mlib_c_ImageLookUp_f.c \ - mlib_v_ImageChannelExtract.c \ - mlib_v_ImageChannelExtract_f.c \ - mlib_v_ImageChannelInsert_34.c \ - mlib_v_ImageChannelInsert.c \ - mlib_v_ImageConvIndex3_8_16nw.c \ - mlib_v_ImageConvIndex3_8_8nw.c \ - mlib_v_ImageCopy.c \ - mlib_v_ImageCopy_blk.s \ # LIBMLIB_IMAGE_V_CFLAGS += $(filter-out -DMLIB_NO_LIBSUNMATH, $(BUILD_LIBMLIB_CFLAGS)) diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index 693f5a87fb8..8bd1118c1ff 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -267,6 +267,7 @@ SUNWprivate_1.1 { Java_jdk_internal_misc_VM_geteuid; Java_jdk_internal_misc_VM_getgid; Java_jdk_internal_misc_VM_getegid; + Java_jdk_internal_misc_VM_getRuntimeArguments; Java_jdk_internal_misc_VM_initialize; Java_java_lang_reflect_Module_defineModule0; diff --git a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java index f15834202b0..b72ac9225b1 100644 --- a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, 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 @@ -584,7 +584,9 @@ public class CLDRConverter { String[] data = (String[])e[1]; if (map.get(TIMEZONE_ID_PREFIX + tzid) == null && - handlerMetaZones.get(tzid) == null) { + handlerMetaZones.get(tzid) == null || + handlerMetaZones.get(tzid) != null && + map.get(METAZONE_ID_PREFIX + handlerMetaZones.get(tzid)) == null) { // First, check the CLDR meta key Optional> cldrMeta = handlerMetaZones.getData().entrySet().stream() diff --git a/jdk/make/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java b/jdk/make/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java index cc125638c96..ae861c5abe5 100644 --- a/jdk/make/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java +++ b/jdk/make/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -121,7 +121,7 @@ public class GenerateCurrencyData { private static final int maxOtherCurrencies = 128; private static int otherCurrenciesCount = 0; - private static StringBuffer otherCurrencies = new StringBuffer(); + private static String[] otherCurrencies = new String[maxOtherCurrencies]; private static int[] otherCurrenciesDefaultFractionDigits = new int[maxOtherCurrencies]; private static int[] otherCurrenciesNumericCode= new int[maxOtherCurrencies]; @@ -318,10 +318,7 @@ public class GenerateCurrencyData { if (otherCurrenciesCount == maxOtherCurrencies) { throw new RuntimeException("too many other currencies"); } - if (otherCurrencies.length() > 0) { - otherCurrencies.append('-'); - } - otherCurrencies.append(currencyCode); + otherCurrencies[otherCurrenciesCount] = currencyCode; otherCurrenciesDefaultFractionDigits[otherCurrenciesCount] = getDefaultFractionDigits(currencyCode); otherCurrenciesNumericCode[otherCurrenciesCount] = getNumericCode(currencyCode); otherCurrenciesCount++; @@ -350,35 +347,41 @@ public class GenerateCurrencyData { out.writeInt(Integer.parseInt(dataVersion)); writeIntArray(mainTable, mainTable.length); out.writeInt(specialCaseCount); - writeLongArray(specialCaseCutOverTimes, specialCaseCount); - writeStringArray(specialCaseOldCurrencies, specialCaseCount); - writeStringArray(specialCaseNewCurrencies, specialCaseCount); - writeIntArray(specialCaseOldCurrenciesDefaultFractionDigits, specialCaseCount); - writeIntArray(specialCaseNewCurrenciesDefaultFractionDigits, specialCaseCount); - writeIntArray(specialCaseOldCurrenciesNumericCode, specialCaseCount); - writeIntArray(specialCaseNewCurrenciesNumericCode, specialCaseCount); + writeSpecialCaseEntries(); out.writeInt(otherCurrenciesCount); - out.writeUTF(otherCurrencies.toString()); - writeIntArray(otherCurrenciesDefaultFractionDigits, otherCurrenciesCount); - writeIntArray(otherCurrenciesNumericCode, otherCurrenciesCount); + writeOtherCurrencies(); } private static void writeIntArray(int[] ia, int count) throws IOException { - for (int i = 0; i < count; i ++) { + for (int i = 0; i < count; i++) { out.writeInt(ia[i]); } } - private static void writeLongArray(long[] la, int count) throws IOException { - for (int i = 0; i < count; i ++) { - out.writeLong(la[i]); + private static void writeSpecialCaseEntries() throws IOException { + for (int index = 0; index < specialCaseCount; index++) { + out.writeLong(specialCaseCutOverTimes[index]); + String str = (specialCaseOldCurrencies[index] != null) + ? specialCaseOldCurrencies[index] : ""; + out.writeUTF(str); + str = (specialCaseNewCurrencies[index] != null) + ? specialCaseNewCurrencies[index] : ""; + out.writeUTF(str); + out.writeInt(specialCaseOldCurrenciesDefaultFractionDigits[index]); + out.writeInt(specialCaseNewCurrenciesDefaultFractionDigits[index]); + out.writeInt(specialCaseOldCurrenciesNumericCode[index]); + out.writeInt(specialCaseNewCurrenciesNumericCode[index]); } } - private static void writeStringArray(String[] sa, int count) throws IOException { - for (int i = 0; i < count; i ++) { - String str = (sa[i] != null) ? sa[i] : ""; + private static void writeOtherCurrencies() throws IOException { + for (int index = 0; index < otherCurrenciesCount; index++) { + String str = (otherCurrencies[index] != null) + ? otherCurrencies[index] : ""; out.writeUTF(str); + out.writeInt(otherCurrenciesDefaultFractionDigits[index]); + out.writeInt(otherCurrenciesNumericCode[index]); } } + } diff --git a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java index da774751e1c..04badbd7f3d 100644 --- a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java +++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java @@ -82,14 +82,14 @@ public class GenGraphs { mods.add(name); Configuration cf = Configuration.empty() .resolveRequires(finder, - ModuleFinder.empty(), + ModuleFinder.of(), Set.of(name)); genGraphs.genDotFile(dir, name, cf); } Configuration cf = Configuration.empty() .resolveRequires(finder, - ModuleFinder.empty(), + ModuleFinder.of(), mods); genGraphs.genDotFile(dir, "jdk", cf); diff --git a/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java b/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java index c1b15d39219..f274afdc709 100644 --- a/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java +++ b/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java @@ -292,7 +292,7 @@ public class ModuleSummary { static Configuration resolve(Set roots) { return Configuration.empty() .resolveRequires(ModuleFinder.ofSystem(), - ModuleFinder.empty(), + ModuleFinder.of(), roots); } diff --git a/jdk/src/demo/share/jvmti/index.html b/jdk/src/demo/share/jvmti/index.html index 25440a104d9..5791b8b046f 100644 --- a/jdk/src/demo/share/jvmti/index.html +++ b/jdk/src/demo/share/jvmti/index.html @@ -415,7 +415,7 @@ Additional information can also be found by doing a search on "jvmti" at Various technical articles are also available through this website. And don't forget the Java Tutorials at -http://java.sun.com/docs/books/tutorial +http://docs.oracle.com/javase/tutorial for getting a quick start on all the various interfaces.

Comments and Feedback

diff --git a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java index fee0b800f2d..50dc8020b25 100644 --- a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java +++ b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -43,9 +43,10 @@ class Constants { 1.0 to 1.3.X 45,3 1.4 to 1.4.X 46,0 1.5 to 1.5.X 49,0 - 1.6 to 1.5.x 50,0 - 1.7 to 1.6.x 51,0 - 1.8 to 1.7.x 52,0 + 1.6 to 1.6.X 50,0 + 1.7 to 1.7.X 51,0 + 1.8 to 1.8.X 52,0 + 1.9 to 1.9.X 53,0 */ public static final Package.Version JAVA_MIN_CLASS_VERSION = @@ -63,6 +64,9 @@ class Constants { public static final Package.Version JAVA8_MAX_CLASS_VERSION = Package.Version.of(52, 00); + public static final Package.Version JAVA9_MAX_CLASS_VERSION = + Package.Version.of(53, 00); + public static final int JAVA_PACKAGE_MAGIC = 0xCAFED00D; public static final Package.Version JAVA5_PACKAGE_VERSION = @@ -79,7 +83,7 @@ class Constants { // upper limit, should point to the latest class version public static final Package.Version JAVA_MAX_CLASS_VERSION = - JAVA8_MAX_CLASS_VERSION; + JAVA9_MAX_CLASS_VERSION; // upper limit should point to the latest package version, for version info!. public static final Package.Version MAX_PACKAGE_VERSION = diff --git a/jdk/src/java.base/share/classes/java/io/BufferedWriter.java b/jdk/src/java.base/share/classes/java/io/BufferedWriter.java index 28e170fe800..3d8e1ee1b19 100644 --- a/jdk/src/java.base/share/classes/java/io/BufferedWriter.java +++ b/jdk/src/java.base/share/classes/java/io/BufferedWriter.java @@ -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 @@ -153,13 +153,18 @@ public class BufferedWriter extends Writer { * needed. If the requested length is at least as large as the buffer, * however, then this method will flush the buffer and write the characters * directly to the underlying stream. Thus redundant - * BufferedWriters will not copy data unnecessarily. + * {@code BufferedWriter}s will not copy data unnecessarily. * * @param cbuf A character array * @param off Offset from which to start reading characters * @param len Number of characters to write * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array + * + * @throws IOException If an I/O error occurs */ public void write(char cbuf[], int off, int len) throws IOException { synchronized (lock) { @@ -195,17 +200,24 @@ public class BufferedWriter extends Writer { /** * Writes a portion of a String. * - *

If the value of the {@code len} parameter is negative then no - * characters are written. This is contrary to the specification of this - * method in the {@linkplain java.io.Writer#write(java.lang.String,int,int) - * superclass}, which requires that an {@link IndexOutOfBoundsException} be - * thrown. + * @implSpec + * While the specification of this method in the + * {@linkplain java.io.Writer#write(java.lang.String,int,int) superclass} + * recommends that an {@link IndexOutOfBoundsException} be thrown + * if {@code len} is negative or {@code off + len} is negative, + * the implementation in this class does not throw such an exception in + * these cases but instead simply writes no characters. * * @param s String to be written * @param off Offset from which to start reading characters * @param len Number of characters to be written * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If {@code off} is negative, + * or {@code off + len} is greater than the length + * of the given string + * + * @throws IOException If an I/O error occurs */ public void write(String s, int off, int len) throws IOException { synchronized (lock) { diff --git a/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java b/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java index ed27bbae314..773b59614d9 100644 --- a/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java +++ b/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2005, 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 @@ -91,6 +91,11 @@ class CharArrayWriter extends Writer { * @param c the data to be written * @param off the start offset in the data * @param len the number of chars that are written + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array */ public void write(char c[], int off, int len) { if ((off < 0) || (off > c.length) || (len < 0) || @@ -114,6 +119,11 @@ class CharArrayWriter extends Writer { * @param str String to be written from * @param off Offset from which to start reading characters * @param len Number of characters to be written + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given string */ public void write(String str, int off, int len) { synchronized (lock) { diff --git a/jdk/src/java.base/share/classes/java/io/FilterWriter.java b/jdk/src/java.base/share/classes/java/io/FilterWriter.java index 303c674e0c0..8272b3cc8bf 100644 --- a/jdk/src/java.base/share/classes/java/io/FilterWriter.java +++ b/jdk/src/java.base/share/classes/java/io/FilterWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2005, 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 @@ -72,7 +72,12 @@ public abstract class FilterWriter extends Writer { * @param off Offset from which to start reading characters * @param len Number of characters to be written * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If the values of the {@code off} and {@code len} parameters + * cause the corresponding method of the underlying {@code Writer} + * to throw an {@code IndexOutOfBoundsException} + * + * @throws IOException If an I/O error occurs */ public void write(char cbuf[], int off, int len) throws IOException { out.write(cbuf, off, len); @@ -85,7 +90,12 @@ public abstract class FilterWriter extends Writer { * @param off Offset from which to start reading characters * @param len Number of characters to be written * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If the values of the {@code off} and {@code len} parameters + * cause the corresponding method of the underlying {@code Writer} + * to throw an {@code IndexOutOfBoundsException} + * + * @throws IOException If an I/O error occurs */ public void write(String str, int off, int len) throws IOException { out.write(str, off, len); diff --git a/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java b/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java index 0d597e6bef4..4fdb148baaf 100644 --- a/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java +++ b/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java @@ -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 @@ -202,7 +202,12 @@ public class OutputStreamWriter extends Writer { * @param off Offset from which to start writing characters * @param len Number of characters to write * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array + * + * @throws IOException If an I/O error occurs */ public void write(char cbuf[], int off, int len) throws IOException { se.write(cbuf, off, len); @@ -215,7 +220,12 @@ public class OutputStreamWriter extends Writer { * @param off Offset from which to start writing characters * @param len Number of characters to write * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given string + * + * @throws IOException If an I/O error occurs */ public void write(String str, int off, int len) throws IOException { se.write(str, off, len); diff --git a/jdk/src/java.base/share/classes/java/io/PipedWriter.java b/jdk/src/java.base/share/classes/java/io/PipedWriter.java index 02201fbec1a..a4534b8604c 100644 --- a/jdk/src/java.base/share/classes/java/io/PipedWriter.java +++ b/jdk/src/java.base/share/classes/java/io/PipedWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, 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 @@ -125,19 +125,25 @@ public class PipedWriter extends Writer { } /** - * Writes len characters from the specified character array - * starting at offset off to this piped output stream. + * Writes {@code len} characters from the specified character array + * starting at offset {@code off} to this piped output stream. * This method blocks until all the characters are written to the output * stream. * If a thread was reading data characters from the connected piped input * stream, but the thread is no longer alive, then an - * IOException is thrown. + * {@code IOException} is thrown. * * @param cbuf the data. * @param off the start offset in the data. * @param len the number of characters to write. - * @exception IOException if the pipe is - * broken, + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array + * + * @throws IOException if the pipe is + * broken, * {@link #connect(java.io.PipedReader) unconnected}, closed * or an I/O error occurs. */ diff --git a/jdk/src/java.base/share/classes/java/io/PrintWriter.java b/jdk/src/java.base/share/classes/java/io/PrintWriter.java index 662f930ef90..d516b8ef404 100644 --- a/jdk/src/java.base/share/classes/java/io/PrintWriter.java +++ b/jdk/src/java.base/share/classes/java/io/PrintWriter.java @@ -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 @@ -410,6 +410,11 @@ public class PrintWriter extends Writer { * @param buf Array of characters * @param off Offset from which to start writing characters * @param len Number of characters to write + * + * @throws IndexOutOfBoundsException + * If the values of the {@code off} and {@code len} parameters + * cause the corresponding method of the underlying {@code Writer} + * to throw an {@code IndexOutOfBoundsException} */ public void write(char buf[], int off, int len) { try { @@ -440,6 +445,11 @@ public class PrintWriter extends Writer { * @param s A String * @param off Offset from which to start writing characters * @param len Number of characters to write + * + * @throws IndexOutOfBoundsException + * If the values of the {@code off} and {@code len} parameters + * cause the corresponding method of the underlying {@code Writer} + * to throw an {@code IndexOutOfBoundsException} */ public void write(String s, int off, int len) { try { diff --git a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java index 1a8344df88b..3806675cdca 100644 --- a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -27,6 +27,8 @@ package java.io; import java.nio.channels.FileChannel; import java.util.concurrent.atomic.AtomicBoolean; +import jdk.internal.misc.JavaIORandomAccessFileAccess; +import jdk.internal.misc.SharedSecrets; import sun.nio.ch.FileChannelImpl; @@ -75,6 +77,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { private static final int O_RDWR = 2; private static final int O_SYNC = 4; private static final int O_DSYNC = 8; + private static final int O_TEMPORARY = 16; /** * Creates a random access file stream to read from, and optionally @@ -202,6 +205,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { */ public RandomAccessFile(File file, String mode) throws FileNotFoundException + { + this(file, mode, false); + } + + private RandomAccessFile(File file, String mode, boolean openAndDelete) + throws FileNotFoundException { String name = (file != null ? file.getPath() : null); int imode = -1; @@ -219,6 +228,8 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { imode = -1; } } + if (openAndDelete) + imode |= O_TEMPORARY; if (imode < 0) throw new IllegalArgumentException("Illegal mode \"" + mode + "\" must be one of " @@ -1165,5 +1176,15 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { static { initIDs(); + SharedSecrets.setJavaIORandomAccessFileAccess(new JavaIORandomAccessFileAccess() + { + // This is for j.u.z.ZipFile.OPEN_DELETE. The O_TEMPORARY flag + // is only implemented/supported on windows. + public RandomAccessFile openAndDelete(File file, String mode) + throws IOException + { + return new RandomAccessFile(file, mode, true); + } + }); } } diff --git a/jdk/src/java.base/share/classes/java/io/StringWriter.java b/jdk/src/java.base/share/classes/java/io/StringWriter.java index 5d1babc3127..15022b353a8 100644 --- a/jdk/src/java.base/share/classes/java/io/StringWriter.java +++ b/jdk/src/java.base/share/classes/java/io/StringWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2004, 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 @@ -83,6 +83,11 @@ public class StringWriter extends Writer { * @param cbuf Array of characters * @param off Offset from which to start writing characters * @param len Number of characters to write + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array */ public void write(char cbuf[], int off, int len) { if ((off < 0) || (off > cbuf.length) || (len < 0) || @@ -107,6 +112,11 @@ public class StringWriter extends Writer { * @param str String to be written * @param off Offset from which to start writing characters * @param len Number of characters to write + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given string */ public void write(String str, int off, int len) { buf.append(str, off, off + len); diff --git a/jdk/src/java.base/share/classes/java/io/Writer.java b/jdk/src/java.base/share/classes/java/io/Writer.java index 5ad5e554fb3..17e8de3ef8a 100644 --- a/jdk/src/java.base/share/classes/java/io/Writer.java +++ b/jdk/src/java.base/share/classes/java/io/Writer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, 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 @@ -32,12 +32,11 @@ package java.io; * Most subclasses, however, will override some of the methods defined here in * order to provide higher efficiency, additional functionality, or both. * - * @see Writer * @see BufferedWriter * @see CharArrayWriter * @see FilterWriter * @see OutputStreamWriter - * @see FileWriter + * @see FileWriter * @see PipedWriter * @see PrintWriter * @see StringWriter @@ -139,6 +138,12 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * @param len * Number of characters to write * + * @throws IndexOutOfBoundsException + * Implementations should throw this exception + * if {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array + * * @throws IOException * If an I/O error occurs */ @@ -160,6 +165,11 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * Writes a portion of a string. * + * @implSpec + * The implementation in this class throws an + * {@code IndexOutOfBoundsException} for the indicated conditions; + * overriding methods may choose to do otherwise. + * * @param str * A String * @@ -170,8 +180,9 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * Number of characters to write * * @throws IndexOutOfBoundsException - * If {@code off} is negative, or {@code len} is negative, - * or {@code off+len} is negative or greater than the length + * Implementations should throw this exception + * if {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length * of the given string * * @throws IOException diff --git a/jdk/src/java.base/share/classes/java/lang/Boolean.java b/jdk/src/java.base/share/classes/java/lang/Boolean.java index eeda751719c..af7bad17a64 100644 --- a/jdk/src/java.base/share/classes/java/lang/Boolean.java +++ b/jdk/src/java.base/share/classes/java/lang/Boolean.java @@ -117,7 +117,9 @@ public final class Boolean implements java.io.Serializable, * Parses the string argument as a boolean. The {@code boolean} * returned represents the value {@code true} if the string argument * is not {@code null} and is equal, ignoring case, to the string - * {@code "true"}.

+ * {@code "true"}. + * Otherwise, a false value is returned, including for a null + * argument.

* Example: {@code Boolean.parseBoolean("True")} returns {@code true}.
* Example: {@code Boolean.parseBoolean("yes")} returns {@code false}. * @@ -165,6 +167,8 @@ public final class Boolean implements java.io.Serializable, * specified string. The {@code Boolean} returned represents a * true value if the string argument is not {@code null} * and is equal, ignoring case, to the string {@code "true"}. + * Otherwise, a false value is returned, including for a null + * argument. * * @param s a string. * @return the {@code Boolean} value represented by the string. @@ -241,14 +245,12 @@ public final class Boolean implements java.io.Serializable, /** * Returns {@code true} if and only if the system property named - * by the argument exists and is equal to the string {@code - * "true"}. (Beginning with version 1.0.2 of the Java™ - * platform, the test of this string is case insensitive.) A - * system property is accessible through {@code getProperty}, a - * method defined by the {@code System} class. - *

- * If there is no property with the specified name, or if the specified - * name is empty or null, then {@code false} is returned. + * by the argument exists and is equal to, ignoring case, the + * string {@code "true"}. + * A system property is accessible through {@code getProperty}, a + * method defined by the {@code System} class.

If there is no + * property with the specified name, or if the specified name is + * empty or null, then {@code false} is returned. * * @param name the system property name. * @return the {@code boolean} value of the system property. diff --git a/jdk/src/java.base/share/classes/java/lang/Math.java b/jdk/src/java.base/share/classes/java/lang/Math.java index 4244d40a3b9..aa678b875ec 100644 --- a/jdk/src/java.base/share/classes/java/lang/Math.java +++ b/jdk/src/java.base/share/classes/java/lang/Math.java @@ -95,7 +95,7 @@ import jdk.internal.HotSpotIntrinsicCandidate; * {@code subtractExact}, {@code multiplyExact}, and {@code toIntExact} * throw an {@code ArithmeticException} when the results overflow. * For other arithmetic operations such as divide, absolute value, - * increment, decrement, and negation overflow occurs only with + * increment by one, decrement by one, and negation, overflow occurs only with * a specific minimum or maximum value and should be checked against * the minimum or maximum as appropriate. * @@ -861,7 +861,7 @@ public final class Math { public static int subtractExact(int x, int y) { int r = x - y; // HD 2-12 Overflow iff the arguments have different signs and - // the sign of the result is different than the sign of x + // the sign of the result is different from the sign of x if (((x ^ y) & (x ^ r)) < 0) { throw new ArithmeticException("integer overflow"); } @@ -882,7 +882,7 @@ public final class Math { public static long subtractExact(long x, long y) { long r = x - y; // HD 2-12 Overflow iff the arguments have different signs and - // the sign of the result is different than the sign of x + // the sign of the result is different from the sign of x if (((x ^ y) & (x ^ r)) < 0) { throw new ArithmeticException("long overflow"); } @@ -908,6 +908,20 @@ public final class Math { return (int)r; } + /** + * Returns the product of the arguments, throwing an exception if the result + * overflows a {@code long}. + * + * @param x the first value + * @param y the second value + * @return the result + * @throws ArithmeticException if the result overflows a long + * @since 9 + */ + public static long multiplyExact(long x, int y) { + return multiplyExact(x, (long)y); + } + /** * Returns the product of the arguments, * throwing an exception if the result overflows a {@code long}. @@ -1059,18 +1073,65 @@ public final class Math { return (int)value; } + /** + * Returns the exact mathematical product of the arguments. + * + * @param x the first value + * @param y the second value + * @return the result + */ + public static long multiplyFull(int x, int y) { + return (long)x * (long)y; + } + + /** + * Returns as a {@code long} the most significant 64 bits of the 128-bit + * product of two 64-bit factors. + * + * @param x the first value + * @param y the second value + * @return the result + */ + public static long multiplyHigh(long x, long y) { + if (x < 0 || y < 0) { + // Use technique from section 8-2 of Henry S. Warren, Jr., + // Hacker's Delight (2nd ed.) (Addison Wesley, 2013), 173-174. + long x1 = x >> 32; + long x2 = x & 0xFFFFFFFFL; + long y1 = y >> 32; + long y2 = y & 0xFFFFFFFFL; + long z2 = x2 * y2; + long t = x1 * y2 + (z2 >>> 32); + long z1 = t & 0xFFFFFFFFL; + long z0 = t >> 32; + z1 += x2 * y1; + return x1 * y1 + z0 + (z1 >> 32); + } else { + // Use Karatsuba technique with two base 2^32 digits. + long x1 = x >>> 32; + long y1 = y >>> 32; + long x2 = x & 0xFFFFFFFFL; + long y2 = y & 0xFFFFFFFFL; + long A = x1 * y1; + long B = x2 * y2; + long C = (x1 + x2) * (y1 + y2); + long K = C - A - B; + return (((B >>> 32) + K) >>> 32) + A; + } + } + /** * Returns the largest (closest to positive infinity) * {@code int} value that is less than or equal to the algebraic quotient. * There is one special case, if the dividend is the * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1}, * then integer overflow occurs and - * the result is equal to the {@code Integer.MIN_VALUE}. + * the result is equal to {@code Integer.MIN_VALUE}. *

* Normal integer division operates under the round to zero rounding mode * (truncation). This operation instead acts under the round toward * negative infinity (floor) rounding mode. - * The floor rounding mode gives different results than truncation + * The floor rounding mode gives different results from truncation * when the exact result is negative. *

    *
  • If the signs of the arguments are the same, the results of @@ -1108,12 +1169,41 @@ public final class Math { * There is one special case, if the dividend is the * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1}, * then integer overflow occurs and - * the result is equal to the {@code Long.MIN_VALUE}. + * the result is equal to {@code Long.MIN_VALUE}. *

    * Normal integer division operates under the round to zero rounding mode * (truncation). This operation instead acts under the round toward * negative infinity (floor) rounding mode. - * The floor rounding mode gives different results than truncation + * The floor rounding mode gives different results from truncation + * when the exact result is negative. + *

    + * For examples, see {@link #floorDiv(int, int)}. + * + * @param x the dividend + * @param y the divisor + * @return the largest (closest to positive infinity) + * {@code int} value that is less than or equal to the algebraic quotient. + * @throws ArithmeticException if the divisor {@code y} is zero + * @see #floorMod(long, int) + * @see #floor(double) + * @since 9 + */ + public static long floorDiv(long x, int y) { + return floorDiv(x, (long)y); + } + + /** + * Returns the largest (closest to positive infinity) + * {@code long} value that is less than or equal to the algebraic quotient. + * There is one special case, if the dividend is the + * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1}, + * then integer overflow occurs and + * the result is equal to {@code Long.MIN_VALUE}. + *

    + * Normal integer division operates under the round to zero rounding mode + * (truncation). This operation instead acts under the round toward + * negative infinity (floor) rounding mode. + * The floor rounding mode gives different results from truncation * when the exact result is negative. *

    * For examples, see {@link #floorDiv(int, int)}. @@ -1181,8 +1271,34 @@ public final class Math { * @since 1.8 */ public static int floorMod(int x, int y) { - int r = x - floorDiv(x, y) * y; - return r; + return x - floorDiv(x, y) * y; + } + + /** + * Returns the floor modulus of the {@code long} and {@int} arguments. + *

    + * The floor modulus is {@code x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y}, and + * is in the range of {@code -abs(y) < r < +abs(y)}. + * + *

    + * The relationship between {@code floorDiv} and {@code floorMod} is such that: + *

      + *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x} + *
    + *

    + * For examples, see {@link #floorMod(int, int)}. + * + * @param x the dividend + * @param y the divisor + * @return the floor modulus {@code x - (floorDiv(x, y) * y)} + * @throws ArithmeticException if the divisor {@code y} is zero + * @see #floorDiv(long, int) + * @since 9 + */ + public static int floorMod(long x, int y) { + // Result cannot overflow the range of int. + return (int)(x - floorDiv(x, y) * y); } /** diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index 3c73d5b61a3..1533130017b 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,21 @@ package java.lang; import java.io.*; +import java.math.BigInteger; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.RandomAccess; import java.util.StringTokenizer; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import sun.security.action.GetPropertyAction; /** * Every Java application has a single instance of class @@ -46,6 +58,8 @@ import jdk.internal.reflect.Reflection; public class Runtime { private static final Runtime currentRuntime = new Runtime(); + private static Version version; + /** * Returns the runtime object associated with the current Java application. * Most of the methods of class {@code Runtime} are instance @@ -917,4 +931,591 @@ public class Runtime { return out; } + /** + * Returns the version of the Java Runtime Environment as a {@link + * Runtime.Version}. + * + * @return the {@link Runtime.Version} of the Java Runtime Environment + * + * @since 9 + */ + public static Version version() { + if (version == null) { + version = Version.parse( + GetPropertyAction.privilegedGetProperty("java.runtime.version")); + } + return version; + } + + /** + * A representation of a version string for an implemenation of the + * Java SE Platform. A version string contains a version number + * optionally followed by pre-release and build information. + * + *

    Version numbers

    + * + *

    A version number, {@code $VNUM}, is a non-empty sequence + * of elements separated by period characters (U+002E). An element is + * either zero, or a unsigned integer numeral without leading zeros. The + * final element in a version number must not be zero. The format is: + *

    + * + *
    +     *     ^[1-9][0-9]*(((\.0)*\.[1-9][0-9]*)*)*$
    +     * 
    + * + *

    The sequence may be of arbitrary length but the first three + * elements are assigned specific meanings, as follows:

    + * + *
    +     *     $MAJOR.$MINOR.$SECURITY
    +     * 
    + * + *
      + * + *
    • {@code $MAJOR} --- The major version + * number, incremented for a major release that contains significant new + * features as specified in a new edition of the Java SE Platform + * Specification, e.g., JSR 337 for + * Java SE 8. Features may be removed in a major release, given + * advance notice at least one major release ahead of time, and + * incompatible changes may be made when justified. The {@code $MAJOR} + * version number of JDK 8 is {@code 8}; the {@code $MAJOR} version + * number of JDK 9 is {@code 9}. When {@code $MAJOR} is incremented, + * all subsequent elements are removed.

    • + * + *
    • {@code $MINOR} --- The minor version + * number, incremented for a minor update release that may contain + * compatible bug fixes, revisions to standard APIs mandated by a + * Maintenance Release + * of the relevant Platform Specification, and implementation features + * outside the scope of that Specification such as new JDK-specific APIs, + * additional service providers, new garbage collectors, and ports to new + * hardware architectures.

    • + * + *
    • {@code $SECURITY} --- The security + * level, incremented for a security update release that contains critical + * fixes including those necessary to improve security. {@code $SECURITY} + * is not reset when {@code $MINOR} is incremented. A + * higher value of {@code $SECURITY} for a given {@code $MAJOR} value, + * therefore, always indicates a more secure release, regardless of the + * value of {@code $MINOR}.

    • + * + *
    + * + *

    The fourth and later elements of a version number are free for use + * by downstream consumers of this code base. Such a consumer may, + * e.g., use the fourth element to identify patch releases which + * contain a small number of critical non-security fixes in addition to + * the security fixes in the corresponding security release.

    + * + *

    The version number does not include trailing zero elements; + * i.e., {@code $SECURITY} is omitted if it has the value zero, + * and {@code $MINOR} is omitted if both {@code $MINOR} and {@code + * $SECURITY} have the value zero.

    + * + *

    The sequence of numerals in a version number is compared to another + * such sequence in numerical, pointwise fashion; e.g., {@code + * 9.9.1} is less than {@code 9.10.3}. If one sequence is shorter than + * another then the missing elements of the shorter sequence are + * considered to be less than the corresponding elements of the longer + * sequence; e.g., {@code 9.1.2} is less than {@code 9.1.2.1}. + *

    + * + *

    Version strings

    + * + *

    A version string, {@code $VSTR}, consists of a version + * number {@code $VNUM}, as described above, optionally followed by + * pre-release and build information, in the format

    + * + *
    +     *     $VNUM(-$PRE)?(\+($BUILD)?(-$OPT)?)?
    +     * 
    + * + *

    where:

    + * + *
      + * + *
    • {@code $PRE}, matching {@code ([a-zA-Z0-9]+)} + * --- A pre-release identifier. Typically {@code ea}, for a + * potentially unstable early-access release under active development, + * or {@code internal}, for an internal developer build. + * + *

    • {@code $BUILD}, matching {@code + * (0|[1-9][0-9]*)} --- The build number, incremented for each promoted + * build. {@code $BUILD} is reset to {@code 1} when any portion of {@code + * $VNUM} is incremented.

      + * + *
    • {@code $OPT}, matching {@code + * ([-a-zA-Z0-9\.]+)} --- Additional build information, if desired. In + * the case of an {@code internal} build this will often contain the date + * and time of the build.

      + * + *
    + * + *

    A version number {@code 10-ea} matches {@code $VNUM = "10"} and + * {@code $PRE = "ea"}. The version number {@code 10+-ea} matches + * {@code $VNUM = "10"} and {@code $OPT = "ea"}.

    + * + *

    When comparing two version strings, the value of {@code $OPT}, if + * present, may or may not be significant depending on the chosen + * comparison method. The comparison methods {@link #compareTo(Version) + * compareTo()} and {@link #compareToIgnoreOpt(Version) + * compareToIgnoreOpt()} should be used consistently with the + * corresponding methods {@link #equals(Object) equals()} and {@link + * #equalsIgnoreOpt(Object) equalsIgnoreOpt()}.

    + * + *

    A short version string, {@code $SVSTR}, often useful in + * less formal contexts, is a version number optionally followed by a + * pre-release identifier: + * + *

    +     *     $VNUM(-$PRE)?
    +     * 
    + * + * @since 9 + */ + public static class Version + implements Comparable + { + private final List version; + private final Optional pre; + private final Optional build; + private final Optional optional; + + + // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)? + // RE limits the format of version strings + // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))? + + private static final String VNUM + = "(?[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)"; + private static final String VNUM_GROUP = "VNUM"; + + private static final String PRE = "(?:-(?
    [a-zA-Z0-9]+))?";
    +        private static final String PRE_GROUP   = "PRE";
    +
    +        private static final String BUILD
    +            = "(?:(?\\+)(?0|[1-9][0-9]*)?)?";
    +        private static final String PLUS_GROUP  = "PLUS";
    +        private static final String BUILD_GROUP = "BUILD";
    +
    +        private static final String OPT      = "(?:-(?[-a-zA-Z0-9.]+))?";
    +        private static final String OPT_GROUP   = "OPT";
    +
    +        private static final String VSTR_FORMAT
    +            = "^" + VNUM + PRE + BUILD + OPT + "$";
    +        private static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
    +
    +        /**
    +         * Constructs a valid version string containing
    +         * a version number followed by pre-release and
    +         * build information.
    +         *
    +         * @param  s
    +         *         A string to be interpreted as a version
    +         *
    +         * @throws  IllegalArgumentException
    +         *          If the given string cannot be interpreted as a valid
    +         *          version
    +         *
    +         * @throws  NullPointerException
    +         *          If {@code s} is {@code null}
    +         *
    +         * @throws  NumberFormatException
    +         *          If an element of the version number or the build number
    +         *          cannot be represented as an {@link Integer}
    +         */
    +        private Version(String s) {
    +            if (s == null)
    +                throw new NullPointerException();
    +
    +            Matcher m = VSTR_PATTERN.matcher(s);
    +            if (!m.matches())
    +                throw new IllegalArgumentException("Invalid version string: '"
    +                                                   + s + "'");
    +
    +            // $VNUM is a dot-separated list of integers of arbitrary length
    +            List list = new ArrayList<>();
    +            for (String i : m.group(VNUM_GROUP).split("\\."))
    +                list.add(Integer.parseInt(i));
    +            version = Collections.unmodifiableList(list);
    +
    +            pre = Optional.ofNullable(m.group(PRE_GROUP));
    +
    +            String b = m.group(BUILD_GROUP);
    +            // $BUILD is an integer
    +            build = (b == null)
    +                ? Optional.empty()
    +                : Optional.ofNullable(Integer.parseInt(b));
    +
    +            optional = Optional.ofNullable(m.group(OPT_GROUP));
    +
    +            // empty '+'
    +            if ((m.group(PLUS_GROUP) != null) && !build.isPresent()) {
    +                if (optional.isPresent()) {
    +                    if (pre.isPresent())
    +                        throw new IllegalArgumentException("'+' found with"
    +                            + " pre-release and optional components:'" + s
    +                            + "'");
    +                } else {
    +                    throw new IllegalArgumentException("'+' found with neither"
    +                        + " build or optional components: '" + s + "'");
    +                }
    +            }
    +        }
    +
    +        /**
    +         * Parses the given string as a valid
    +         * version string containing a
    +         * version number followed by pre-release and
    +         * build information.
    +         *
    +         * @param  s
    +         *         A string to interpret as a version
    +         *
    +         * @throws  IllegalArgumentException
    +         *          If the given string cannot be interpreted as a valid
    +         *          version
    +         *
    +         * @throws  NullPointerException
    +         *          If the given string is {@code null}
    +         *
    +         * @throws  NumberFormatException
    +         *          If an element of the version number or the build number
    +         *          cannot be represented as an {@link Integer}
    +         *
    +         * @return  The Version of the given string
    +         */
    +        public static Version parse(String s) {
    +            return new Version(s);
    +        }
    +
    +        /**
    +         * Returns the major version number.
    +         *
    +         * @return  The major version number
    +         */
    +        public int major() {
    +            return version.get(0);
    +        }
    +
    +        /**
    +         * Returns the minor version number or zero if it
    +         * was not set.
    +         *
    +         * @return  The minor version number or zero if it was not set
    +         */
    +        public int minor() {
    +            return (version.size() > 1 ? version.get(1) : 0);
    +        }
    +
    +        /**
    +         * Returns the security version number or zero
    +         * if it was not set.
    +         *
    +         * @return  The security version number or zero if it was not set
    +         */
    +        public int security() {
    +            return (version.size() > 2 ? version.get(2) : 0);
    +        }
    +
    +        /**
    +         * Returns an unmodifiable {@link java.util.List List} of the
    +         * integer numerals contained in the version
    +         * number.  The {@code List} always contains at least one
    +         * element corresponding to the major version
    +         * number.
    +         *
    +         * @return  An unmodifiable list of the integer numerals
    +         *          contained in the version number
    +         */
    +        public List version() {
    +            return version;
    +        }
    +
    +        /**
    +         * Returns the optional pre-release information.
    +         *
    +         * @return  The optional pre-release information as a String
    +         */
    +        public Optional pre() {
    +            return pre;
    +        }
    +
    +        /**
    +         * Returns the build number.
    +         *
    +         * @return  The optional build number.
    +         */
    +        public Optional build() {
    +            return build;
    +        }
    +
    +        /**
    +         * Returns optional additional identifying build
    +         * information.
    +         *
    +         * @return  Additional build information as a String
    +         */
    +        public Optional optional() {
    +            return optional;
    +        }
    +
    +        /**
    +         * Compares this version to another.
    +         *
    +         * 

    Each of the components in the version is + * compared in the follow order of precedence: version numbers, + * pre-release identifiers, build numbers, optional build information. + *

    + * + *

    Comparison begins by examining the sequence of version numbers. + * If one sequence is shorter than another, then the missing elements + * of the shorter sequence are considered to be less than the + * corresponding elements of the longer sequence.

    + * + *

    A version with a pre-release identifier is always considered to + * be less than a version without one. Pre-release identifiers are + * compared numerically when they consist only of digits, and + * lexicographically otherwise. Numeric identifiers are considered to + * be less than non-numeric identifiers.

    + * + *

    A version without a build number is always less than one with a + * build number; otherwise build numbers are compared numerically.

    + * + *

    The optional build information is compared lexicographically. + * During this comparison, a version with optional build information is + * considered to be greater than a version without one.

    + * + *

    A version is not comparable to any other type of object. + * + * @param ob + * The object to be compared + * + * @return A negative integer, zero, or a positive integer if this + * {@code Version} is less than, equal to, or greater than the + * given {@code Version} + * + * @throws NullPointerException + * If the given object is {@code null} + */ + @Override + public int compareTo(Version ob) { + return compare(ob, false); + } + + /** + * Compares this version to another disregarding optional build + * information. + * + *

    Two versions are compared by examining the version string as + * described in {@link #compareTo(Version)} with the exception that the + * optional build information is always ignored.

    + * + *

    A version is not comparable to any other type of object. + * + * @param ob + * The object to be compared + * + * @return A negative integer, zero, or a positive integer if this + * {@code Version} is less than, equal to, or greater than the + * given {@code Version} + * + * @throws NullPointerException + * If the given object is {@code null} + */ + public int compareToIgnoreOpt(Version ob) { + return compare(ob, true); + } + + private int compare(Version ob, boolean ignoreOpt) { + if (ob == null) + throw new NullPointerException("Invalid argument"); + + int ret = compareVersion(ob); + if (ret != 0) + return ret; + + ret = comparePre(ob); + if (ret != 0) + return ret; + + ret = compareBuild(ob); + if (ret != 0) + return ret; + + if (!ignoreOpt) + return compareOpt(ob); + + return 0; + } + + private int compareVersion(Version ob) { + int size = version.size(); + int oSize = ob.version().size(); + int min = Math.min(size, oSize); + for (int i = 0; i < min; i++) { + Integer val = version.get(i); + Integer oVal = ob.version().get(i); + if (val != oVal) + return val - oVal; + } + if (size != oSize) + return size - oSize; + return 0; + } + + private int comparePre(Version ob) { + Optional oPre = ob.pre(); + if (!pre.isPresent()) { + if (oPre.isPresent()) + return 1; + } else { + if (!oPre.isPresent()) + return -1; + String val = pre.get(); + String oVal = oPre.get(); + if (val.matches("\\d+")) { + return (oVal.matches("\\d+") + ? (new BigInteger(val)).compareTo(new BigInteger(oVal)) + : -1); + } else { + return (oVal.matches("\\d+") + ? 1 + : val.compareTo(oVal)); + } + } + return 0; + } + + private int compareBuild(Version ob) { + Optional oBuild = ob.build(); + if (oBuild.isPresent()) { + return (build.isPresent() + ? build.get().compareTo(oBuild.get()) + : 1); + } else if (build.isPresent()) { + return -1; + } + return 0; + } + + private int compareOpt(Version ob) { + Optional oOpt = ob.optional(); + if (!optional.isPresent()) { + if (oOpt.isPresent()) + return -1; + } else { + if (!oOpt.isPresent()) + return 1; + return optional.get().compareTo(oOpt.get()); + } + return 0; + } + + /** + * Returns a string representation of this version. + * + * @return The version string + */ + @Override + public String toString() { + StringBuilder sb + = new StringBuilder(version.stream() + .map(Object::toString) + .collect(Collectors.joining("."))); + + pre.ifPresent(v -> sb.append("-").append(v)); + + if (build.isPresent()) { + sb.append("+").append(build.get()); + if (optional.isPresent()) + sb.append("-").append(optional.get()); + } else { + if (optional.isPresent()) { + sb.append(pre.isPresent() ? "-" : "+-"); + sb.append(optional.get()); + } + } + + return sb.toString(); + } + + /** + * Determines whether this {@code Version} is equal to another object. + * + *

    Two {@code Version}s are equal if and only if they represent the + * same version string. + * + *

    This method satisfies the general contract of the {@link + * Object#equals(Object) Object.equals} method.

    + * + * @param ob + * The object to which this {@code Version} is to be compared + * + * @return {@code true} if, and only if, the given object is a {@code + * Version} that is identical to this {@code Version} + * + */ + @Override + public boolean equals(Object ob) { + boolean ret = equalsIgnoreOpt(ob); + if (!ret) + return false; + + Version that = (Version)ob; + return (this.optional().equals(that.optional())); + } + + /** + * Determines whether this {@code Version} is equal to another + * disregarding optional build information. + * + *

    Two {@code Version}s are equal if and only if they represent the + * same version string disregarding the optional build information. + * + * @param ob + * The object to which this {@code Version} is to be compared + * + * @return {@code true} if, and only if, the given object is a {@code + * Version} that is identical to this {@code Version} + * ignoring the optinal build information + * + */ + public boolean equalsIgnoreOpt(Object ob) { + if (this == ob) + return true; + if (!(ob instanceof Version)) + return false; + + Version that = (Version)ob; + return (this.version().equals(that.version()) + && this.pre().equals(that.pre()) + && this.build().equals(that.build())); + } + + /** + * Returns the hash code of this version. + * + *

    This method satisfies the general contract of the {@link + * Object#hashCode Object.hashCode} method. + * + * @return The hashcode of this version + */ + @Override + public int hashCode() { + int h = 1; + int p = 17; + + h = p * h + version.hashCode(); + h = p * h + pre.hashCode(); + h = p * h + build.hashCode(); + h = p * h + optional.hashCode(); + + return h; + } + } + } diff --git a/jdk/src/java.base/share/classes/java/lang/StackWalker.java b/jdk/src/java.base/share/classes/java/lang/StackWalker.java index aef9c729a92..247cd467a83 100644 --- a/jdk/src/java.base/share/classes/java/lang/StackWalker.java +++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java @@ -306,8 +306,9 @@ public final class StackWalker { return DEFAULT_WALKER; } - checkPermission(options); - return new StackWalker(toEnumSet(options)); + EnumSet

    + * See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and + * a comparison to the integer division {@code /} operator. + * + * @param x the dividend + * @param y the divisor + * @return the largest (closest to positive infinity) + * {@code int} value that is less than or equal to the algebraic quotient. + * @throws ArithmeticException if the divisor {@code y} is zero + * @see Math#floorDiv(long, int) + * @see Math#floor(double) + * @since 9 + */ + public static long floorDiv(long x, int y) { + return Math.floorDiv(x, y); + } + /** * Returns the largest (closest to positive infinity) * {@code long} value that is less than or equal to the algebraic quotient. @@ -905,6 +971,35 @@ public final class StrictMath { public static int floorMod(int x, int y) { return Math.floorMod(x , y); } + + /** + * Returns the floor modulus of the {@code long} and {@int} arguments. + *

    + * The floor modulus is {@code x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y}, and + * is in the range of {@code -abs(y) < r < +abs(y)}. + * + *

    + * The relationship between {@code floorDiv} and {@code floorMod} is such that: + *

      + *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x} + *
    + *

    + * See {@link Math#floorMod(int, int) Math.floorMod} for examples and + * a comparison to the {@code %} operator. + * + * @param x the dividend + * @param y the divisor + * @return the floor modulus {@code x - (floorDiv(x, y) * y)} + * @throws ArithmeticException if the divisor {@code y} is zero + * @see Math#floorMod(long, int) + * @see StrictMath#floorDiv(long, int) + * @since 9 + */ + public static int floorMod(long x, int y) { + return Math.floorMod(x , y); + } + /** * Returns the floor modulus of the {@code long} arguments. *

    diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index ab7bb02c1f7..7ac564d959a 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -576,7 +576,8 @@ public final class System { * Key * Description of Associated Value * java.version - * Java Runtime Environment version + * Java Runtime Environment version which may be interpreted + * as a {@link Runtime.Version} * java.vendor * Java Runtime Environment vendor * java.vendor.url @@ -584,19 +585,22 @@ public final class System { * java.home * Java installation directory * java.vm.specification.version - * Java Virtual Machine specification version + * Java Virtual Machine specification version which may be + * interpreted as a {@link Runtime.Version} * java.vm.specification.vendor * Java Virtual Machine specification vendor * java.vm.specification.name * Java Virtual Machine specification name * java.vm.version - * Java Virtual Machine implementation version + * Java Virtual Machine implementation version which may be + * interpreted as a {@link Runtime.Version} * java.vm.vendor * Java Virtual Machine implementation vendor * java.vm.name * Java Virtual Machine implementation name * java.specification.version - * Java Runtime Environment specification version + * Java Runtime Environment specification version which may be + * interpreted as a {@link Runtime.Version} * java.specification.vendor * Java Runtime Environment specification vendor * java.specification.name diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java index 54fc27f31b5..310ada1b470 100644 --- a/jdk/src/java.base/share/classes/java/lang/Thread.java +++ b/jdk/src/java.base/share/classes/java/lang/Thread.java @@ -340,6 +340,45 @@ class Thread implements Runnable { sleep(millis); } + /** + * Indicates that the caller is momentarily unable to progress, until the + * occurrence of one or more actions on the part of other activities. By + * invoking this method within each iteration of a spin-wait loop construct, + * the calling thread indicates to the runtime that it is busy-waiting. + * The runtime may take action to improve the performance of invoking + * spin-wait loop constructions. + *

    + * @apiNote + * As an example consider a method in a class that spins in a loop until + * some flag is set outside of that method. A call to the {@code onSpinWait} + * method should be placed inside the spin loop. + *

    {@code
    +     *     class EventHandler {
    +     *         volatile boolean eventNotificationNotReceived;
    +     *         void waitForEventAndHandleIt() {
    +     *             while ( eventNotificationNotReceived ) {
    +     *                 java.lang.Thread.onSpinWait();
    +     *             }
    +     *             readAndProcessEvent();
    +     *         }
    +     *
    +     *         void readAndProcessEvent() {
    +     *             // Read event from some source and process it
    +     *              . . .
    +     *         }
    +     *     }
    +     * }
    + *

    + * The code above would remain correct even if the {@code onSpinWait} + * method was not called at all. However on some architectures the Java + * Virtual Machine may issue the processor instructions to address such + * code patterns in a more beneficial way. + *

    + * @since 9 + */ + @HotSpotIntrinsicCandidate + public static void onSpinWait() {} + /** * Initializes a Thread with the current AccessControlContext. * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean) diff --git a/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java b/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java index 4590f39edd1..c32ae6a0f15 100644 --- a/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java +++ b/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java @@ -46,7 +46,7 @@ package java.lang.annotation; * {@code @Target(ElementType.FIELD)} may only be written as a modifier for a * field declaration. * - *

    The constant {@link #TYPE_USE} corresponds to the 15 type contexts in JLS + *

    The constant {@link #TYPE_USE} corresponds to the type contexts in JLS * 4.11, as well as to two declaration contexts: type declarations (including * annotation type declarations) and type parameter declarations. * diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 08e38987bf2..da1700ffdb1 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -706,6 +706,9 @@ class InvokerBytecodeGenerator { case ARRAY_STORE: emitArrayStore(name); continue; + case ARRAY_LENGTH: + emitArrayLength(name); + continue; case IDENTITY: assert(name.arguments.length == 1); emitPushArguments(name); @@ -740,15 +743,16 @@ class InvokerBytecodeGenerator { return classFile; } - void emitArrayLoad(Name name) { emitArrayOp(name, Opcodes.AALOAD); } - void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); } + void emitArrayLoad(Name name) { emitArrayOp(name, Opcodes.AALOAD); } + void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); } + void emitArrayLength(Name name) { emitArrayOp(name, Opcodes.ARRAYLENGTH); } void emitArrayOp(Name name, int arrayOpcode) { - assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE; + assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE || arrayOpcode == Opcodes.ARRAYLENGTH; Class elementType = name.function.methodType().parameterType(0).getComponentType(); assert elementType != null; emitPushArguments(name); - if (elementType.isPrimitive()) { + if (arrayOpcode != Opcodes.ARRAYLENGTH && elementType.isPrimitive()) { Wrapper w = Wrapper.forPrimitiveType(elementType); arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java index 29cc430f877..1aca86298fe 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java @@ -95,12 +95,12 @@ class Invokers { /*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) { // TODO cache invoker - return makeVarHandleMethodInvoker(ak); + return makeVarHandleMethodInvoker(ak, false); } /*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) { // TODO cache invoker - return makeVarHandleMethodExactInvoker(ak); + return makeVarHandleMethodInvoker(ak, true); } private MethodHandle cachedInvoker(int idx) { @@ -127,26 +127,11 @@ class Invokers { return invoker; } - private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) { + private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak, boolean isExact) { MethodType mtype = targetType; MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class); - LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.methodName(), mtype); - VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal()); - MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad); - - invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.methodName(), mtype), false); - assert(checkVarHandleInvoker(invoker)); - - maybeCompileToBytecode(invoker); - return invoker; - } - - private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) { - MethodType mtype = targetType; - MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class); - - LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.methodName(), mtype); + LambdaForm lform = varHandleMethodInvokerHandleForm(ak.methodName(), mtype, isExact); VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal()); MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad); @@ -400,59 +385,7 @@ class Invokers { return lform; } - private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) { - // TODO Cache form? - - final int THIS_MH = 0; - final int CALL_VH = THIS_MH + 1; - final int ARG_BASE = CALL_VH + 1; - final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); - int nameCursor = ARG_LIMIT; - final int VAD_ARG = nameCursor++; - final int CHECK_TYPE = nameCursor++; - final int GET_MEMBER = nameCursor++; - final int LINKER_CALL = nameCursor++; - - MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class) - .basicType() - .appendParameterTypes(MemberName.class); - - MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic); - try { - linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - - Name[] names = new Name[LINKER_CALL + 1]; - names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class)); - names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class)); - for (int i = 0; i < mtype.parameterCount(); i++) { - names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i))); - } - - BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L(); - names[THIS_MH] = names[THIS_MH].withConstraint(speciesData); - - NamedFunction getter = speciesData.getterFunction(0); - names[VAD_ARG] = new Name(getter, names[THIS_MH]); - - Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class); - - names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]); - - names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]); - outArgs[outArgs.length - 1] = names[GET_MEMBER]; - - names[LINKER_CALL] = new Name(linker, outArgs); - LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)), - ARG_LIMIT, names); - - lform.compileToBytecode(); - return lform; - } - - private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) { + private static LambdaForm varHandleMethodInvokerHandleForm(String name, MethodType mtype, boolean isExact) { // TODO Cache form? final int THIS_MH = 0; @@ -477,8 +410,11 @@ class Invokers { NamedFunction getter = speciesData.getterFunction(0); names[VAD_ARG] = new Name(getter, names[THIS_MH]); - names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]); - + if (isExact) { + names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]); + } else { + names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]); + } Object[] outArgs = new Object[ARG_LIMIT]; outArgs[0] = names[CHECK_TYPE]; for (int i = 1; i < ARG_LIMIT; i++) { @@ -488,7 +424,8 @@ class Invokers { MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class) .basicType(); names[LINKER_CALL] = new Name(outCallType, outArgs); - LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)), + String debugName = isExact ? ":VarHandle_exactInvoker" : ":VarHandle_invoker"; + LambdaForm lform = new LambdaForm(name + debugName + shortenSignature(basicTypeSignature(mtype)), ARG_LIMIT, names); lform.prepare(); @@ -511,21 +448,13 @@ class Invokers { /*non-public*/ static @ForceInline - void checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) { - MethodType erasedTarget = handle.vform.methodType_table[ad.type]; - MethodType erasedSymbolic = ad.symbolicMethodTypeErased; - if (erasedTarget != erasedSymbolic) - throw newWrongMethodTypeException(erasedTarget, erasedSymbolic); - } - - /*non-public*/ static - @ForceInline - MemberName getVarHandleMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) { - MemberName mn = handle.vform.memberName_table[ad.mode]; - if (mn == null) { - throw handle.unsupported(); + MethodHandle checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) { + MethodHandle mh = handle.getMethodHandle(ad.mode); + MethodType mt = mh.type(); + if (mt != ad.symbolicMethodTypeInvoker) { + throw newWrongMethodTypeException(mt, ad.symbolicMethodTypeInvoker); } - return mn; + return mh; } /*non-public*/ static @@ -649,8 +578,7 @@ class Invokers { NF_getCallSiteTarget, NF_checkCustomized, NF_checkVarHandleGenericType, - NF_checkVarHandleExactType, - NF_getVarHandleMemberName; + NF_checkVarHandleExactType; static { try { NamedFunction nfs[] = { @@ -666,8 +594,6 @@ class Invokers { .getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)), NF_checkVarHandleExactType = new NamedFunction(Invokers.class .getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)), - NF_getVarHandleMemberName = new NamedFunction(Invokers.class - .getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class)) }; // Each nf must be statically invocable or we get tied up in our bootstraps. assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs)); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index 782eff613ae..ac0b5847fff 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -41,9 +41,15 @@ import sun.invoke.empty.Empty; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyType; import sun.invoke.util.Wrapper; + +import jdk.internal.org.objectweb.asm.AnnotationVisitor; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; + import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; +import static jdk.internal.org.objectweb.asm.Opcodes.*; /** * Trusted implementation code for MethodHandle. @@ -66,25 +72,28 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; /// Factory methods to create method handles: - static MethodHandle makeArrayElementAccessor(Class arrayClass, boolean isSetter) { - if (arrayClass == Object[].class) - return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER); + static MethodHandle makeArrayElementAccessor(Class arrayClass, ArrayAccess access) { + if (arrayClass == Object[].class) { + return ArrayAccess.objectAccessor(access); + } if (!arrayClass.isArray()) throw newIllegalArgumentException("not an array: "+arrayClass); MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass); - int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX); + int cacheIndex = ArrayAccess.cacheIndex(access); MethodHandle mh = cache[cacheIndex]; if (mh != null) return mh; - mh = ArrayAccessor.getAccessor(arrayClass, isSetter); - MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter); + mh = ArrayAccessor.getAccessor(arrayClass, access); + MethodType correctType = ArrayAccessor.correctType(arrayClass, access); if (mh.type() != correctType) { assert(mh.type().parameterType(0) == Object[].class); - assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class); - assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType()); + /* if access == SET */ assert(access != ArrayAccess.SET || mh.type().parameterType(2) == Object.class); + /* if access == GET */ assert(access != ArrayAccess.GET || + (mh.type().returnType() == Object.class && + correctType.parameterType(0).getComponentType() == correctType.returnType())); // safe to view non-strictly, because element type follows from array type mh = mh.viewAsType(correctType, false); } - mh = makeIntrinsic(mh, (isSetter ? Intrinsic.ARRAY_STORE : Intrinsic.ARRAY_LOAD)); + mh = makeIntrinsic(mh, ArrayAccess.intrinsic(access)); // Atomically update accessor cache. synchronized(cache) { if (cache[cacheIndex] == null) { @@ -97,9 +106,56 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return mh; } + enum ArrayAccess { + GET, SET, LENGTH; + + // As ArrayAccess and ArrayAccessor have a circular dependency, the ArrayAccess properties cannot be stored in + // final fields. + + static String opName(ArrayAccess a) { + switch (a) { + case GET: return "getElement"; + case SET: return "setElement"; + case LENGTH: return "length"; + } + throw unmatchedArrayAccess(a); + } + + static MethodHandle objectAccessor(ArrayAccess a) { + switch (a) { + case GET: return ArrayAccessor.OBJECT_ARRAY_GETTER; + case SET: return ArrayAccessor.OBJECT_ARRAY_SETTER; + case LENGTH: return ArrayAccessor.OBJECT_ARRAY_LENGTH; + } + throw unmatchedArrayAccess(a); + } + + static int cacheIndex(ArrayAccess a) { + switch (a) { + case GET: return ArrayAccessor.GETTER_INDEX; + case SET: return ArrayAccessor.SETTER_INDEX; + case LENGTH: return ArrayAccessor.LENGTH_INDEX; + } + throw unmatchedArrayAccess(a); + } + + static Intrinsic intrinsic(ArrayAccess a) { + switch (a) { + case GET: return Intrinsic.ARRAY_LOAD; + case SET: return Intrinsic.ARRAY_STORE; + case LENGTH: return Intrinsic.ARRAY_LENGTH; + } + throw unmatchedArrayAccess(a); + } + } + + static InternalError unmatchedArrayAccess(ArrayAccess a) { + return newInternalError("should not reach here (unmatched ArrayAccess: " + a + ")"); + } + static final class ArrayAccessor { - /// Support for array element access - static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2; + /// Support for array element and length access + static final int GETTER_INDEX = 0, SETTER_INDEX = 1, LENGTH_INDEX = 2, INDEX_LIMIT = 3; static final ClassValue TYPED_ACCESSORS = new ClassValue() { @Override @@ -107,14 +163,16 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return new MethodHandle[INDEX_LIMIT]; } }; - static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER; + static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER, OBJECT_ARRAY_LENGTH; static { MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class); - cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, false), Intrinsic.ARRAY_LOAD); - cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, true), Intrinsic.ARRAY_STORE); + cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.GET), Intrinsic.ARRAY_LOAD); + cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.SET), Intrinsic.ARRAY_STORE); + cache[LENGTH_INDEX] = OBJECT_ARRAY_LENGTH = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.LENGTH), Intrinsic.ARRAY_LENGTH); assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName())); assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName())); + assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_LENGTH.internalMemberName())); } static int getElementI(int[] a, int i) { return a[i]; } @@ -137,31 +195,47 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static void setElementC(char[] a, int i, char x) { a[i] = x; } static void setElementL(Object[] a, int i, Object x) { a[i] = x; } - static String name(Class arrayClass, boolean isSetter) { + static int lengthI(int[] a) { return a.length; } + static int lengthJ(long[] a) { return a.length; } + static int lengthF(float[] a) { return a.length; } + static int lengthD(double[] a) { return a.length; } + static int lengthZ(boolean[] a) { return a.length; } + static int lengthB(byte[] a) { return a.length; } + static int lengthS(short[] a) { return a.length; } + static int lengthC(char[] a) { return a.length; } + static int lengthL(Object[] a) { return a.length; } + + static String name(Class arrayClass, ArrayAccess access) { Class elemClass = arrayClass.getComponentType(); if (elemClass == null) throw newIllegalArgumentException("not an array", arrayClass); - return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass); + return ArrayAccess.opName(access) + Wrapper.basicTypeChar(elemClass); } - static MethodType type(Class arrayClass, boolean isSetter) { + static MethodType type(Class arrayClass, ArrayAccess access) { Class elemClass = arrayClass.getComponentType(); Class arrayArgClass = arrayClass; if (!elemClass.isPrimitive()) { arrayArgClass = Object[].class; elemClass = Object.class; } - return !isSetter ? - MethodType.methodType(elemClass, arrayArgClass, int.class) : - MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); + switch (access) { + case GET: return MethodType.methodType(elemClass, arrayArgClass, int.class); + case SET: return MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); + case LENGTH: return MethodType.methodType(int.class, arrayArgClass); + } + throw unmatchedArrayAccess(access); } - static MethodType correctType(Class arrayClass, boolean isSetter) { + static MethodType correctType(Class arrayClass, ArrayAccess access) { Class elemClass = arrayClass.getComponentType(); - return !isSetter ? - MethodType.methodType(elemClass, arrayClass, int.class) : - MethodType.methodType(void.class, arrayClass, int.class, elemClass); + switch (access) { + case GET: return MethodType.methodType(elemClass, arrayClass, int.class); + case SET: return MethodType.methodType(void.class, arrayClass, int.class, elemClass); + case LENGTH: return MethodType.methodType(int.class, arrayClass); + } + throw unmatchedArrayAccess(access); } - static MethodHandle getAccessor(Class arrayClass, boolean isSetter) { - String name = name(arrayClass, isSetter); - MethodType type = type(arrayClass, isSetter); + static MethodHandle getAccessor(Class arrayClass, ArrayAccess access) { + String name = name(arrayClass, access); + MethodType type = type(arrayClass, access); try { return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type); } catch (ReflectiveOperationException ex) { @@ -1091,6 +1165,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; // Put the whole mess into its own nested class. // That way we can lazily load the code and set up the constants. private static class BindCaller { + private static MethodType INVOKER_MT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class); + static MethodHandle bindCaller(MethodHandle mh, Class hostClass) { // Do not use this function to inject calls into system classes. @@ -1109,38 +1185,15 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; } private static MethodHandle makeInjectedInvoker(Class hostClass) { - Class bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null); - if (hostClass.getClassLoader() != bcc.getClassLoader()) - throw new InternalError(hostClass.getName()+" (CL)"); try { - if (hostClass.getProtectionDomain() != bcc.getProtectionDomain()) - throw new InternalError(hostClass.getName()+" (PD)"); - } catch (SecurityException ex) { - // Self-check was blocked by security manager. This is OK. - // In fact the whole try body could be turned into an assertion. - } - try { - MethodHandle init = IMPL_LOOKUP.findStatic(bcc, "init", MethodType.methodType(void.class)); - init.invokeExact(); // force initialization of the class - } catch (Throwable ex) { - throw uncaughtException(ex); - } - MethodHandle bccInvoker; - try { - MethodType invokerMT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class); - bccInvoker = IMPL_LOOKUP.findStatic(bcc, "invoke_V", invokerMT); + Class invokerClass = UNSAFE.defineAnonymousClass(hostClass, INJECTED_INVOKER_TEMPLATE, null); + assert checkInjectedInvoker(hostClass, invokerClass); + return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT); } catch (ReflectiveOperationException ex) { throw uncaughtException(ex); } - // Test the invoker, to ensure that it really injects into the right place. - try { - MethodHandle vamh = prepareForInvoker(MH_checkCallerClass); - Object ok = bccInvoker.invokeExact(vamh, new Object[]{hostClass, bcc}); - } catch (Throwable ex) { - throw new InternalError(ex); - } - return bccInvoker; } + private static ClassValue CV_makeInjectedInvoker = new ClassValue() { @Override protected MethodHandle computeValue(Class hostClass) { return makeInjectedInvoker(hostClass); @@ -1171,62 +1224,82 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return mh; } + private static boolean checkInjectedInvoker(Class hostClass, Class invokerClass) { + assert (hostClass.getClassLoader() == invokerClass.getClassLoader()) : hostClass.getName()+" (CL)"; + try { + assert (hostClass.getProtectionDomain() == invokerClass.getProtectionDomain()) : hostClass.getName()+" (PD)"; + } catch (SecurityException ex) { + // Self-check was blocked by security manager. This is OK. + } + try { + // Test the invoker to ensure that it really injects into the right place. + MethodHandle invoker = IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT); + MethodHandle vamh = prepareForInvoker(MH_checkCallerClass); + return (boolean)invoker.invoke(vamh, new Object[]{ invokerClass }); + } catch (Throwable ex) { + throw new InternalError(ex); + } + } + private static final MethodHandle MH_checkCallerClass; static { final Class THIS_CLASS = BindCaller.class; - assert(checkCallerClass(THIS_CLASS, THIS_CLASS)); + assert(checkCallerClass(THIS_CLASS)); try { MH_checkCallerClass = IMPL_LOOKUP .findStatic(THIS_CLASS, "checkCallerClass", - MethodType.methodType(boolean.class, Class.class, Class.class)); - assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS, THIS_CLASS)); + MethodType.methodType(boolean.class, Class.class)); + assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS)); } catch (Throwable ex) { throw new InternalError(ex); } } @CallerSensitive - private static boolean checkCallerClass(Class expected, Class expected2) { - // This method is called via MH_checkCallerClass and so it's - // correct to ask for the immediate caller here. + private static boolean checkCallerClass(Class expected) { + // This method is called via MH_checkCallerClass and so it's correct to ask for the immediate caller here. Class actual = Reflection.getCallerClass(); - if (actual != expected && actual != expected2) - throw new InternalError("found "+actual.getName()+", expected "+expected.getName() - +(expected == expected2 ? "" : ", or else "+expected2.getName())); + if (actual != expected) + throw new InternalError("found " + actual.getName() + ", expected " + expected.getName()); return true; } - private static final byte[] T_BYTES; - static { - final Object[] values = {null}; - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - try { - Class tClass = T.class; - String tName = tClass.getName(); - String tResource = tName.substring(tName.lastIndexOf('.')+1)+".class"; - try (java.io.InputStream in = tClass.getResourceAsStream(tResource)) { - values[0] = in.readAllBytes(); - } - } catch (java.io.IOException ex) { - throw new InternalError(ex); - } - return null; - } - }); - T_BYTES = (byte[]) values[0]; - } + private static final byte[] INJECTED_INVOKER_TEMPLATE = generateInvokerTemplate(); - // The following class is used as a template for Unsafe.defineAnonymousClass: - private static class T { - static void init() { } // side effect: initializes this class - static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable { - return vamh.invokeExact(args); - } + /** Produces byte code for a class that is used as an injected invoker. */ + private static byte[] generateInvokerTemplate() { + ClassWriter cw = new ClassWriter(0); + + // private static class InjectedInvoker { + // @Hidden + // static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable { + // return vamh.invokeExact(args); + // } + // } + cw.visit(52, ACC_PRIVATE | ACC_SUPER, "InjectedInvoker", null, "java/lang/Object", null); + + MethodVisitor mv = cw.visitMethod(ACC_STATIC, "invoke_V", + "(Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;", + null, null); + + // Suppress invoker method in stack traces. + AnnotationVisitor av0 = mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); + av0.visitEnd(); + + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact", + "([Ljava/lang/Object;)Ljava/lang/Object;", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 2); + mv.visitEnd(); + + cw.visitEnd(); + return cw.toByteArray(); } } - /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */ private static final class WrappedMember extends DelegatingMethodHandle { private final MethodHandle target; @@ -1282,6 +1355,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; NEW_ARRAY, ARRAY_LOAD, ARRAY_STORE, + ARRAY_LENGTH, IDENTITY, ZERO, NONE // no intrinsic associated diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index c3a97a178a3..716d62ff177 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2244,6 +2244,21 @@ return mh1; return ani.asType(ani.type().changeReturnType(arrayClass)); } + /** + * Produces a method handle returning the length of an array. + * The type of the method handle will have {@code int} as return type, + * and its sole argument will be the array type. + * @param arrayClass an array type + * @return a method handle which can retrieve the length of an array of the given array type + * @throws NullPointerException if the argument is {@code null} + * @throws IllegalArgumentException if arrayClass is not an array type + * @since 9 + */ + public static + MethodHandle arrayLength(Class arrayClass) throws IllegalArgumentException { + return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.LENGTH); + } + /** * Produces a method handle giving read access to elements of an array. * The type of the method handle will have a return type of the array's @@ -2256,7 +2271,7 @@ return mh1; */ public static MethodHandle arrayElementGetter(Class arrayClass) throws IllegalArgumentException { - return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false); + return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.GET); } /** @@ -2271,7 +2286,7 @@ return mh1; */ public static MethodHandle arrayElementSetter(Class arrayClass) throws IllegalArgumentException { - return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true); + return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET); } /** diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 0d965ed5a54..7da455097b8 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -128,7 +128,7 @@ public final class StringConcatFactory { /** * Default strategy to use for concatenation. */ - private static final Strategy DEFAULT_STRATEGY = Strategy.BC_SB; + private static final Strategy DEFAULT_STRATEGY = Strategy.MH_INLINE_SIZED_EXACT; private enum Strategy { /** diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 78a75bf05cc..ee7be4096bf 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -26,6 +26,7 @@ package java.lang.invoke; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; @@ -33,7 +34,6 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; @@ -1475,11 +1475,11 @@ public abstract class VarHandle { TypesAndInvokers tis = getTypesAndInvokers(); MethodHandle mh = tis.methodHandle_table[mode]; if (mh == null) { - mh = tis.methodHandle_table[mode] = getMethodHandleUncached(tis, mode); + mh = tis.methodHandle_table[mode] = getMethodHandleUncached(mode); } return mh; } - private final MethodHandle getMethodHandleUncached(TypesAndInvokers tis, int mode) { + private final MethodHandle getMethodHandleUncached(int mode) { MethodType mt = accessModeType(AccessMode.values()[mode]). insertParameterTypes(0, VarHandle.class); MemberName mn = vform.getMemberName(mode); @@ -1501,7 +1501,7 @@ public abstract class VarHandle { } static final BiFunction, ArrayIndexOutOfBoundsException> - AIOOBE_SUPPLIER = Objects.outOfBoundsExceptionFormatter( + AIOOBE_SUPPLIER = Preconditions.outOfBoundsExceptionFormatter( new Function() { @Override public ArrayIndexOutOfBoundsException apply(String s) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template index 7a058afedec..ebb6dd31b79 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template +++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template @@ -24,9 +24,11 @@ */ package java.lang.invoke; -import java.util.Objects; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; +import java.util.Objects; + import static java.lang.invoke.MethodHandleStatics.UNSAFE; #warn @@ -163,8 +165,7 @@ final class VarHandle$Type$s { @ForceInline static boolean weakCompareAndSetVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) { - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)), + return UNSAFE.weakCompareAndSwap$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)), handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, {#if[Object]?handle.fieldType.cast(value):value}); @@ -345,8 +346,7 @@ final class VarHandle$Type$s { @ForceInline static boolean weakCompareAndSetVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) { - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$Type$(handle.base, + return UNSAFE.weakCompareAndSwap$Type$Volatile(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, {#if[Object]?handle.fieldType.cast(value):value}); @@ -447,7 +447,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -458,7 +458,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } @@ -470,7 +470,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Opaque(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -481,7 +481,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Opaque(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } @@ -493,7 +493,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -504,7 +504,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } #if[CAS] @@ -517,7 +517,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndSwap$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -530,7 +530,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -543,7 +543,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -556,7 +556,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -569,7 +569,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -581,9 +581,8 @@ final class VarHandle$Type$s { #else[Object] $type$[] array = ($type$[]) oarray; #end[Object] - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + return UNSAFE.weakCompareAndSwap$Type$Volatile(array, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -596,7 +595,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -609,7 +608,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -622,7 +621,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndSet$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } #end[CAS] @@ -636,7 +635,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndAdd$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, value); } @@ -648,7 +647,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndAdd$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, value) + value; } #end[AtomicAdd] diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template index 8639e0d342e..66bf267476e 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template +++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template @@ -25,6 +25,7 @@ package java.lang.invoke; import jdk.internal.misc.Unsafe; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; import java.nio.ByteBuffer; @@ -81,7 +82,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static int index(byte[] ba, int index) { - return Objects.checkIndex(index, ba.length - ALIGN, null); + return Preconditions.checkIndex(index, ba.length - ALIGN, null); } @ForceInline @@ -233,8 +234,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static boolean weakCompareAndSetVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) { byte[] ba = (byte[]) oba; - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$RawType$( + return UNSAFE.weakCompareAndSwap$RawType$Volatile( ba, address(ba, index(ba, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); @@ -271,22 +271,33 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { #if[AtomicAdd] @ForceInline - static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) { + static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ delta) { byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.getAndAdd$RawType$( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value))); + if (handle.be == BE) { + return UNSAFE.getAndAdd$RawType$( + ba, + address(ba, index(ba, index)), + delta); + } else { + return getAndAddConvEndianWithCAS(ba, index, delta); + } } @ForceInline - static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) { - byte[] ba = (byte[]) oba; - return convEndian(handle.be, UNSAFE.getAndAdd$RawType$( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value))) + value; + static $type$ getAndAddConvEndianWithCAS(byte[] ba, int index, $type$ delta) { + $type$ nativeExpectedValue, expectedValue; + long offset = address(ba, index(ba, index)); + do { + nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset); + expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); + } while (!UNSAFE.weakCompareAndSwap$RawType$Volatile(ba, offset, + nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta))); + return expectedValue; + } + + @ForceInline + static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ delta) { + return getAndAdd(handle, oba, index, delta) + delta; } #end[AtomicAdd] @@ -307,14 +318,14 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static int index(ByteBuffer bb, int index) { - return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); + return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); } @ForceInline static int indexRO(ByteBuffer bb, int index) { if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY)) throw new ReadOnlyBufferException(); - return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); + return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); } @ForceInline @@ -466,8 +477,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static boolean weakCompareAndSetVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) { ByteBuffer bb = (ByteBuffer) obb; - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$RawType$( + return UNSAFE.weakCompareAndSwap$RawType$Volatile( UNSAFE.getObject(bb, BYTE_BUFFER_HB), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); @@ -504,23 +514,34 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { #if[AtomicAdd] @ForceInline - static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) { + static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ delta) { ByteBuffer bb = (ByteBuffer) obb; - return convEndian(handle.be, - UNSAFE.getAndAdd$RawType$( - UNSAFE.getObject(bb, BYTE_BUFFER_HB), - address(bb, indexRO(bb, index)), - convEndian(handle.be, value))); + if (handle.be == BE) { + return UNSAFE.getAndAdd$RawType$( + UNSAFE.getObject(bb, BYTE_BUFFER_HB), + address(bb, indexRO(bb, index)), + delta); + } else { + return getAndAddConvEndianWithCAS(bb, index, delta); + } } @ForceInline - static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) { - ByteBuffer bb = (ByteBuffer) obb; - return convEndian(handle.be, - UNSAFE.getAndAdd$RawType$( - UNSAFE.getObject(bb, BYTE_BUFFER_HB), - address(bb, indexRO(bb, index)), - convEndian(handle.be, value))) + value; + static $type$ getAndAddConvEndianWithCAS(ByteBuffer bb, int index, $type$ delta) { + $type$ nativeExpectedValue, expectedValue; + Object base = UNSAFE.getObject(bb, BYTE_BUFFER_HB); + long offset = address(bb, indexRO(bb, index)); + do { + nativeExpectedValue = UNSAFE.get$RawType$Volatile(base, offset); + expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); + } while (!UNSAFE.weakCompareAndSwap$RawType$Volatile(base, offset, + nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta))); + return expectedValue; + } + + @ForceInline + static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ delta) { + return getAndAdd(handle, obb, index, delta) + delta; } #end[AtomicAdd] diff --git a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java index 4b6ab934dcf..d1efde87f50 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java +++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java @@ -152,7 +152,7 @@ import java.util.stream.Collectors; * Configuration parent = Layer.boot().configuration(); * * Configuration cf = parent.resolveRequires(finder, - * ModuleFinder.empty(), + * ModuleFinder.of(), * Set.of("myapp")); * cf.modules().forEach(m -> { * System.out.format("%s -> %s%n", @@ -366,7 +366,7 @@ public final class Configuration { Configuration parent = empty(); Resolver resolver - = new Resolver(finder, parent, ModuleFinder.empty(), traceOutput); + = new Resolver(finder, parent, ModuleFinder.of(), traceOutput); resolver.resolveRequires(roots).resolveUses(); return new Configuration(parent, resolver, check); diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java index 1cdd12838b1..a6924484c0e 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java @@ -33,12 +33,15 @@ import java.nio.file.Paths; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; import sun.security.action.GetPropertyAction; /** @@ -60,15 +63,15 @@ import sun.security.action.GetPropertyAction; * ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3); * * Optional omref = finder.find("jdk.foo"); - * if (omref.isPresent()) { ... } + * omref.ifPresent(mref -> ... ); * * }

    * *

    The {@link #find(String) find} and {@link #findAll() findAll} methods - * defined here can fail for several reasons. These include include I/O errors, - * errors detected parsing a module descriptor ({@code module-info.class}), or - * in the case of {@code ModuleFinder} returned by {@link #of ModuleFinder.of}, - * that two or more modules with the same name are found in a directory. + * defined here can fail for several reasons. These include I/O errors, errors + * detected parsing a module descriptor ({@code module-info.class}), or in the + * case of {@code ModuleFinder} returned by {@link #of ModuleFinder.of}, that + * two or more modules with the same name are found in a directory. * When an error is detected then these methods throw {@link FindException * FindException} with an appropriate {@link Throwable#getCause cause}. * The behavior of a {@code ModuleFinder} after a {@code FindException} is @@ -205,11 +208,13 @@ public interface ModuleFinder { * *

    The module finder returned by this method supports modules that are * packaged as JAR files. A JAR file with a {@code module-info.class} in - * the top-level directory of the JAR file is a modular JAR and is an - * explicit module. A JAR file that does not have a {@code - * module-info.class} in the top-level directory is an {@link - * ModuleDescriptor#isAutomatic automatic} module. The {@link - * ModuleDescriptor} for an automatic module is created as follows: + * the top-level directory of the JAR file (or overridden by a versioned + * entry in a {@link java.util.jar.JarFile#isMultiRelease() multi-release} + * JAR file) is a modular JAR and is an explicit module. + * A JAR file that does not have a {@code module-info.class} in the + * top-level directory is an {@link ModuleDescriptor#isAutomatic automatic} + * module. The {@link ModuleDescriptor} for an automatic module is created as + * follows: * *

      * @@ -263,18 +268,22 @@ public interface ModuleFinder { *
    * *

    In addition to JAR files, an implementation may also support modules - * that are packaged in other implementation specific module formats. As - * with automatic modules, the contents of a packaged or exploded module - * may need to be scanned in order to determine the packages in - * the module. If a {@code .class} file that corresponds to a class in an + * that are packaged in other implementation specific module formats. When + * a file is encountered that is not recognized as a packaged module then + * {@code FindException} is thrown. An implementation may choose to ignore + * some files, {@link java.nio.file.Files#isHidden hidden} files for + * example. Paths to files that do not exist are always ignored.

    + * + *

    As with automatic modules, the contents of a packaged or exploded + * module may need to be scanned in order to determine the packages + * in the module. If a {@code .class} file that corresponds to a class in an * unnamed package is encountered then {@code FindException} is thrown.

    * *

    Finders created by this method are lazy and do not eagerly check * that the given file paths are directories or packaged modules. * Consequently, the {@code find} or {@code findAll} methods will only * fail if invoking these methods results in searching a directory or - * packaged module and an error is encountered. Paths to files that do not - * exist are ignored.

    + * packaged module and an error is encountered.

    * * @param entries * A possibly-empty array of paths to directories of modules @@ -283,81 +292,87 @@ public interface ModuleFinder { * @return A {@code ModuleFinder} that locates modules on the file system */ static ModuleFinder of(Path... entries) { + // special case zero entries + if (entries.length == 0) { + return new ModuleFinder() { + @Override + public Optional find(String name) { + Objects.requireNonNull(name); + return Optional.empty(); + } + + @Override + public Set findAll() { + return Collections.emptySet(); + } + }; + } + return new ModulePath(entries); } /** - * Returns a module finder that is the equivalent to composing two - * module finders. The resulting finder will locate modules references - * using {@code first}; if not found then it will attempt to locate module - * references using {@code second}. + * Returns a module finder that is composed from a sequence of zero or more + * module finders. The {@link #find(String) find} method of the resulting + * module finder will locate a module by invoking the {@code find} method + * of each module finder, in array index order, until either the module is + * found or all module finders have been searched. The {@link #findAll() + * findAll} method of the resulting module finder will return a set of + * modules that includes all modules located by the first module finder. + * The set of modules will include all modules located by the second or + * subsequent module finder that are not located by previous module finders + * in the sequence. * - *

    The {@link #findAll() findAll} method of the resulting module finder - * will locate all modules located by the first module finder. It will - * also locate all modules located by the second module finder that are not - * located by the first module finder.

    + *

    When locating modules then any exceptions or errors thrown by the + * {@code find} or {@code findAll} methods of the underlying module finders + * will be propogated to the caller of the resulting module finder's + * {@code find} or {@code findAll} methods.

    * - * @apiNote This method will eventually be changed to take a sequence of - * module finders. + * @param finders + * The array of module finders * - * @param first - * The first module finder - * @param second - * The second module finder - * - * @return A {@code ModuleFinder} that composes two module finders + * @return A {@code ModuleFinder} that composes a sequence of module finders */ - static ModuleFinder compose(ModuleFinder first, ModuleFinder second) { - Objects.requireNonNull(first); - Objects.requireNonNull(second); + static ModuleFinder compose(ModuleFinder... finders) { + final List finderList = Arrays.asList(finders); + finderList.forEach(Objects::requireNonNull); return new ModuleFinder() { - Set allModules; + private final Map nameToModule = new HashMap<>(); + private Set allModules; @Override public Optional find(String name) { - Optional om = first.find(name); - if (!om.isPresent()) - om = second.find(name); - return om; + // cached? + ModuleReference mref = nameToModule.get(name); + if (mref != null) + return Optional.of(mref); + Optional omref = finderList.stream() + .map(f -> f.find(name)) + .flatMap(Optional::stream) + .findFirst(); + omref.ifPresent(m -> nameToModule.put(name, m)); + return omref; } + @Override public Set findAll() { - if (allModules == null) { - allModules = Stream.concat(first.findAll().stream(), - second.findAll().stream()) - .map(a -> a.descriptor().name()) - .distinct() - .map(this::find) - .map(Optional::get) - .collect(Collectors.toSet()); - } + if (allModules != null) + return allModules; + // seed with modules already found + Set result = new HashSet<>(nameToModule.values()); + finderList.stream() + .flatMap(f -> f.findAll().stream()) + .forEach(mref -> { + String name = mref.descriptor().name(); + if (nameToModule.putIfAbsent(name, mref) == null) { + result.add(mref); + } + }); + allModules = Collections.unmodifiableSet(result); return allModules; } }; } - /** - * Returns an empty module finder. The empty finder does not find any - * modules. - * - * @apiNote This is useful when using methods such as {@link - * Configuration#resolveRequires resolveRequires} where two finders are - * specified. An alternative is {@code ModuleFinder.of()}. - * - * @return A {@code ModuleFinder} that does not find any modules - */ - static ModuleFinder empty() { - // an alternative implementation of ModuleFinder.of() - return new ModuleFinder() { - @Override public Optional find(String name) { - Objects.requireNonNull(name); - return Optional.empty(); - } - @Override public Set findAll() { - return Collections.emptySet(); - } - }; - } - } diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java index efc8c37b8a2..7bf9342ca88 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java @@ -154,7 +154,7 @@ final class ModuleInfo { int minor_version = in.readUnsignedShort(); int major_version = in.readUnsignedShort(); if (major_version < 53) { - // throw invalidModuleDescriptor"Must be >= 53.0"); + throw invalidModuleDescriptor("Must be >= 53.0"); } ConstantPool cpool = new ConstantPool(in); diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java index 1b77bfd8618..4d3d2bf15a0 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.nio.ByteBuffer; +import java.util.Objects; import java.util.Optional; @@ -163,9 +164,12 @@ public interface ModuleReader extends Closeable { * @param bb * The byte buffer to release * - * @implSpec The default implementation does nothing. + * @implSpec The default implementation doesn't do anything except check + * if the byte buffer is null. */ - default void release(ByteBuffer bb) { } + default void release(ByteBuffer bb) { + Objects.requireNonNull(bb); + } /** * Closes the module reader. Once closed then subsequent calls to locate or diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java index 6b0b5d46fe9..eccd0d493f4 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java @@ -220,10 +220,10 @@ class ModuleReferences { Optional implFind(String name) throws IOException { JarEntry je = getEntry(name); if (je != null) { + if (jf.isMultiRelease()) + name = SharedSecrets.javaUtilJarAccess().getRealName(jf, je); String encodedPath = ParseUtil.encodePath(name, false); String uris = "jar:" + uri + "!/" + encodedPath; - if (jf.isMultiRelease()) - uris += "#runtime"; return Optional.of(URI.create(uris)); } else { return Optional.empty(); diff --git a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java index d14ee8d60e4..9dd6694267c 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java +++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java @@ -45,6 +45,7 @@ import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReaderFactory; import jdk.internal.module.ModuleHashes; +import jdk.internal.module.ModuleHashes.HashSupplier; import jdk.internal.module.SystemModules; import jdk.internal.module.ModulePatcher; import jdk.internal.perf.PerfCounter; @@ -84,57 +85,23 @@ class SystemModuleFinder implements ModuleFinder { long t0 = System.nanoTime(); imageReader = ImageReaderFactory.getImageReader(); - String[] moduleNames = SystemModules.MODULE_NAMES; - ModuleDescriptor[] descriptors = null; + String[] names = moduleNames(); + ModuleDescriptor[] descriptors = descriptors(names); - boolean fastLoad = System.getProperty("jdk.installed.modules.disable") == null; - if (fastLoad) { - // fast loading of ModuleDescriptor of installed modules - descriptors = SystemModules.modules(); - } - - int n = moduleNames.length; + int n = names.length; moduleCount.add(n); Set mods = new HashSet<>(n); Map map = new HashMap<>(n); for (int i = 0; i < n; i++) { - String mn = moduleNames[i]; - ModuleDescriptor md; - String hash; - if (fastLoad) { - md = descriptors[i]; - hash = SystemModules.MODULES_TO_HASH[i]; - } else { - // fallback to read module-info.class - // if fast loading of ModuleDescriptors is disabled - ImageLocation location = imageReader.findLocation(mn, "module-info.class"); - md = ModuleDescriptor.read(imageReader.getResourceBuffer(location)); - hash = null; - } - if (!md.name().equals(mn)) - throw new InternalError(); + ModuleDescriptor md = descriptors[i]; // create the ModuleReference - - URI uri = URI.create("jrt:/" + mn); - - Supplier readerSupplier = new Supplier<>() { - @Override - public ModuleReader get() { - return new ImageModuleReader(mn, uri); - } - }; - - ModuleReference mref = - new ModuleReference(md, uri, readerSupplier, hashSupplier(hash)); - - // may need a reference to a patched module if -Xpatch specified - mref = ModulePatcher.interposeIfNeeded(mref); + ModuleReference mref = toModuleReference(md, hashSupplier(i, names[i])); mods.add(mref); - map.put(mn, mref); + map.put(names[i], mref); // counters packageCount.add(md.packages().size()); @@ -147,16 +114,114 @@ class SystemModuleFinder implements ModuleFinder { initTime.addElapsedTimeFrom(t0); } - private static ModuleHashes.HashSupplier hashSupplier(String hash) { - if (hash == null) - return null; + /* + * Returns an array of ModuleDescriptor of the given module names. + * + * This obtains ModuleDescriptors from SystemModules class that is generated + * from the jlink system-modules plugin. ModuleDescriptors have already + * been validated at link time. + * + * If java.base is patched, or fastpath is disabled for troubleshooting + * purpose, it will fall back to find system modules via jrt file system. + */ + private static ModuleDescriptor[] descriptors(String[] names) { + // fastpath is enabled by default. + // It can be disabled for troubleshooting purpose. + boolean disabled = + System.getProperty("jdk.system.module.finder.disabledFastPath") != null; - return new ModuleHashes.HashSupplier() { + // fast loading of ModuleDescriptor of system modules + if (isFastPathSupported() && !disabled) + return SystemModules.modules(); + + // if fast loading of ModuleDescriptors is disabled + // fallback to read module-info.class + ModuleDescriptor[] descriptors = new ModuleDescriptor[names.length]; + for (int i = 0; i < names.length; i++) { + String mn = names[i]; + ImageLocation loc = imageReader.findLocation(mn, "module-info.class"); + descriptors[i] = ModuleDescriptor.read(imageReader.getResourceBuffer(loc)); + + // add the recorded hashes of tied modules + Hashes.add(descriptors[i]); + } + return descriptors; + } + + private static boolean isFastPathSupported() { + return SystemModules.MODULE_NAMES.length > 0; + } + + private static String[] moduleNames() { + if (isFastPathSupported()) + // module names recorded at link time + return SystemModules.MODULE_NAMES; + + // this happens when java.base is patched with java.base + // from an exploded image + return imageReader.getModuleNames(); + } + + private static ModuleReference toModuleReference(ModuleDescriptor md, + HashSupplier hash) + { + String mn = md.name(); + URI uri = URI.create("jrt:/" + mn); + + Supplier readerSupplier = new Supplier<>() { @Override - public String generate(String algorithm) { - return hash; + public ModuleReader get() { + return new ImageModuleReader(mn, uri); } }; + + ModuleReference mref = + new ModuleReference(md, uri, readerSupplier, hash); + + // may need a reference to a patched module if -Xpatch specified + mref = ModulePatcher.interposeIfNeeded(mref); + + return mref; + } + + private static HashSupplier hashSupplier(int index, String name) { + if (isFastPathSupported()) { + return new HashSupplier() { + @Override + public String generate(String algorithm) { + return SystemModules.MODULES_TO_HASH[index]; + } + }; + } else { + return Hashes.hashFor(name); + } + } + + /* + * This helper class is only used when SystemModules is patched. + * It will get the recorded hashes from module-info.class. + */ + private static class Hashes { + static Map hashes = new HashMap<>(); + + static void add(ModuleDescriptor descriptor) { + Optional ohashes = descriptor.hashes(); + if (ohashes.isPresent()) { + hashes.putAll(ohashes.get().hashes()); + } + } + + static HashSupplier hashFor(String name) { + if (!hashes.containsKey(name)) + return null; + + return new HashSupplier() { + @Override + public String generate(String algorithm) { + return hashes.get(name); + } + }; + } } SystemModuleFinder() { } @@ -207,9 +272,9 @@ class SystemModuleFinder implements ModuleFinder { * if not found. */ private ImageLocation findImageLocation(String name) throws IOException { + Objects.requireNonNull(name); if (closed) throw new IOException("ModuleReader is closed"); - if (imageReader != null) { return imageReader.findLocation(module, name); } else { @@ -257,6 +322,7 @@ class SystemModuleFinder implements ModuleFinder { @Override public void release(ByteBuffer bb) { + Objects.requireNonNull(bb); ImageReader.releaseByteBuffer(bb); } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java index 0ca75a874c4..6e220a5e43c 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java @@ -75,11 +75,12 @@ import sun.security.util.SecurityConstants; * *

    A Java virtual machine has at least one non-empty layer, the {@link * #boot() boot} layer, that is created when the Java virtual machine is - * started. The system modules, including {@code java.base}, are in - * the boot layer. The modules in the boot layer are mapped to the bootstrap - * class loader and other class loaders that are built-in into the ava virtual - * machine. The boot layer will often be the {@link #parent() parent} when - * creating additional layers.

    + * started. The boot layer contains module {@code java.base} and is the only + * layer in the Java virtual machine with a module named "{@code java.base}". + * The modules in the boot layer are mapped to the bootstrap class loader and + * other class loaders that are + * built-in into the Java virtual machine. The boot layer will often be + * the {@link #parent() parent} when creating additional layers.

    * *

    As when creating a {@code Configuration}, * {@link ModuleDescriptor#isAutomatic() automatic} modules receive @@ -105,7 +106,7 @@ import sun.security.util.SecurityConstants; * Layer parent = Layer.boot(); * * Configuration cf = parent.configuration() - * .resolveRequires(finder, ModuleFinder.empty(), Set.of("myapp")); + * .resolveRequires(finder, ModuleFinder.of(), Set.of("myapp")); * * ClassLoader scl = ClassLoader.getSystemClassLoader(); * @@ -204,7 +205,8 @@ public final class Layer { * for this layer * @throws LayerInstantiationException * If all modules cannot be defined to the same class loader for any - * of the reasons listed above + * of the reasons listed above or the layer cannot be created because + * the configuration contains a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("createClassLoader")} or * {@code RuntimePermission("getClassLoader")} is denied by @@ -219,14 +221,13 @@ public final class Layer { checkCreateClassLoaderPermission(); checkGetClassLoaderPermission(); - Loader loader; try { - loader = new Loader(cf.modules(), parentLoader); + Loader loader = new Loader(cf.modules(), parentLoader); loader.initRemotePackageMap(cf, this); + return new Layer(cf, this, mn -> loader); } catch (IllegalArgumentException e) { throw new LayerInstantiationException(e.getMessage()); } - return new Layer(cf, this, mn -> loader); } @@ -266,6 +267,9 @@ public final class Layer { * @throws IllegalArgumentException * If the parent of the given configuration is not the configuration * for this layer + * @throws LayerInstantiationException + * If the layer cannot be created because the configuration contains + * a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("createClassLoader")} or * {@code RuntimePermission("getClassLoader")} is denied by @@ -281,7 +285,11 @@ public final class Layer { checkGetClassLoaderPermission(); LoaderPool pool = new LoaderPool(cf, this, parentLoader); - return new Layer(cf, this, pool::loaderFor); + try { + return new Layer(cf, this, pool::loaderFor); + } catch (IllegalArgumentException e) { + throw new LayerInstantiationException(e.getMessage()); + } } @@ -330,7 +338,8 @@ public final class Layer { * for this layer * @throws LayerInstantiationException * If creating the {@code Layer} fails for any of the reasons - * listed above + * listed above or the layer cannot be created because the + * configuration contains a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("getClassLoader")} is denied by * the security manager diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java index 59eb856f8fb..26e47245f38 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java @@ -513,7 +513,7 @@ public final class Module { * package {@code pn} to the given module. * *

    This method has no effect if the package is already exported to the - * given module. If also has no effect if invoked on an unnamed module (as + * given module. It also has no effect if invoked on an unnamed module (as * unnamed modules export all packages).

    * * @param pn @@ -866,7 +866,7 @@ public final class Module { URI uri = mref.location().orElse(null); Module m; - if (loader == null && name.equals("java.base")) { + if (loader == null && name.equals("java.base") && Layer.boot() == null) { m = Object.class.getModule(); } else { m = new Module(layer, loader, descriptor, uri); diff --git a/jdk/src/java.base/share/classes/java/math/BigDecimal.java b/jdk/src/java.base/share/classes/java/math/BigDecimal.java index 557c5cc2e35..162daf9458c 100644 --- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java +++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java @@ -55,7 +55,7 @@ import java.util.Arrays; * object to the operation. In either case, eight rounding * modes are provided for the control of rounding. Using the * integer fields in this class (such as {@link #ROUND_HALF_UP}) to - * represent rounding mode is largely obsolete; the enumeration values + * represent rounding mode is deprecated; the enumeration values * of the {@code RoundingMode} {@code enum}, (such as {@link * RoundingMode#HALF_UP}) should be used instead. * @@ -93,7 +93,7 @@ import java.util.Arrays; *

    In general the rounding modes and precision setting determine * how operations return results with a limited number of digits when * the exact result has more digits (perhaps infinitely many in the - * case of division) than the number of digits returned. + * case of division and square root) than the number of digits returned. * * First, the * total number of digits to return is specified by the @@ -128,6 +128,7 @@ import java.util.Arrays; * Subtractmax(minuend.scale(), subtrahend.scale()) * Multiplymultiplier.scale() + multiplicand.scale() * Dividedividend.scale() - divisor.scale() + * Square rootradicand.scale()/2 * * * These scales are the ones used by the methods which return exact @@ -195,18 +196,19 @@ import java.util.Arrays; * {@code BigDecimal} value; for example [19, 2] is the * {@code BigDecimal} numerically equal to 0.19 having a scale of 2. * - *

    Note: care should be exercised if {@code BigDecimal} objects - * are used as keys in a {@link java.util.SortedMap SortedMap} or - * elements in a {@link java.util.SortedSet SortedSet} since - * {@code BigDecimal}'s natural ordering is inconsistent - * with equals. See {@link Comparable}, {@link - * java.util.SortedMap} or {@link java.util.SortedSet} for more - * information. * *

    All methods and constructors for this class throw * {@code NullPointerException} when passed a {@code null} object * reference for any input parameter. * + * @apiNote Care should be exercised if {@code BigDecimal} objects + * are used as keys in a {@link java.util.SortedMap SortedMap} or + * elements in a {@link java.util.SortedSet SortedSet} since + * {@code BigDecimal}'s natural ordering is inconsistent + * with equals. See {@link Comparable}, {@link + * java.util.SortedMap} or {@link java.util.SortedSet} for more + * information. + * * @see BigInteger * @see MathContext * @see RoundingMode @@ -346,6 +348,16 @@ public class BigDecimal extends Number implements Comparable { public static final BigDecimal TEN = ZERO_THROUGH_TEN[10]; + /** + * The value 0.1, with a scale of 1. + */ + private static final BigDecimal ONE_TENTH = valueOf(1L, 1); + + /** + * The value 0.5, with a scale of 1. + */ + private static final BigDecimal ONE_HALF = valueOf(5L, 1); + // Constructors /** @@ -366,10 +378,10 @@ public class BigDecimal extends Number implements Comparable { * same sequence of characters as the {@link #BigDecimal(String)} * constructor, while allowing a sub-array to be specified. * - *

    Note that if the sequence of characters is already available + * @implNote If the sequence of characters is already available * within a character array, using this constructor is faster than * converting the {@code char} array to string and using the - * {@code BigDecimal(String)} constructor . + * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @param offset first character in the array to inspect. @@ -390,14 +402,14 @@ public class BigDecimal extends Number implements Comparable { * constructor, while allowing a sub-array to be specified and * with rounding according to the context settings. * - *

    Note that if the sequence of characters is already available + * @implNote If the sequence of characters is already available * within a character array, using this constructor is faster than * converting the {@code char} array to string and using the * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @param offset first character in the array to inspect. - * @param len number of characters to consider.. + * @param len number of characters to consider. * @param mc the context to use. * @throws ArithmeticException if the result is inexact but the * rounding mode is {@code UNNECESSARY}. @@ -668,10 +680,10 @@ public class BigDecimal extends Number implements Comparable { * same sequence of characters as the {@link #BigDecimal(String)} * constructor. * - *

    Note that if the sequence of characters is already available + * @implNote If the sequence of characters is already available * as a character array, using this constructor is faster than * converting the {@code char} array to string and using the - * {@code BigDecimal(String)} constructor . + * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @throws NumberFormatException if {@code in} is not a valid @@ -689,10 +701,10 @@ public class BigDecimal extends Number implements Comparable { * constructor and with rounding according to the context * settings. * - *

    Note that if the sequence of characters is already available + * @implNote If the sequence of characters is already available * as a character array, using this constructor is faster than * converting the {@code char} array to string and using the - * {@code BigDecimal(String)} constructor . + * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @param mc the context to use. @@ -794,7 +806,7 @@ public class BigDecimal extends Number implements Comparable { * "-0" [0,0] * * - *

    Note: For values other than {@code float} and + * @apiNote For values other than {@code float} and * {@code double} NaN and ±Infinity, this constructor is * compatible with the values returned by {@link Float#toString} * and {@link Double#toString}. This is generally the preferred @@ -848,13 +860,13 @@ public class BigDecimal extends Number implements Comparable { * This is because 0.1 cannot be represented exactly as a * {@code double} (or, for that matter, as a binary fraction of * any finite length). Thus, the value that is being passed - * in to the constructor is not exactly equal to 0.1, + * in to the constructor is not exactly equal to 0.1, * appearances notwithstanding. * *

  • * The {@code String} constructor, on the other hand, is * perfectly predictable: writing {@code new BigDecimal("0.1")} - * creates a {@code BigDecimal} which is exactly equal to + * creates a {@code BigDecimal} which is exactly equal to * 0.1, as one would expect. Therefore, it is generally * recommended that the {@linkplain #BigDecimal(String) * String constructor} be used in preference to this one. @@ -1188,10 +1200,11 @@ public class BigDecimal extends Number implements Comparable { /** * Translates a {@code long} unscaled value and an - * {@code int} scale into a {@code BigDecimal}. This - * {@literal "static factory method"} is provided in preference to - * a ({@code long}, {@code int}) constructor because it - * allows for reuse of frequently used {@code BigDecimal} values.. + * {@code int} scale into a {@code BigDecimal}. + * + * @apiNote This static factory method is provided in preference + * to a ({@code long}, {@code int}) constructor because it allows + * for reuse of frequently used {@code BigDecimal} values. * * @param unscaledVal unscaled value of the {@code BigDecimal}. * @param scale scale of the {@code BigDecimal}. @@ -1211,10 +1224,11 @@ public class BigDecimal extends Number implements Comparable { /** * Translates a {@code long} value into a {@code BigDecimal} - * with a scale of zero. This {@literal "static factory method"} - * is provided in preference to a ({@code long}) constructor - * because it allows for reuse of frequently used - * {@code BigDecimal} values. + * with a scale of zero. + * + * @apiNote This static factory method is provided in preference + * to a ({@code long}) constructor because it allows for reuse of + * frequently used {@code BigDecimal} values. * * @param val value of the {@code BigDecimal}. * @return a {@code BigDecimal} whose value is {@code val}. @@ -1259,11 +1273,11 @@ public class BigDecimal extends Number implements Comparable { * the {@code double}'s canonical string representation provided * by the {@link Double#toString(double)} method. * - *

    Note: This is generally the preferred way to convert - * a {@code double} (or {@code float}) into a - * {@code BigDecimal}, as the value returned is equal to that - * resulting from constructing a {@code BigDecimal} from the - * result of using {@link Double#toString(double)}. + * @apiNote This is generally the preferred way to convert a + * {@code double} (or {@code float}) into a {@code BigDecimal}, as + * the value returned is equal to that resulting from constructing + * a {@code BigDecimal} from the result of using {@link + * Double#toString(double)}. * * @param val {@code double} to convert to a {@code BigDecimal}. * @return a {@code BigDecimal} whose value is equal to or approximately @@ -1885,7 +1899,7 @@ public class BigDecimal extends Number implements Comparable { * *

    The remainder is given by * {@code this.subtract(this.divideToIntegralValue(divisor).multiply(divisor))}. - * Note that this is not the modulo operation (the result can be + * Note that this is not the modulo operation (the result can be * negative). * * @param divisor value by which this {@code BigDecimal} is to be divided. @@ -1995,6 +2009,296 @@ public class BigDecimal extends Number implements Comparable { return result; } + /** + * Returns an approximation to the square root of {@code this} + * with rounding according to the context settings. + * + *

    The preferred scale of the returned result is equal to + * {@code this.scale()/2}. The value of the returned result is + * always within one ulp of the exact decimal value for the + * precision in question. If the rounding mode is {@link + * RoundingMode#HALF_UP HALF_UP}, {@link RoundingMode#HALF_DOWN + * HALF_DOWN}, or {@link RoundingMode#HALF_EVEN HALF_EVEN}, the + * result is within one half an ulp of the exact decimal value. + * + *

    Special case: + *

      + *
    • The square root of a number numerically equal to {@code + * ZERO} is numerically equal to {@code ZERO} with a preferred + * scale according to the general rule above. In particular, for + * {@code ZERO}}, {@code ZERO.sqrt(mc).equals(ZERO)} is true with + * any {@code MathContext} as an argument. + *
    + * + * @param mc the context to use. + * @return the square root of {@code this}. + * @throws ArithmeticException if {@code this} is less than zero. + * @throws ArithmeticException if an exact result is requested + * ({@code mc.getPrecision()==0}) and there is no finite decimal + * expansion of the exact result + * @throws ArithmeticException if + * {@code (mc.getRoundingMode()==RoundingMode.UNNECESSARY}) and + * the exact result cannot fit in {@code mc.getPrecision()} + * digits. + * @see BigInteger#sqrt() + * @since 9 + */ + public BigDecimal sqrt(MathContext mc) { + int signum = signum(); + if (signum == 1) { + /* + * The following code draws on the algorithm presented in + * "Properly Rounded Variable Precision Square Root," Hull and + * Abrham, ACM Transactions on Mathematical Software, Vol 11, + * No. 3, September 1985, Pages 229-237. + * + * The BigDecimal computational model differs from the one + * presented in the paper in several ways: first BigDecimal + * numbers aren't necessarily normalized, second many more + * rounding modes are supported, including UNNECESSARY, and + * exact results can be requested. + * + * The main steps of the algorithm below are as follows, + * first argument reduce the value to the numerical range + * [1, 10) using the following relations: + * + * x = y * 10 ^ exp + * sqrt(x) = sqrt(y) * 10^(exp / 2) if exp is even + * sqrt(x) = sqrt(y/10) * 10 ^((exp+1)/2) is exp is odd + * + * Then use Newton's iteration on the reduced value to compute + * the numerical digits of the desired result. + * + * Finally, scale back to the desired exponent range and + * perform any adjustment to get the preferred scale in the + * representation. + */ + + // The code below favors relative simplicity over checking + // for special cases that could run faster. + + int preferredScale = this.scale()/2; + BigDecimal zeroWithFinalPreferredScale = valueOf(0L, preferredScale); + + // First phase of numerical normalization, strip trailing + // zeros and check for even powers of 10. + BigDecimal stripped = this.stripTrailingZeros(); + int strippedScale = stripped.scale(); + + // Numerically sqrt(10^2N) = 10^N + if (stripped.isPowerOfTen() && + strippedScale % 2 == 0) { + BigDecimal result = valueOf(1L, strippedScale/2); + if (result.scale() != preferredScale) { + // Adjust to requested precision and preferred + // scale as appropriate. + result = result.add(zeroWithFinalPreferredScale, mc); + } + return result; + } + + // After stripTrailingZeros, the representation is normalized as + // + // unscaledValue * 10^(-scale) + // + // where unscaledValue is an integer with the mimimum + // precision for the cohort of the numerical value. To + // allow binary floating-point hardware to be used to get + // approximately a 15 digit approximation to the square + // root, it is helpful to instead normalize this so that + // the significand portion is to right of the decimal + // point by roughly (scale() - precision() +1). + + // Now the precision / scale adjustment + int scaleAdjust = 0; + int scale = stripped.scale() - stripped.precision() + 1; + if (scale % 2 == 0) { + scaleAdjust = scale; + } else { + scaleAdjust = scale - 1; + } + + BigDecimal working = stripped.scaleByPowerOfTen(scaleAdjust); + + assert // Verify 0.1 <= working < 10 + ONE_TENTH.compareTo(working) <= 0 && working.compareTo(TEN) < 0; + + // Use good ole' Math.sqrt to get the initial guess for + // the Newton iteration, good to at least 15 decimal + // digits. This approach does incur the cost of a + // + // BigDecimal -> double -> BigDecimal + // + // conversion cycle, but it avoids the need for several + // Newton iterations in BigDecimal arithmetic to get the + // working answer to 15 digits of precision. If many fewer + // than 15 digits were needed, it might be faster to do + // the loop entirely in BigDecimal arithmetic. + // + // (A double value might have as much many as 17 decimal + // digits of precision; it depends on the relative density + // of binary and decimal numbers at different regions of + // the number line.) + // + // (It would be possible to check for certain special + // cases to avoid doing any Newton iterations. For + // example, if the BigDecimal -> double conversion was + // known to be exact and the rounding mode had a + // low-enough precision, the post-Newton rounding logic + // could be applied directly.) + + BigDecimal guess = new BigDecimal(Math.sqrt(working.doubleValue())); + int guessPrecision = 15; + int originalPrecision = mc.getPrecision(); + int targetPrecision; + + // If an exact value is requested, it must only need about + // half of the input digits to represent since multiplying + // an N digit number by itself yield a 2N-1 digit or 2N + // digit result. + if (originalPrecision == 0) { + targetPrecision = stripped.precision()/2 + 1; + } else { + targetPrecision = originalPrecision; + } + + // When setting the precision to use inside the Newton + // iteration loop, take care to avoid the case where the + // precision of the input exceeds the requested precision + // and rounding the input value too soon. + BigDecimal approx = guess; + int workingPrecision = working.precision(); + do { + int tmpPrecision = Math.max(Math.max(guessPrecision, targetPrecision + 2), + workingPrecision); + MathContext mcTmp = new MathContext(tmpPrecision, RoundingMode.HALF_EVEN); + // approx = 0.5 * (approx + fraction / approx) + approx = ONE_HALF.multiply(approx.add(working.divide(approx, mcTmp), mcTmp)); + guessPrecision *= 2; + } while (guessPrecision < targetPrecision + 2); + + BigDecimal result; + RoundingMode targetRm = mc.getRoundingMode(); + if (targetRm == RoundingMode.UNNECESSARY || originalPrecision == 0) { + RoundingMode tmpRm = + (targetRm == RoundingMode.UNNECESSARY) ? RoundingMode.DOWN : targetRm; + MathContext mcTmp = new MathContext(targetPrecision, tmpRm); + result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mcTmp); + + // If result*result != this numerically, the square + // root isn't exact + if (this.subtract(result.multiply(result)).compareTo(ZERO) != 0) { + throw new ArithmeticException("Computed square root not exact."); + } + } else { + result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mc); + } + + if (result.scale() != preferredScale) { + // The preferred scale of an add is + // max(addend.scale(), augend.scale()). Therefore, if + // the scale of the result is first minimized using + // stripTrailingZeros(), adding a zero of the + // preferred scale rounding the correct precision will + // perform the proper scale vs precision tradeoffs. + result = result.stripTrailingZeros(). + add(zeroWithFinalPreferredScale, + new MathContext(originalPrecision, RoundingMode.UNNECESSARY)); + } + assert squareRootResultAssertions(result, mc); + return result; + } else { + switch (signum) { + case -1: + throw new ArithmeticException("Attempted square root " + + "of negative BigDecimal"); + case 0: + return valueOf(0L, scale()/2); + + default: + throw new AssertionError("Bad value from signum"); + } + } + } + + private boolean isPowerOfTen() { + return BigInteger.ONE.equals(this.unscaledValue()); + } + + /** + * For nonzero values, check numerical correctness properties of + * the computed result for the chosen rounding mode. + * + * For the directed roundings, for DOWN and FLOOR, result^2 must + * be {@code <=} the input and (result+ulp)^2 must be {@code >} the + * input. Conversely, for UP and CEIL, result^2 must be {@code >=} the + * input and (result-ulp)^2 must be {@code <} the input. + */ + private boolean squareRootResultAssertions(BigDecimal result, MathContext mc) { + if (result.signum() == 0) { + return squareRootZeroResultAssertions(result, mc); + } else { + RoundingMode rm = mc.getRoundingMode(); + BigDecimal ulp = result.ulp(); + BigDecimal neighborUp = result.add(ulp); + // Make neighbor down accurate even for powers of ten + if (this.isPowerOfTen()) { + ulp = ulp.divide(TEN); + } + BigDecimal neighborDown = result.subtract(ulp); + + // Both the starting value and result should be nonzero and positive. + if (result.signum() != 1 || + this.signum() != 1) { + return false; + } + + switch (rm) { + case DOWN: + case FLOOR: + return + result.multiply(result).compareTo(this) <= 0 && + neighborUp.multiply(neighborUp).compareTo(this) > 0; + + case UP: + case CEILING: + return + result.multiply(result).compareTo(this) >= 0 && + neighborDown.multiply(neighborDown).compareTo(this) < 0; + + case HALF_DOWN: + case HALF_EVEN: + case HALF_UP: + BigDecimal err = result.multiply(result).subtract(this).abs(); + BigDecimal errUp = neighborUp.multiply(neighborUp).subtract(this); + BigDecimal errDown = this.subtract(neighborDown.multiply(neighborDown)); + // All error values should be positive so don't need to + // compare absolute values. + + int err_comp_errUp = err.compareTo(errUp); + int err_comp_errDown = err.compareTo(errDown); + + return + errUp.signum() == 1 && + errDown.signum() == 1 && + + err_comp_errUp <= 0 && + err_comp_errDown <= 0 && + + ((err_comp_errUp == 0 ) ? err_comp_errDown < 0 : true) && + ((err_comp_errDown == 0 ) ? err_comp_errUp < 0 : true); + // && could check for digit conditions for ties too + + default: // Definition of UNNECESSARY already verified. + return true; + } + } + } + + private boolean squareRootZeroResultAssertions(BigDecimal result, MathContext mc) { + return this.compareTo(ZERO) == 0; + } + /** * Returns a {@code BigDecimal} whose value is * (thisn), The power is computed exactly, to @@ -2394,8 +2698,8 @@ public class BigDecimal extends Number implements Comparable { * in this case, the specified rounding mode is applied to the * division. * - *

    Note that since BigDecimal objects are immutable, calls of - * this method do not result in the original object being + * @apiNote Since BigDecimal objects are immutable, calls of + * this method do not result in the original object being * modified, contrary to the usual convention of having methods * named setX mutate field {@code X}. * Instead, {@code setScale} returns an object with the proper @@ -2427,8 +2731,8 @@ public class BigDecimal extends Number implements Comparable { * in this case, the specified rounding mode is applied to the * division. * - *

    Note that since BigDecimal objects are immutable, calls of - * this method do not result in the original object being + * @apiNote Since BigDecimal objects are immutable, calls of + * this method do not result in the original object being * modified, contrary to the usual convention of having methods * named setX mutate field {@code X}. * Instead, {@code setScale} returns an object with the proper @@ -2522,8 +2826,8 @@ public class BigDecimal extends Number implements Comparable { * versions of {@code setScale}, but saves the caller the trouble * of specifying a rounding mode in cases where it is irrelevant. * - *

    Note that since {@code BigDecimal} objects are immutable, - * calls of this method do not result in the original + * @apiNote Since {@code BigDecimal} objects are immutable, + * calls of this method do not result in the original * object being modified, contrary to the usual convention of * having methods named setX mutate field * {@code X}. Instead, {@code setScale} returns an @@ -2791,7 +3095,7 @@ public class BigDecimal extends Number implements Comparable { /** * Returns the hash code for this {@code BigDecimal}. Note that * two {@code BigDecimal} objects that are numerically equal but - * differ in scale (like 2.0 and 2.00) will generally not + * differ in scale (like 2.0 and 2.00) will generally not * have the same hash code. * * @return hash code for this {@code BigDecimal}. @@ -3042,7 +3346,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to a {@code BigInteger}. * This conversion is analogous to the * narrowing primitive conversion from {@code double} to - * {@code long} as defined in section 5.1.3 of + * {@code long} as defined in * The Java™ Language Specification: * any fractional part of this * {@code BigDecimal} will be discarded. Note that this @@ -3054,6 +3358,7 @@ public class BigDecimal extends Number implements Comparable { * {@link #toBigIntegerExact()} method. * * @return this {@code BigDecimal} converted to a {@code BigInteger}. + * @jls 5.1.3 Narrowing Primitive Conversion */ public BigInteger toBigInteger() { // force to an integer, quietly @@ -3079,7 +3384,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to a {@code long}. * This conversion is analogous to the * narrowing primitive conversion from {@code double} to - * {@code short} as defined in section 5.1.3 of + * {@code short} as defined in * The Java™ Language Specification: * any fractional part of this * {@code BigDecimal} will be discarded, and if the resulting @@ -3090,6 +3395,7 @@ public class BigDecimal extends Number implements Comparable { * as return a result with the opposite sign. * * @return this {@code BigDecimal} converted to a {@code long}. + * @jls 5.1.3 Narrowing Primitive Conversion */ @Override public long longValue(){ @@ -3148,7 +3454,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to an {@code int}. * This conversion is analogous to the * narrowing primitive conversion from {@code double} to - * {@code short} as defined in section 5.1.3 of + * {@code short} as defined in * The Java™ Language Specification: * any fractional part of this * {@code BigDecimal} will be discarded, and if the resulting @@ -3159,6 +3465,7 @@ public class BigDecimal extends Number implements Comparable { * value as well as return a result with the opposite sign. * * @return this {@code BigDecimal} converted to an {@code int}. + * @jls 5.1.3 Narrowing Primitive Conversion */ @Override public int intValue() { @@ -3231,7 +3538,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to a {@code float}. * This conversion is similar to the * narrowing primitive conversion from {@code double} to - * {@code float} as defined in section 5.1.3 of + * {@code float} as defined in * The Java™ Language Specification: * if this {@code BigDecimal} has too great a * magnitude to represent as a {@code float}, it will be @@ -3242,6 +3549,7 @@ public class BigDecimal extends Number implements Comparable { * value. * * @return this {@code BigDecimal} converted to a {@code float}. + * @jls 5.1.3 Narrowing Primitive Conversion */ @Override public float floatValue(){ @@ -3275,7 +3583,7 @@ public class BigDecimal extends Number implements Comparable { * Converts this {@code BigDecimal} to a {@code double}. * This conversion is similar to the * narrowing primitive conversion from {@code double} to - * {@code float} as defined in section 5.1.3 of + * {@code float} as defined in * The Java™ Language Specification: * if this {@code BigDecimal} has too great a * magnitude represent as a {@code double}, it will be @@ -3286,6 +3594,7 @@ public class BigDecimal extends Number implements Comparable { * value. * * @return this {@code BigDecimal} converted to a {@code double}. + * @jls 5.1.3 Narrowing Primitive Conversion */ @Override public double doubleValue(){ diff --git a/jdk/src/java.base/share/classes/java/math/BigInteger.java b/jdk/src/java.base/share/classes/java/math/BigInteger.java index c89aa09698d..b89939b5c1e 100644 --- a/jdk/src/java.base/share/classes/java/math/BigInteger.java +++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java @@ -116,6 +116,7 @@ import jdk.internal.HotSpotIntrinsicCandidate; * +2{@code Integer.MAX_VALUE} (exclusive). * * @see BigDecimal + * @jls 4.2.2 Integer Operations * @author Josh Bloch * @author Michael McCloskey * @author Alan Eliasen @@ -126,7 +127,7 @@ import jdk.internal.HotSpotIntrinsicCandidate; public class BigInteger extends Number implements Comparable { /** * The signum of this BigInteger: -1 for negative, 0 for zero, or - * 1 for positive. Note that the BigInteger zero must have + * 1 for positive. Note that the BigInteger zero must have * a signum of 0. This is necessary to ensures that there is exactly one * representation for each BigInteger value. */ @@ -710,7 +711,7 @@ public class BigInteger extends Number implements Comparable { * Constructs a randomly generated positive BigInteger that is probably * prime, with the specified bitLength. * - *

    It is recommended that the {@link #probablePrime probablePrime} + * @apiNote It is recommended that the {@link #probablePrime probablePrime} * method be used in preference to this constructor unless there * is a compelling need to specify a certainty. * @@ -1157,9 +1158,11 @@ public class BigInteger extends Number implements Comparable { /** * Returns a BigInteger whose value is equal to that of the - * specified {@code long}. This "static factory method" is - * provided in preference to a ({@code long}) constructor - * because it allows for reuse of frequently used BigIntegers. + * specified {@code long}. + * + * @apiNote This static factory method is provided in preference + * to a ({@code long}) constructor because it allows for reuse of + * frequently used BigIntegers. * * @param val value of the BigInteger to return. * @return a BigInteger with the specified value. @@ -3551,13 +3554,13 @@ public class BigInteger extends Number implements Comparable { /** * Returns the number of bits in the minimal two's-complement - * representation of this BigInteger, excluding a sign bit. + * representation of this BigInteger, excluding a sign bit. * For positive BigIntegers, this is equivalent to the number of bits in * the ordinary binary representation. (Computes * {@code (ceil(log2(this < 0 ? -this : this+1)))}.) * * @return number of bits in the minimal two's-complement - * representation of this BigInteger, excluding a sign bit. + * representation of this BigInteger, excluding a sign bit. */ public int bitLength() { int n = bitLengthPlusOne - 1; @@ -4034,7 +4037,7 @@ public class BigInteger extends Number implements Comparable { * Converts this BigInteger to an {@code int}. This * conversion is analogous to a * narrowing primitive conversion from {@code long} to - * {@code int} as defined in section 5.1.3 of + * {@code int} as defined in * The Java™ Language Specification: * if this BigInteger is too big to fit in an * {@code int}, only the low-order 32 bits are returned. @@ -4044,6 +4047,7 @@ public class BigInteger extends Number implements Comparable { * * @return this BigInteger converted to an {@code int}. * @see #intValueExact() + * @jls 5.1.3 Narrowing Primitive Conversion */ public int intValue() { int result = 0; @@ -4055,7 +4059,7 @@ public class BigInteger extends Number implements Comparable { * Converts this BigInteger to a {@code long}. This * conversion is analogous to a * narrowing primitive conversion from {@code long} to - * {@code int} as defined in section 5.1.3 of + * {@code int} as defined in * The Java™ Language Specification: * if this BigInteger is too big to fit in a * {@code long}, only the low-order 64 bits are returned. @@ -4065,6 +4069,7 @@ public class BigInteger extends Number implements Comparable { * * @return this BigInteger converted to a {@code long}. * @see #longValueExact() + * @jls 5.1.3 Narrowing Primitive Conversion */ public long longValue() { long result = 0; @@ -4078,7 +4083,7 @@ public class BigInteger extends Number implements Comparable { * Converts this BigInteger to a {@code float}. This * conversion is similar to the * narrowing primitive conversion from {@code double} to - * {@code float} as defined in section 5.1.3 of + * {@code float} as defined in * The Java™ Language Specification: * if this BigInteger has too great a magnitude * to represent as a {@code float}, it will be converted to @@ -4088,6 +4093,7 @@ public class BigInteger extends Number implements Comparable { * information about the precision of the BigInteger value. * * @return this BigInteger converted to a {@code float}. + * @jls 5.1.3 Narrowing Primitive Conversion */ public float floatValue() { if (signum == 0) { @@ -4162,7 +4168,7 @@ public class BigInteger extends Number implements Comparable { * Converts this BigInteger to a {@code double}. This * conversion is similar to the * narrowing primitive conversion from {@code double} to - * {@code float} as defined in section 5.1.3 of + * {@code float} as defined in * The Java™ Language Specification: * if this BigInteger has too great a magnitude * to represent as a {@code double}, it will be converted to @@ -4172,6 +4178,7 @@ public class BigInteger extends Number implements Comparable { * information about the precision of the BigInteger value. * * @return this BigInteger converted to a {@code double}. + * @jls 5.1.3 Narrowing Primitive Conversion */ public double doubleValue() { if (signum == 0) { diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java index a295d862ada..4945713e228 100644 --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -87,27 +87,22 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl return isReusePortAvailable; } - private static volatile Set> socketOptions; - /** - * Returns a set of SocketOptions supported by this impl - * and by this impl's socket (Socket or ServerSocket) + * Returns a set of SocketOptions supported by this impl and by this impl's + * socket (Socket or ServerSocket) * * @return a Set of SocketOptions */ @Override protected Set> supportedOptions() { - Set> options = socketOptions; - if (options == null) { - if (isReusePortAvailable()) { - options = new HashSet<>(); - options.addAll(super.supportedOptions()); - options.add(StandardSocketOptions.SO_REUSEPORT); - options = Collections.unmodifiableSet(options); - } else { - options = super.supportedOptions(); - } - socketOptions = options; + Set> options; + if (isReusePortAvailable()) { + options = new HashSet<>(); + options.addAll(super.supportedOptions()); + options.add(StandardSocketOptions.SO_REUSEPORT); + options = Collections.unmodifiableSet(options); + } else { + options = super.supportedOptions(); } return options; } diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java index c9afa2657a2..465ec01cc37 100644 --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java @@ -104,27 +104,22 @@ abstract class AbstractPlainSocketImpl extends SocketImpl return isReusePortAvailable; } - private static volatile Set> socketOptions; - - /** - * Returns a set of SocketOptions supported by this impl - * and by this impl's socket (Socket or ServerSocket) - * - * @return a Set of SocketOptions - */ + /** + * Returns a set of SocketOptions supported by this impl and by this impl's + * socket (Socket or ServerSocket) + * + * @return a Set of SocketOptions + */ @Override protected Set> supportedOptions() { - Set> options = socketOptions; - if (options == null) { - if (isReusePortAvailable()) { - options = new HashSet<>(); - options.addAll(super.supportedOptions()); - options.add(StandardSocketOptions.SO_REUSEPORT); - options = Collections.unmodifiableSet(options); - } else { - options = super.supportedOptions(); - } - socketOptions = options; + Set> options; + if (isReusePortAvailable()) { + options = new HashSet<>(); + options.addAll(super.supportedOptions()); + options.add(StandardSocketOptions.SO_REUSEPORT); + options = Collections.unmodifiableSet(options); + } else { + options = super.supportedOptions(); } return options; } diff --git a/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java b/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java index 6a3dcc76c7d..07f95ac56fb 100644 --- a/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java +++ b/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,7 +23,10 @@ * questions. */ package java.net; + import java.io.IOException; +import static java.net.InetAddress.PREFER_IPV6_VALUE; +import static java.net.InetAddress.PREFER_SYSTEM_VALUE; /* * Package private implementation of InetAddressImpl for dual @@ -35,15 +38,23 @@ import java.io.IOException; * * @since 1.4 */ - class Inet6AddressImpl implements InetAddressImpl { - public native String getLocalHostName() throws UnknownHostException; - public native InetAddress[] - lookupAllHostAddr(String hostname) throws UnknownHostException; - public native String getHostByAddr(byte[] addr) throws UnknownHostException; - private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException; - public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException { + public native String getLocalHostName() throws UnknownHostException; + + public native InetAddress[] lookupAllHostAddr(String hostname) + throws UnknownHostException; + + public native String getHostByAddr(byte[] addr) throws UnknownHostException; + + private native boolean isReachable0(byte[] addr, int scope, int timeout, + byte[] inf, int ttl, int if_scope) + throws IOException; + + public boolean isReachable(InetAddress addr, int timeout, + NetworkInterface netif, int ttl) + throws IOException + { byte[] ifaddr = null; int scope = -1; int netif_scope = -1; @@ -79,7 +90,8 @@ class Inet6AddressImpl implements InetAddressImpl { public synchronized InetAddress anyLocalAddress() { if (anyLocalAddress == null) { - if (InetAddress.preferIPv6Address) { + if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE || + InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) { anyLocalAddress = new Inet6Address(); anyLocalAddress.holder().hostName = "::"; } else { @@ -91,7 +103,8 @@ class Inet6AddressImpl implements InetAddressImpl { public synchronized InetAddress loopbackAddress() { if (loopbackAddress == null) { - if (InetAddress.preferIPv6Address) { + if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE || + InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) { byte[] loopback = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; @@ -103,6 +116,6 @@ class Inet6AddressImpl implements InetAddressImpl { return loopbackAddress; } - private InetAddress anyLocalAddress; - private InetAddress loopbackAddress; + private InetAddress anyLocalAddress; + private InetAddress loopbackAddress; } diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java index e45b590200a..33e70ea1b43 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -26,8 +26,6 @@ package java.net; import java.util.NavigableSet; -import java.util.Iterator; -import java.util.List; import java.util.ArrayList; import java.util.Objects; import java.util.Scanner; @@ -41,6 +39,7 @@ import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; import java.io.ObjectOutputStream.PutField; +import java.lang.annotation.Native; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentSkipListSet; @@ -193,6 +192,11 @@ import sun.net.util.IPAddressUtil; */ public class InetAddress implements java.io.Serializable { + + @Native static final int PREFER_IPV4_VALUE = 0; + @Native static final int PREFER_IPV6_VALUE = 1; + @Native static final int PREFER_SYSTEM_VALUE = 2; + /** * Specify the address family: Internet Protocol, Version 4 * @since 1.4 @@ -206,8 +210,7 @@ class InetAddress implements java.io.Serializable { static final int IPv6 = 2; /* Specify address family preference */ - static transient boolean preferIPv6Address = false; - + static transient final int preferIPv6Address; static class InetAddressHolder { /** @@ -293,8 +296,19 @@ class InetAddress implements java.io.Serializable { * Load net library into runtime, and perform initializations. */ static { - preferIPv6Address = java.security.AccessController.doPrivileged( - new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue(); + String str = java.security.AccessController.doPrivileged( + new GetPropertyAction("java.net.preferIPv6Addresses")); + if (str == null) { + preferIPv6Address = PREFER_IPV4_VALUE; + } else if (str.equalsIgnoreCase("true")) { + preferIPv6Address = PREFER_IPV6_VALUE; + } else if (str.equalsIgnoreCase("false")) { + preferIPv6Address = PREFER_IPV4_VALUE; + } else if (str.equalsIgnoreCase("system")) { + preferIPv6Address = PREFER_SYSTEM_VALUE; + } else { + preferIPv6Address = PREFER_IPV4_VALUE; + } AccessController.doPrivileged( new java.security.PrivilegedAction<>() { public Void run() { diff --git a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java index 365092b1e07..9c9e4b8f53a 100644 --- a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java +++ b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java @@ -26,7 +26,9 @@ package java.net; import java.io.IOException; +import java.util.Collections; import java.util.Enumeration; +import java.util.Set; /** * The multicast datagram socket class is useful for sending @@ -716,4 +718,24 @@ class MulticastSocket extends DatagramSocket { } // synch p } //synch ttl } //method + + private static Set> options; + private static boolean optionsSet = false; + + @Override + public Set> supportedOptions() { + synchronized (MulticastSocket.class) { + if (optionsSet) { + return options; + } + try { + DatagramSocketImpl impl = getImpl(); + options = Collections.unmodifiableSet(impl.supportedOptions()); + } catch (SocketException ex) { + options = Collections.emptySet(); + } + optionsSet = true; + return options; + } + } } diff --git a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html index d8e8949fc32..76c82b5b81e 100644 --- a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -1,5 +1,5 @@ - - - - - - - - -

    Button2DragTest
    Bug ID: 4955110

    - -

    This is an AUTOMATIC test, simply wait for completion

    - - - - diff --git a/jdk/test/java/awt/dnd/Button2DragTest/Button2DragTest.java b/jdk/test/java/awt/dnd/Button2DragTest/Button2DragTest.java index 33bb5058706..c5045ed7fa7 100644 --- a/jdk/test/java/awt/dnd/Button2DragTest/Button2DragTest.java +++ b/jdk/test/java/awt/dnd/Button2DragTest/Button2DragTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, 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 @@ -21,45 +21,52 @@ * questions. */ -/* - test - @bug 4955110 - @summary tests that a drag ends on button2 release - @author Alexander.Gerasimov area=dnd - @library ../../regtesthelpers - @build Util - @run applet/othervm Button2DragTest.html -*/ +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.StringSelection; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetAdapter; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.event.InputEvent; - -/** - * Button2DragTest.java - * - * summary: tests that DragSourceDragEvent.getDropAction() accords to its new spec - * (does not depend on the user drop action) - * - */ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; -import java.awt.datatransfer.*; -import java.awt.dnd.*; import test.java.awt.regtesthelpers.Util; - -public class Button2DragTest extends Applet { +/** + * @test + * @bug 4955110 + * @summary tests that DragSourceDragEvent.getDropAction() accords to its new + * spec (does not depend on the user drop action) + * @library ../../regtesthelpers + * @build Util + * @run main/othervm Button2DragTest + * @author Alexander.Gerasimov area=dnd + */ +public final class Button2DragTest { private volatile boolean dropSuccess; - private Frame frame; + private static Frame frame; + public static void main(final String[] args) { + Button2DragTest test = new Button2DragTest(); + try { + test.run(); + } finally { + if (frame != null) { + frame.dispose(); + } + } + } - public void init() { - // Set up the environment -- set the layout manager, add - // buttons, etc. - setLayout(new BorderLayout()); - + public void run() { frame = new Frame(); final DragSourceListener dragSourceListener = new DragSourceAdapter() { @@ -84,20 +91,13 @@ public class Button2DragTest extends Applet { } }; new DropTarget(frame, dropTargetListener); - } - - - public void start() { - //Get things going. Request focus, set size, et cetera - setSize(200,200); - setVisible(true); - validate(); //What would normally go into main() will probably go here. //Use System.out.println for diagnostic messages that you want //to read after the test is done. - + frame.setUndecorated(true); frame.setBounds(100, 100, 200, 200); + frame.setLocationRelativeTo(null); frame.setVisible(true); Robot robot = Util.createRobot(); diff --git a/jdk/test/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java b/jdk/test/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java index 92dcc214376..11cd886d598 100644 --- a/jdk/test/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java +++ b/jdk/test/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,13 +44,9 @@ public class AltGraphModifierTest { = { "This test is for verifying Alt-Gr modifier of an event.", "Windows :-", - "1. Please check if Alt-Gr key is present on keyboard.", - "2. If present, press the Alt-Gr key and perform", - " mouse click on the TestWindow.", - "3. If Alt-Gr key is not present, press Ctrl+Alt keys &", - " perform mouse click on the TestWindow.", - "4. Test will exit by itself with appropriate result.", - "", + "1. Click Pass.", + "2. Alt-Gr modifier is tested under Robot tests.", + " ", "Linux :-", "1. Please check if Alt-Gr key is present on keyboard.", "2. If present, press the Alt-Gr key and perform", @@ -63,10 +59,11 @@ public class AltGraphModifierTest { "6. Press Right Alt Key & perform mouse click on the", " TestWindow", "7. Test will exit by itself with appropriate result.", - "", + " ", "Mac :-", - " Mac fix is under progress, & will be fixed soon.", - " Please click Fail" + "1. Press Right Option key on the keyboard and mouse click", + " on the TestWindow", + "3. Test will exit by itself with appropriate result.", }; Sysout.createDialog(); @@ -77,7 +74,7 @@ public class AltGraphModifierTest { public static void initTestWindow() { mainFrame = new Frame(); mainFrame.setTitle("TestWindow"); - mainFrame.setSize(300, 200); + mainFrame.setBounds(700, 10, 300, 300); mainFrame.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { diff --git a/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.html b/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.html deleted file mode 100644 index 9973c033612..00000000000 --- a/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - -RestoreActiveWindowTest - - - -

    RestoreActiveWindowTest
    Bug ID: 6365992

    - -

    See the dialog box (usually in upper left corner) for instructions

    - - - - diff --git a/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.java b/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.java index 66e4148931c..8d29dbb5849 100644 --- a/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.java +++ b/jdk/test/java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 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 @@ -22,210 +22,194 @@ */ /* - test - @bug 6365992 6379599 - @summary REG: Showing and disposing a native print dialog makes the main frame inactive, Win32 - @author Dmitry.Cherepanov@SUN.COM area=awt.printdialog - @run applet/manual=yesno RestoreActiveWindowTest.html -*/ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; -import java.awt.print.*; -import javax.print.attribute.*; - -public class RestoreActiveWindowTest extends Applet -{ - Button showBtn1 = new Button("show a native print dialog"); - Button showBtn2 = new Button("show a native page dialog"); - - public void init() - { - showBtn1.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent ae) { - PrinterJob.getPrinterJob().printDialog(); - } - }); - showBtn2.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent ae){ - PrinterJob.getPrinterJob().pageDialog(new PageFormat()); - } - }); - - add(showBtn1); - add(showBtn2); - - String[] instructions = { - "1.1) Click on 'show a native print dialog'. A native print dialog will come up.", - "1.2) Click on the 'close'(X) button. The dialog will be closed.", - "1.3) After the dialog closing another window should become the active window.", - "1.4) If there no any active window then the test failed.", - "2.1) Click on 'show a native page dialog'. A native page dialog will come up.", - "2.2) Click on the 'close'(X) button. The dialog will be closed.", - "2.3) After the dialog closing another window should become the active window.", - "2.4) If there no any active window then the test failed.", - "3) Test Passed." - }; - - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - public void start () - { - //Get things going. Request focus, set size, et cetera - setSize (200,200); - show(); - - }// start() - - //The rest of this class is the actions which perform the test... - - //Use Sysout.println to communicate with the user NOT System.out!! - //Sysout.println ("Something Happened!"); - -}// class ManualYesNoTest - -/* Place other classes related to the test after this line */ - - - - - -/**************************************************** - 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. + * @test + * @bug 6365992 6379599 8137137 + * @summary REG: Showing and disposing a native print dialog makes the main + * frame inactive, Win32 + * @run main/manual RestoreActiveWindowTest */ +import java.awt.Frame; +import java.awt.Button; +import java.awt.GridBagLayout; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.GridLayout; +import java.awt.GridBagConstraints; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.print.PrinterJob; +import java.awt.print.PageFormat; -class Sysout -{ - private static TestDialog dialog; +public class RestoreActiveWindowTest implements ActionListener { - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); + private static Frame mainFrame; + private static Button printDialogButton; + private static Button pageDialogButton; + private static Frame instructionFrame; + private static GridBagLayout layout; + private static Panel mainControlPanel; + private static Panel resultButtonPanel; + private static TextArea instructionTextArea; + private static Button passButton; + private static Button failButton; + private static Thread mainThread = null; + private static boolean testPassed = false; + private static boolean isInterrupted = false; + private static final int testTimeOut = 300000; + private static String testFailMessage; + + public void createAndShowGUI() { + mainFrame = new Frame("Test"); + mainFrame.setSize(200, 200); + mainFrame.setLocationRelativeTo(null); + mainFrame.setLayout(new GridLayout(2, 1)); + + printDialogButton = new Button("show a native print dialog"); + pageDialogButton = new Button("show a native page dialog"); + printDialogButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + PrinterJob.getPrinterJob().printDialog(); + setButtonEnable(true); + testFailMessage = "Print dialog test failed."; + } + }); + pageDialogButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + PrinterJob.getPrinterJob().pageDialog(new PageFormat()); + setButtonEnable(true); + testFailMessage = "Page dialog test failed."; + } + }); + + mainFrame.add(printDialogButton); + mainFrame.add(pageDialogButton); + mainFrame.setVisible(true); + + mainFrame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent we) { + cleanUp(); + throw new RuntimeException("User has closed the test window " + + "without clicking Pass or Fail."); + } + }); } - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); + private void createInstructionUI() { + instructionFrame = new Frame("Native Print Dialog and Page Dialog"); + layout = new GridBagLayout(); + mainControlPanel = new Panel(layout); + resultButtonPanel = new Panel(layout); + + GridBagConstraints gbc = new GridBagConstraints(); + String instructions + = "\nINSTRUCTIONS:\n" + + "\n 1. Click on the 'show a native print dialog' button. A " + + "native print dialog will come up." + + "\n 2. Click on the 'Cancel' button on Mac OS X or " + + "'close'(X) on other paltforms. Dialog will be closed." + + "\n 3. After the dialog is closed another window should " + + "become the active window." + + "\n 4. If there no any active window then the test has " + + "failed. Click on 'Fail' Button." + + "\n 5. Click on the 'show a native page dialog' button. A " + + "native page dialog will come up." + + "\n 6. Click on the 'Cancel' button on Mac OS X or " + + "'close'(X) on other paltforms. Dialog will be closed." + + "\n 7. After the dialog is closed another window should " + + "become the active window." + + "\n 8. If there no any active window then the test has " + + "failed. Click on 'Fail' Button." + + "\n 9. Test Passed. Click on 'Pass' Button."; + + instructionTextArea = new TextArea(13, 80); + instructionTextArea.setText(instructions); + instructionTextArea.setEnabled(false); + instructionTextArea.setBackground(Color.white); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weightx = 0.5; + gbc.fill = GridBagConstraints.HORIZONTAL; + mainControlPanel.add(instructionTextArea, gbc); + + passButton = new Button("Pass"); + passButton.setName("Pass"); + passButton.addActionListener((ActionListener) this); + + failButton = new Button("Fail"); + failButton.setName("Fail"); + failButton.addActionListener((ActionListener) this); + + setButtonEnable(false); + + gbc.gridx = 0; + gbc.gridy = 0; + resultButtonPanel.add(passButton, gbc); + gbc.gridx = 1; + gbc.gridy = 0; + resultButtonPanel.add(failButton, gbc); + gbc.gridx = 0; + gbc.gridy = 1; + mainControlPanel.add(resultButtonPanel, gbc); + + instructionFrame.add(mainControlPanel); + instructionFrame.pack(); + instructionFrame.setVisible(true); } - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); + @Override + public void actionPerformed(ActionEvent ae) { + if (ae.getSource() instanceof Button) { + Button btn = (Button) ae.getSource(); + switch (btn.getName()) { + case "Pass": + testPassed = true; + isInterrupted = true; + mainThread.interrupt(); + break; + case "Fail": + testPassed = false; + isInterrupted = true; + mainThread.interrupt(); + break; + } + } } - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); + private static void setButtonEnable(boolean status) { + passButton.setEnabled(status); + failButton.setEnabled(status); } -}// 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 -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //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); - - pack(); - - setVisible(true); - }// 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" ); - System.out.println(messageIn); + private static void cleanUp() { + mainFrame.dispose(); + instructionFrame.dispose(); } -}// TestDialog class + public static void main(String args[]) { + RestoreActiveWindowTest printDialogs = new RestoreActiveWindowTest(); + printDialogs.createInstructionUI(); + printDialogs.createAndShowGUI(); + + mainThread = Thread.currentThread(); + try { + mainThread.sleep(testTimeOut); + } catch (InterruptedException ex) { + if (!testPassed) { + throw new RuntimeException(testFailMessage); + } + } finally { + cleanUp(); + } + + if (!isInterrupted) { + throw new RuntimeException("Test Timed out after " + + testTimeOut / 1000 + " seconds"); + } + } +} diff --git a/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java b/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java index a8ec7d49188..b5fc3667b94 100644 --- a/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java +++ b/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java @@ -33,7 +33,7 @@ import java.util.Arrays; /** * @test - * @bug 8132973 8132732 8155013 + * @bug 8132973 8132732 8155013 8154958 * @summary Some check for BeanProperty annotation * @author a.stepanov * @run main AnonymousClassBeanPropertyTest @@ -62,6 +62,10 @@ public class AnonymousClassBeanPropertyTest { // ---------- test cases (interfaces) ---------- + public interface IPublic { + double getX(); + } + private interface IGet { double getX(); } @@ -113,6 +117,10 @@ public class AnonymousClassBeanPropertyTest { void setX(double a[]); } + private interface IIs { + boolean isX(); + } + // ---------- checks ---------- @@ -124,7 +132,7 @@ public class AnonymousClassBeanPropertyTest { return ok; } - private static boolean checkInfo(Class c, String what) { + private static boolean checkInfo(Class c, String what, boolean checkVals) { BeanInfo i; try { i = Introspector.getBeanInfo(c, Object.class); } @@ -154,6 +162,8 @@ public class AnonymousClassBeanPropertyTest { ok &= check("visualUpdate", (boolean) d.getValue("visualUpdate"), UPDATE); + if (!checkVals) { return ok; } + Object vals[] = (Object[]) d.getValue("enumerationValues"); if (vals == null) { System.out.println("null enumerationValues"); @@ -210,8 +220,10 @@ public class AnonymousClassBeanPropertyTest { (boolean) d.getValue("visualUpdate"), !UPDATE); Object vals[] = (Object[]) d.getValue("enumerationValues"); - if (vals != null || vals.length > 0) { - System.out.println("non-empty enumerationValues"); + if (vals != null && vals.length > 0) { + System.out.println("non-empty enumerationValues:"); + for (Object v: vals) { System.out.print(v.toString()); } + System.out.println(); return false; } @@ -228,6 +240,31 @@ public class AnonymousClassBeanPropertyTest { //---------------------------------------------------------------------- + // TODO: please uncomment/update after 8154958 fix + /* + IPublic testPublic = new IPublic() { + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX() { return X; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testPublic.getClass(), "IPublic", true); + System.out.println("OK = " + ok); + passed = passed && ok; + */ + + //---------------------------------------------------------------------- + IGet testGet = new IGet() { @BeanProperty( description = DESCRIPTION, @@ -244,7 +281,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGet.getClass(), "IGet"); + ok = checkInfo(testGet.getClass(), "IGet", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -269,7 +306,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testSet.getClass(), "ISet"); + ok = checkInfo(testSet.getClass(), "ISet", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -294,7 +331,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetByIndex.getClass(), "IGetByIndex"); + ok = checkInfo(testGetByIndex.getClass(), "IGetByIndex", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -319,7 +356,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testSetByIndex.getClass(), "ISetByIndex"); + ok = checkInfo(testSetByIndex.getClass(), "ISetByIndex", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -346,7 +383,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetArray.getClass(), "IGetArray"); + ok = checkInfo(testGetArray.getClass(), "IGetArray", true); System.out.println("OK = " + ok); passed = passed && ok; */ @@ -374,7 +411,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testSetArray.getClass(), "ISetArray"); + ok = checkInfo(testSetArray.getClass(), "ISetArray", true); System.out.println("OK = " + ok); passed = passed && ok; */ @@ -402,7 +439,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetBoth_1.getClass(), "IGetBoth-1"); + ok = checkInfo(testGetBoth_1.getClass(), "IGetBoth-1", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -429,7 +466,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetBoth_2.getClass(), "IGetBoth-2"); + ok = checkInfo(testGetBoth_2.getClass(), "IGetBoth-2", true); System.out.println("OK = " + ok); passed = passed && ok; */ @@ -465,11 +502,11 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetBoth_3.getClass(), "IGetBoth-3"); + ok = checkInfo(testGetBoth_3.getClass(), "IGetBoth-3", true); System.out.println("OK = " + ok); ok2 = checkAlternativeInfo(testGetBoth_3.getClass(), "IGetBoth-3"); System.out.println("OK = " + ok2); - passed = passed && ok && ok2; + passed = passed && (ok || ok2); */ //---------------------------------------------------------------------- @@ -495,7 +532,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testSetBoth_1.getClass(), "ISetBoth-1"); + ok = checkInfo(testSetBoth_1.getClass(), "ISetBoth-1", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -522,7 +559,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testSetBoth_2.getClass(), "ISetBoth-2"); + ok = checkInfo(testSetBoth_2.getClass(), "ISetBoth-2", true); System.out.println("OK = " + ok); passed = passed && ok; */ @@ -558,11 +595,11 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testSetBoth_3.getClass(), "ISetBoth-3"); + ok = checkInfo(testSetBoth_3.getClass(), "ISetBoth-3", true); System.out.println("OK = " + ok); ok2 = checkAlternativeInfo(testSetBoth_3.getClass(), "ISetBoth-3"); System.out.println("OK = " + ok2); - passed = passed && ok && ok2; + passed = passed && (ok || ok2); */ //---------------------------------------------------------------------- @@ -588,7 +625,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSet_1.getClass(), "IGetSet-1"); + ok = checkInfo(testGetSet_1.getClass(), "IGetSet-1", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -614,7 +651,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSet_2.getClass(), "IGetSet-2"); + ok = checkInfo(testGetSet_2.getClass(), "IGetSet-2", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -649,11 +686,11 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSet_3.getClass(), "IGetSet-3"); + ok = checkInfo(testGetSet_3.getClass(), "IGetSet-3", true); System.out.println("OK = " + ok); ok2 = checkAlternativeInfo(testGetSet_3.getClass(), "IGetSet-3"); System.out.println("OK = " + ok2); - passed = passed && ok && ok2; + passed = passed && (ok || ok2); */ //---------------------------------------------------------------------- @@ -679,7 +716,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSetByIndex_1.getClass(), "IGetSetByIndex-1"); + ok = checkInfo(testGetSetByIndex_1.getClass(), "IGetSetByIndex-1", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -705,7 +742,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSetByIndex_2.getClass(), "IGetSetByIndex-2"); + ok = checkInfo(testGetSetByIndex_2.getClass(), "IGetSetByIndex-2", true); System.out.println("OK = " + ok); passed = passed && ok; @@ -744,12 +781,12 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSetByIndex_3.getClass(), "IGetSetByIndex-3"); + ok = checkInfo(testGetSetByIndex_3.getClass(), "IGetSetByIndex-3", true); System.out.println("OK = " + ok); ok2 = checkAlternativeInfo( testGetSetByIndex_3.getClass(), "IGetSetByIndex-3"); System.out.println("OK = " + ok2); - passed = passed && ok && ok2; + passed = passed && (ok || ok2); */ //---------------------------------------------------------------------- @@ -781,7 +818,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSetBoth_1.getClass(), "IGetSetBoth-1"); + ok = checkInfo(testGetSetBoth_1.getClass(), "IGetSetBoth-1", true); System.out.println("OK = " + ok); passed = passed && ok; */ @@ -813,7 +850,7 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSetBoth_2.getClass(), "IGetSetBoth-2"); + ok = checkInfo(testGetSetBoth_2.getClass(), "IGetSetBoth-2", true); System.out.println("OK = " + ok); passed = passed && ok; */ @@ -853,14 +890,135 @@ public class AnonymousClassBeanPropertyTest { public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} }; - ok = checkInfo(testGetSetBoth_3.getClass(), "IGetSetBoth-3"); + ok = checkInfo(testGetSetBoth_3.getClass(), "IGetSetBoth-3", true); System.out.println("OK = " + ok); ok2 = checkAlternativeInfo( testGetSetBoth_3.getClass(), "IGetSetBoth-3"); System.out.println("OK = " + ok2); - passed = passed && ok && ok2; + passed = passed && (ok || ok2); */ + //---------------------------------------------------------------------- + + IIs testIs_1 = new IIs() { + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + @Override + public boolean isX() { return false; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testIs_1.getClass(), "IIs-1", false); + System.out.println("OK = " + ok); + passed = passed && ok; + + + IIs testIs_2 = new IIs() { + + private boolean b; + + @Override + public boolean isX() { return b; } + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public void setX(boolean v) { b = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testIs_2.getClass(), "IIs-2", false); + System.out.println("OK = " + ok); + passed = passed && ok; + + + IIs testIs_3 = new IIs() { + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + @Override + public boolean isX() { return false; } + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public boolean getX() { return false; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testIs_3.getClass(), "IIs-3", false); + System.out.println("OK = " + ok); + ok2 = checkAlternativeInfo(testIs_3.getClass(), "IIs-3"); + System.out.println("OK = " + ok2); + passed = passed && (ok || ok2); + + // TODO: please uncomment/update after 8132973 fix + /* + IIs testIs_4 = new IIs() { + + private boolean b; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + @Override + public boolean isX() { return b; } + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public void setX(boolean v) { b = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testIs_4.getClass(), "IIs-4", false); + System.out.println("OK = " + ok); + ok2 = checkAlternativeInfo(testIs_4.getClass(), "IIs-4"); + System.out.println("OK = " + ok2); + passed = passed && (ok || ok2); + */ + + + //---------------------------------------------------------------------- + + if (!passed) { throw new RuntimeException("test failed"); } System.out.println("\ntest passed"); } diff --git a/jdk/test/java/beans/Introspector/BeanPropertyTest.java b/jdk/test/java/beans/Introspector/BeanPropertyTest.java index 6f957074c6e..5e84aaaed4e 100644 --- a/jdk/test/java/beans/Introspector/BeanPropertyTest.java +++ b/jdk/test/java/beans/Introspector/BeanPropertyTest.java @@ -33,7 +33,7 @@ import java.util.Arrays; /** * @test - * @bug 8132703 8132163 8132732 8132973 8154756 8132888 + * @bug 8132703 8132163 8132732 8132973 8154756 8132888 8155103 * @summary Some check for BeanProperty annotation * @author a.stepanov * @run main BeanPropertyTest @@ -853,6 +853,64 @@ public class BeanPropertyTest { public void removePropertyChangeListener(PropertyChangeListener l) {} } + // JDK-8155103 + public static enum E { + + ONE, + TWO { + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int v) {} + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int v) {} + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + + } + + private static enum EB { + + TRUE(true), FALSE(false); + + private boolean b; + private EB(boolean v) { b = v; } + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public boolean isTrue() { return true; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + + } + // ---------- checks ---------- @@ -953,7 +1011,7 @@ public class BeanPropertyTest { } private static boolean ignoreVals(Class c) { - return (c.equals(Self.class) || c.equals(SelfArr.class)); + return (c.equals(Self.class) || c.equals(SelfArr.class)) || c.equals(EB.class); } @@ -1003,6 +1061,29 @@ public class BeanPropertyTest { passed = passed && ok; } + // enums + + Class enumCases[] = { + + // TODO: uncomment/update after 8155103 fix + //E.class, E.TWO.getClass(), EB.class + }; + + int ne = 1; + for (Class c: enumCases) { + + System.out.println("\nEnum-" + ne + ":"); + ne++; + + BeanInfo i; + try { i = Introspector.getBeanInfo(c, Object.class); } + catch (IntrospectionException e) { throw new RuntimeException(e); } + boolean ok = checkInfo(i, !ignoreVals(c)); + System.out.println(ok ? "OK" : "NOK"); + passed = passed && ok; + } + + if (!passed) { throw new RuntimeException("test failed"); } System.out.println("\ntest passed"); } diff --git a/jdk/test/java/beans/Introspector/InheritanceBeanPropertyTest.java b/jdk/test/java/beans/Introspector/InheritanceBeanPropertyTest.java new file mode 100644 index 00000000000..e42fa6228f3 --- /dev/null +++ b/jdk/test/java/beans/Introspector/InheritanceBeanPropertyTest.java @@ -0,0 +1,1281 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.beans.BeanInfo; +import java.beans.BeanProperty; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; + +import java.util.Arrays; + + +/** + * @test + * @bug 8132565 8155013 + * @summary Some inheritance check for BeanProperty annotation + * @author a.stepanov + * @run main InheritanceBeanPropertyTest + */ + + +public class InheritanceBeanPropertyTest { + + private final static String DESCRIPTION = "TEST"; + private final static boolean BOUND = true; + private final static boolean EXPERT = false; + private final static boolean HIDDEN = true; + private final static boolean PREFERRED = false; + private final static boolean REQUIRED = true; + private final static boolean UPDATE = false; + + private final static double X = java.lang.Math.PI; + + private final static String + V_NAME = "java.lang.Math.PI", + V_SHORT = "PI", + V = Double.toString(X); + + private final static String DESCRIPTION_2 = "XYZ"; + + + // ---------- test cases ---------- + + public static class BaseGet { + + private final static String TESTCASE = "base getter"; + + public double getX() { return X; } + } + + public static class OverloadGet extends BaseGet { + + private final static String TESTCASE = "overload getter"; + + private final double x[] = {X, X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public double getX(int i) { return x[i]; } // indexed + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static class BaseSet { + + private final static String TESTCASE = "base setter"; + + double u; + public void setX(double v) { u = v; } + } + + public static class OverloadSet extends BaseSet { + + private final static String TESTCASE = "overload setter"; + + private final double x[] = {X, X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int i, double v) { x[i] = v; } // indexed + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static class BaseIGet { + + protected final double x[] = {X, X, X}; + public double[] getX() { return x; } + } + + public static class OverloadIGet extends BaseIGet { + + private final static String TESTCASE = "overload indexed getter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public double getX(int i) { return x[i]; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static class BaseISet { + + protected double x[] = {X, X, X}; + public void setX(double a[]) { x = Arrays.copyOf(a, a.length); } + } + + public static class OverloadISet extends BaseISet { + + private final static String TESTCASE = "overload indexed setter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int i, double v) { x[i] = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static class BoolGet { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public boolean getX() { return false; } + } + + public static class BoolGetIs extends BoolGet { + + private final static String TESTCASE = "base boolean getter + is"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public boolean isX() { return false; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + // ---------- + + public static class BoolIs { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public boolean isX() { return false; } + } + + public static class BoolIsGet extends BoolIs { + + private final static String TESTCASE = "base is + boolean getter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public boolean getX() { return false; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static class AnnotatedGet { + + private final static String TESTCASE = "annotated super getter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public double getX() { return 0.; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class OverrideAnnotatedGet extends AnnotatedGet { + + private final static String TESTCASE = "override annotated getter"; + + @Override + public double getX() { return X; } + } + + // ---------- + + public static class AnnotatedIs { + + private final static String TESTCASE = "annotated super is"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public boolean isX() { return false; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class OverrideAnnotatedIs extends AnnotatedIs { + + private final static String TESTCASE = "override annotated is"; + + @Override + public boolean isX() { return false; } + } + + // ---------- + + public static class AnnotatedSet { + + private final static String TESTCASE = "annotated super set"; + + protected double x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(double v) { x = -v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class OverrideAnnotatedSet extends AnnotatedSet { + + private final static String TESTCASE = "override annotated setter"; + + @Override + public void setX(double v) { x = v; } + } + + // ---------- + + public static class AnnotatedGet2 { + + protected double x; + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public double getX() { return 0.; } + } + + public static class OverrideAnnotatedGet2 extends AnnotatedGet2 { + + private final static String TESTCASE = "override annotated getter - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX() { return X; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class AnnotatedGet2Ext extends AnnotatedGet2 { + + private final static String TESTCASE = "extend annotated getter - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(double v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static class AnnotatedIs2 { + + protected boolean b = false; + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public boolean isX() { return false; } + } + + public static class OverrideAnnotatedIs2 extends AnnotatedIs2 { + + private final static String TESTCASE = "override annotated is - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + @Override + public boolean isX() { return b; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class AnnotatedIs2Ext extends AnnotatedIs2 { + + private final static String TESTCASE = "extend annotated is - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public void setX(boolean v) { b = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static class AnnotatedSet2 { + + protected double x; + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public void setX(double v) { x = -v; } + } + + public static class OverrideAnnotatedSet2 extends AnnotatedSet2 { + + private final static String TESTCASE = "override annotated setter - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(double v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class AnnotatedSet2Ext extends AnnotatedSet2 { + + private final static String TESTCASE = "extend annotated setter - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public double getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public abstract static class AbstractGet { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public abstract double getX(); + } + + public static class OverrideAbstractGet extends AbstractGet { + + private final static String TESTCASE = + "override abstract annotated getter"; + + @Override + public double getX() { return X; } + } + + public static class OverrideAbstractGet2 extends AbstractGet { + + private final static String TESTCASE = + "override abstract annotated getter - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX() { return X; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public abstract static class AbstractGetExt extends AbstractGet { + + private final static String TESTCASE = + "extend abstract annotated getter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public abstract void setX(double v); + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public abstract static class AbstractIs { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public abstract boolean isX(); + } + + public static class OverrideAbstractIs extends AbstractIs { + + private final static String TESTCASE = + "override abstract annotated is"; + + @Override + public boolean isX() { return true; } + } + + public static class OverrideAbstractIs2 extends AbstractIs { + + private final static String TESTCASE = + "override abstract annotated is - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + @Override + public boolean isX() { return true; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + + public abstract static class AbstractIsExt extends AbstractIs { + + private final static String TESTCASE = + "extend abstract annotated is"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public abstract boolean getX(); + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public abstract static class AbstractSet { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public abstract void setX(double v); + } + + public static class OverrideAbstractSet extends AbstractSet { + + private final static String TESTCASE = + "override abstract annotated setter"; + + private double x; + + @Override + public void setX(double v) { x = v; } + } + + public static class OverrideAbstractSet2 extends AbstractSet { + + private final static String TESTCASE = + "override abstract annotated setter - 2"; + + private double x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(double v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public abstract static class AbstractSetExt extends AbstractSet { + + private final static String TESTCASE = + "extend abstract annotated setter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public abstract void setX(double v[]); + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static abstract class AbstractGet2 { + + private final static String TESTCASE = "abstract super getter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public abstract double getX(); + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static abstract class AbstractGet2Ext extends AbstractGet2 { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public abstract void setX(double a[]); + } + + // ---------- + + public static interface IGet { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + double getX(); + } + + public static class IGetImpl implements IGet { + + private final static String TESTCASE = "implement getter interface"; + + @Override + public double getX() { return X; } + } + + public static class IGetImpl2 implements IGet { + + private final static String TESTCASE = "implement getter interface - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX() { return X; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public abstract static class IGetImpl3 implements IGet { + + private final static String TESTCASE = "implement getter interface - 3"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public abstract void setX(double v); + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static interface IIs { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public boolean isX(); + } + + public static class IIsImpl implements IIs { + + private final static String TESTCASE = "implement is interface"; + + @Override + public boolean isX() { return true; } + } + + public static class IIsImpl2 implements IIs { + + private final static String TESTCASE = "implement is interface - 2"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + @Override + public boolean isX() { return true; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public abstract static class IIsImpl3 implements IIs { + + private final static String TESTCASE = "implement is interface - 3"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public abstract void setX(boolean v); + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static interface ISet { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public void setX(double v); + } + + public static class ISetImpl implements ISet { + + private final static String TESTCASE = "implement getter interface"; + + private double x; + + @Override + public void setX(double v) { x = v; } + } + + public static class ISetImpl2 implements ISet { + + private final static String TESTCASE = "implement getter interface - 2"; + + private double x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(double v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public abstract static class ISetImpl3 implements ISet { + + private final static String TESTCASE = "implement getter interface - 3"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public abstract double getX(); + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static interface ISet2 { + + final static String TESTCASE = "super interface - setter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(double v); + + public void addPropertyChangeListener(PropertyChangeListener l); + public void removePropertyChangeListener(PropertyChangeListener l); + } + + public static class ISet2Impl implements ISet2 { + + private double x; + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + @Override + public void setX(double v) { x = v; } + + @Override + public void addPropertyChangeListener(PropertyChangeListener l) {} + @Override + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static interface IGet2 { + + final static String TESTCASE = "super interface - indexed getter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public double[] getX(); + + public void addPropertyChangeListener(PropertyChangeListener l); + public void removePropertyChangeListener(PropertyChangeListener l); + } + + public static class IGet2Impl implements IGet2 { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + @Override + public double[] getX() { return new double[]{X, X}; } + + @Override + public void addPropertyChangeListener(PropertyChangeListener l) {} + @Override + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + public static class ProtectedGet { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + protected double getX() { return 0.; } + } + + public static class OverrideProtectedGet extends ProtectedGet { + + final static String TESTCASE = "override protected getter"; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX() { return X; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // ---------- + + // static getter - see also JDK-8154938 + public static class StaticGet { + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public static double getProp() { return 0.; } + } + + public static class HideStaticGet extends StaticGet { + + final static String TESTCASE = "hide static getter"; + + public double getX() { return X; } // add to get the "default" info + public static double getProp() { return X; } + } + + // TODO: if 8154938 is considered to be a real issue, + // create one more test case "HideStaticGet2 extends StaticGet" with an + // annotated getter and check the correctness of the corresponding bean info + + // ---------- checks ---------- + + private static boolean check(String what, boolean v, boolean ref) { + + boolean ok = (v == ref); + if (!ok) { System.out.println( + "invalid " + what + ": " + v + ", expected: " + ref); } + return ok; + } + + private static boolean checkInfo(BeanInfo i, boolean ignoreValsCheck) { + + System.out.println("checking info..."); + + PropertyDescriptor descriptors[] = i.getPropertyDescriptors(); + int nd = descriptors.length; + if (nd != 1) { + System.out.println("invalid number of descriptors: " + nd); + return false; + } + + PropertyDescriptor d = descriptors[0]; + + String descr = d.getShortDescription(); + boolean ok = descr.equals(DESCRIPTION); + if (!ok) { System.out.println("invalid description: " + descr + + ", expected: " + DESCRIPTION); } + + ok &= check("isBound", d.isBound(), BOUND); + ok &= check("isExpert", d.isExpert(), EXPERT); + ok &= check("isHidden", d.isHidden(), HIDDEN); + ok &= check("isPreferred", d.isPreferred(), PREFERRED); + ok &= check("required", (boolean) d.getValue("required"), REQUIRED); + ok &= check("visualUpdate", + (boolean) d.getValue("visualUpdate"), UPDATE); + + if (ignoreValsCheck) { return ok; } + + Object vals[] = (Object[]) d.getValue("enumerationValues"); + if (vals == null) { + System.out.println("null enumerationValues"); + return false; + } + + boolean okVals = ( + (vals.length == 3) && + vals[0].toString().equals(V_SHORT) && + vals[1].toString().equals(V) && + vals[2].toString().equals(V_NAME)); + + if (!okVals) { System.out.println("invalid enumerationValues"); } + + return (ok && okVals); + } + + private static boolean checkDefault(BeanInfo i) { + + System.out.println("checking default info..."); + + PropertyDescriptor descriptors[] = i.getPropertyDescriptors(); + int nd = descriptors.length; + if (nd != 1) { + System.out.println("invalid number of descriptors: " + nd); + return false; + } + + PropertyDescriptor d = descriptors[0]; + + String descr = d.getShortDescription(); + boolean ok = descr.equals("x"); + if (!ok) { System.out.println("invalid description: " + descr + + ", expected: x"); } + + ok &= check("isBound", d.isBound(), false); + ok &= check("isExpert", d.isExpert(), false); + ok &= check("isHidden", d.isHidden(), false); + ok &= check("isPreferred", d.isPreferred(), false); + ok &= check("required", (boolean) d.getValue("required"), false); + ok &= check("visualUpdate", + (boolean) d.getValue("visualUpdate"), false); + + Object vals[] = (Object[]) d.getValue("enumerationValues"); + if (vals != null && vals.length > 0) { + System.out.println("non-empty enumerationValues"); + ok = false; + } + + return ok; + } + + // do not check enumerationValues for these classes + private static boolean ignoreVals(Class c) { + return ( + c.equals(BoolGetIs.class) || + c.equals(BoolIsGet.class) || + c.equals(AnnotatedIs.class) || + c.equals(OverrideAnnotatedIs2.class) || + c.equals(AnnotatedIs2Ext.class) || + c.equals(OverrideAbstractIs.class) || + c.equals(OverrideAbstractIs2.class) || + c.equals(AbstractIsExt.class) || + c.equals(OverrideAbstractIs.class) || + c.equals(IIsImpl.class) || + c.equals(IIsImpl2.class) || + c.equals(IIsImpl3.class) + ); + } + + // default property descriptor data are expected for these classes + private static boolean isDefault(Class c) { + return ( + c.equals(OverrideAnnotatedGet.class) || + c.equals(OverrideAnnotatedIs.class ) || + c.equals(OverrideAnnotatedSet.class) || + c.equals(OverrideAbstractGet.class) || + c.equals(OverrideAbstractIs.class) || + c.equals(OverrideAbstractSet.class) || + c.equals(IGetImpl.class) || + c.equals(IIsImpl.class) || + c.equals(ISetImpl.class) || + c.equals(BaseGet.class) || + c.equals(BaseSet.class) || + c.equals(HideStaticGet.class) + ); + } + + + // ---------- run test ---------- + + public static void main(String[] args) throws Exception { + + Class + ic1 = ISet2Impl.class.getInterfaces()[0], + ic2 = IGet2Impl.class.getInterfaces()[0]; + + Class cases[] = { + + OverloadGet.class, + OverloadGet.class.getSuperclass(), + OverloadSet.class, + OverloadSet.class.getSuperclass(), + OverloadIGet.class, + OverloadISet.class, + + // TODO: uncomment/update after 8132565 fix + //BoolGetIs.class, + //BoolIsGet.class, + //OverrideAnnotatedGet.class, + //OverrideAnnotatedIs.class, + //OverrideAnnotatedSet.class, + //OverrideAnnotatedGet2.class, + //AnnotatedGet2Ext.class, + //OverrideAnnotatedIs2.class + //AnnotatedIs2Ext.class, + //OverrideAnnotatedSet2.class, + //AnnotatedSet2Ext.class, + + OverrideAnnotatedGet.class.getSuperclass(), + OverrideAnnotatedIs.class.getSuperclass(), + OverrideAnnotatedSet.class.getSuperclass(), + + // TODO: uncomment/update after 8132565 fix + //OverrideAbstractGet.class, + //OverrideAbstractGet2.class, + //AbstractGetExt.class, + //OverrideAbstractIs.class, + //OverrideAbstractIs2.class, + //AbstractIsExt.class + //OverrideAbstractSet.class, + //OverrideAbstractSet2.class, + //AbstractSetExt.class, + + AbstractGet2Ext.class.getSuperclass(), + IGetImpl.class, + IGetImpl2.class, + IGetImpl3.class, + IIsImpl.class, + IIsImpl2.class, + IIsImpl3.class, + ISetImpl.class, + ISetImpl2.class, + ISetImpl3.class, + ic1, + // ic2, // TODO: uncomment/update after 8155013 fix + OverrideProtectedGet.class, + HideStaticGet.class + }; + + boolean passed = true; + + for (Class c: cases) { + + java.lang.reflect.Field f = c.getDeclaredField("TESTCASE"); + f.setAccessible(true); + String descr = f.get(c).toString(); + + System.out.println("\n" + c.getSimpleName() + " (" + descr + "):"); + BeanInfo i; + try { + i = Introspector.getBeanInfo(c, + (c.equals(ic1) || c.equals(ic2)) ? null : Object.class); + } + catch (IntrospectionException e) { throw new RuntimeException(e); } + + boolean ok; + + if (isDefault(c)) { + ok = checkDefault(i); + } else { + ok = checkInfo(i, ignoreVals(c)); + } + System.out.println(ok ? "OK" : "NOK"); + passed = passed && ok; + } + + if (!passed) { throw new RuntimeException("test failed"); } + System.out.println("\ntest passed"); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/Test4625418.java b/jdk/test/java/beans/XMLEncoder/Test4625418.java index 0f9203e864d..a8a23aced37 100644 --- a/jdk/test/java/beans/XMLEncoder/Test4625418.java +++ b/jdk/test/java/beans/XMLEncoder/Test4625418.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2007, 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 @@ -26,332 +26,338 @@ * @bug 4625418 * @summary Tests XML encoding * @author Sergey Malenkov - * - * @run main Test4625418 ASCII - * @run main Test4625418 Big5 - * ?run main Test4625418 Big5-HKSCS - * ?run main Test4625418 Big5_HKSCS - * @run main Test4625418 Big5_Solaris - * ?run main Test4625418 Cp037 - * @run main Test4625418 Cp1006 - * ?run main Test4625418 Cp1025 - * -run main Test4625418 Cp1026 - * @run main Test4625418 Cp1046 - * @run main Test4625418 Cp1047 - * @run main Test4625418 Cp1097 - * @run main Test4625418 Cp1098 - * ?run main Test4625418 Cp1112 - * ?run main Test4625418 Cp1122 - * ?run main Test4625418 Cp1123 - * @run main Test4625418 Cp1124 - * ?run main Test4625418 Cp1140 - * ?run main Test4625418 Cp1141 - * ?run main Test4625418 Cp1142 - * ?run main Test4625418 Cp1143 - * ?run main Test4625418 Cp1144 - * ?run main Test4625418 Cp1145 - * ?run main Test4625418 Cp1146 - * ?run main Test4625418 Cp1147 - * ?run main Test4625418 Cp1148 - * ?run main Test4625418 Cp1149 - * @run main Test4625418 Cp1250 - * @run main Test4625418 Cp1251 - * @run main Test4625418 Cp1252 - * @run main Test4625418 Cp1253 - * @run main Test4625418 Cp1254 - * @run main Test4625418 Cp1255 - * @run main Test4625418 Cp1256 - * @run main Test4625418 Cp1257 - * @run main Test4625418 Cp1258 - * ?run main Test4625418 Cp1381 - * ?run main Test4625418 Cp1383 - * ?run main Test4625418 Cp273 - * ?run main Test4625418 Cp277 - * ?run main Test4625418 Cp278 - * ?run main Test4625418 Cp280 - * ?run main Test4625418 Cp284 - * ?run main Test4625418 Cp285 - * ?run main Test4625418 Cp297 - * ?run main Test4625418 Cp33722 - * ?run main Test4625418 Cp420 - * ?run main Test4625418 Cp424 - * @run main Test4625418 Cp437 - * ?run main Test4625418 Cp500 - * ?run main Test4625418 Cp50220 - * ?run main Test4625418 Cp50221 - * @run main Test4625418 Cp737 - * @run main Test4625418 Cp775 - * -run main Test4625418 Cp834 - * ?run main Test4625418 Cp838 - * @run main Test4625418 Cp850 - * @run main Test4625418 Cp852 - * @run main Test4625418 Cp855 - * @run main Test4625418 Cp856 - * @run main Test4625418 Cp857 - * @run main Test4625418 Cp858 - * @run main Test4625418 Cp860 - * @run main Test4625418 Cp861 - * @run main Test4625418 Cp862 - * @run main Test4625418 Cp863 - * @run main Test4625418 Cp864 - * @run main Test4625418 Cp865 - * @run main Test4625418 Cp866 - * @run main Test4625418 Cp868 - * @run main Test4625418 Cp869 - * ?run main Test4625418 Cp870 - * ?run main Test4625418 Cp871 - * @run main Test4625418 Cp874 - * ?run main Test4625418 Cp875 - * ?run main Test4625418 Cp918 - * @run main Test4625418 Cp921 - * @run main Test4625418 Cp922 - * -run main Test4625418 Cp930 - * @run main Test4625418 Cp933 - * ?run main Test4625418 Cp935 - * ?run main Test4625418 Cp937 - * ?run main Test4625418 Cp939 - * ?run main Test4625418 Cp942 - * ?run main Test4625418 Cp942C - * @run main Test4625418 Cp943 - * ?run main Test4625418 Cp943C - * @run main Test4625418 Cp948 - * @run main Test4625418 Cp949 - * ?run main Test4625418 Cp949C - * @run main Test4625418 Cp950 - * @run main Test4625418 Cp964 - * ?run main Test4625418 Cp970 - * ?run main Test4625418 EUC-JP - * @run main Test4625418 EUC-KR - * @run main Test4625418 EUC_CN - * ?run main Test4625418 EUC_JP - * ?run main Test4625418 EUC_JP_LINUX - * ?run main Test4625418 EUC_JP_Solaris - * @run main Test4625418 EUC_KR - * ?run main Test4625418 EUC_TW - * @run main Test4625418 GB18030 - * @run main Test4625418 GB2312 - * @run main Test4625418 GBK - * ?run main Test4625418 IBM-Thai - * @run main Test4625418 IBM00858 - * ?run main Test4625418 IBM01140 - * ?run main Test4625418 IBM01141 - * ?run main Test4625418 IBM01142 - * ?run main Test4625418 IBM01143 - * ?run main Test4625418 IBM01144 - * ?run main Test4625418 IBM01145 - * ?run main Test4625418 IBM01146 - * ?run main Test4625418 IBM01147 - * ?run main Test4625418 IBM01148 - * ?run main Test4625418 IBM01149 - * ?run main Test4625418 IBM037 - * -run main Test4625418 IBM1026 - * @run main Test4625418 IBM1047 - * ?run main Test4625418 IBM273 - * ?run main Test4625418 IBM277 - * ?run main Test4625418 IBM278 - * ?run main Test4625418 IBM280 - * ?run main Test4625418 IBM284 - * ?run main Test4625418 IBM285 - * ?run main Test4625418 IBM297 - * ?run main Test4625418 IBM420 - * ?run main Test4625418 IBM424 - * @run main Test4625418 IBM437 - * ?run main Test4625418 IBM500 - * @run main Test4625418 IBM775 - * @run main Test4625418 IBM850 - * @run main Test4625418 IBM852 - * @run main Test4625418 IBM855 - * @run main Test4625418 IBM857 - * @run main Test4625418 IBM860 - * @run main Test4625418 IBM861 - * @run main Test4625418 IBM862 - * @run main Test4625418 IBM863 - * @run main Test4625418 IBM864 - * @run main Test4625418 IBM865 - * @run main Test4625418 IBM866 - * @run main Test4625418 IBM868 - * @run main Test4625418 IBM869 - * ?run main Test4625418 IBM870 - * ?run main Test4625418 IBM871 - * ?run main Test4625418 IBM918 - * ?run main Test4625418 ISCII91 - * -run main Test4625418 ISO-2022-CN - * @run main Test4625418 ISO-2022-JP - * @run main Test4625418 ISO-2022-KR - * @run main Test4625418 ISO-8859-1 - * @run main Test4625418 ISO-8859-13 - * @run main Test4625418 ISO-8859-15 - * @run main Test4625418 ISO-8859-2 - * @run main Test4625418 ISO-8859-3 - * @run main Test4625418 ISO-8859-4 - * @run main Test4625418 ISO-8859-5 - * @run main Test4625418 ISO-8859-6 - * @run main Test4625418 ISO-8859-7 - * @run main Test4625418 ISO-8859-8 - * @run main Test4625418 ISO-8859-9 - * -run main Test4625418 ISO2022CN - * @run main Test4625418 ISO2022JP - * @run main Test4625418 ISO2022KR - * -run main Test4625418 ISO2022_CN_CNS - * -run main Test4625418 ISO2022_CN_GB - * @run main Test4625418 ISO8859_1 - * @run main Test4625418 ISO8859_13 - * @run main Test4625418 ISO8859_15 - * @run main Test4625418 ISO8859_2 - * @run main Test4625418 ISO8859_3 - * @run main Test4625418 ISO8859_4 - * @run main Test4625418 ISO8859_5 - * @run main Test4625418 ISO8859_6 - * @run main Test4625418 ISO8859_7 - * @run main Test4625418 ISO8859_8 - * @run main Test4625418 ISO8859_9 - * -run main Test4625418 JISAutoDetect - * ?run main Test4625418 JIS_X0201 - * -run main Test4625418 JIS_X0212-1990 - * @run main Test4625418 KOI8-R - * @run main Test4625418 KOI8-U - * @run main Test4625418 KOI8_R - * @run main Test4625418 KOI8_U - * @run main Test4625418 MS874 - * ?run main Test4625418 MS932 - * ?run main Test4625418 MS936 - * @run main Test4625418 MS949 - * @run main Test4625418 MS950 - * ?run main Test4625418 MS950_HKSCS - * @run main Test4625418 MacArabic - * @run main Test4625418 MacCentralEurope - * @run main Test4625418 MacCroatian - * @run main Test4625418 MacCyrillic - * -run main Test4625418 MacDingbat - * @run main Test4625418 MacGreek - * @run main Test4625418 MacHebrew - * @run main Test4625418 MacIceland - * @run main Test4625418 MacRoman - * @run main Test4625418 MacRomania - * -run main Test4625418 MacSymbol - * @run main Test4625418 MacThai - * @run main Test4625418 MacTurkish - * @run main Test4625418 MacUkraine - * ?run main Test4625418 PCK - * ?run main Test4625418 SJIS - * ?run main Test4625418 Shift_JIS - * @run main Test4625418 TIS-620 - * @run main Test4625418 TIS620 - * @run main Test4625418 US-ASCII - * @run main Test4625418 UTF-16 - * @run main Test4625418 UTF-16BE - * @run main Test4625418 UTF-16LE - * @run main Test4625418 UTF-32 - * @run main Test4625418 UTF-32BE - * @run main Test4625418 UTF-32LE - * @run main Test4625418 UTF-8 - * @run main Test4625418 UTF8 - * @run main Test4625418 UTF_32 - * @run main Test4625418 UTF_32BE - * -run main Test4625418 UTF_32BE_BOM - * @run main Test4625418 UTF_32LE - * -run main Test4625418 UTF_32LE_BOM - * @run main Test4625418 UnicodeBig - * @run main Test4625418 UnicodeBigUnmarked - * @run main Test4625418 UnicodeLittle - * @run main Test4625418 UnicodeLittleUnmarked - * @run main Test4625418 windows-1250 - * @run main Test4625418 windows-1251 - * @run main Test4625418 windows-1252 - * @run main Test4625418 windows-1253 - * @run main Test4625418 windows-1254 - * @run main Test4625418 windows-1255 - * @run main Test4625418 windows-1256 - * @run main Test4625418 windows-1257 - * @run main Test4625418 windows-1258 - * ?run main Test4625418 windows-31j - * -run main Test4625418 x-Big5_Solaris - * ?run main Test4625418 x-EUC-TW - * @run main Test4625418 x-IBM1006 - * ?run main Test4625418 x-IBM1025 - * @run main Test4625418 x-IBM1046 - * @run main Test4625418 x-IBM1097 - * @run main Test4625418 x-IBM1098 - * ?run main Test4625418 x-IBM1112 - * ?run main Test4625418 x-IBM1122 - * ?run main Test4625418 x-IBM1123 - * @run main Test4625418 x-IBM1124 - * ?run main Test4625418 x-IBM1381 - * ?run main Test4625418 x-IBM1383 - * ?run main Test4625418 x-IBM33722 - * @run main Test4625418 x-IBM737 - * -run main Test4625418 x-IBM834 - * @run main Test4625418 x-IBM856 - * @run main Test4625418 x-IBM874 - * ?run main Test4625418 x-IBM875 - * @run main Test4625418 x-IBM921 - * @run main Test4625418 x-IBM922 - * -run main Test4625418 x-IBM930 - * @run main Test4625418 x-IBM933 - * ?run main Test4625418 x-IBM935 - * ?run main Test4625418 x-IBM937 - * ?run main Test4625418 x-IBM939 - * ?run main Test4625418 x-IBM942 - * ?run main Test4625418 x-IBM942C - * @run main Test4625418 x-IBM943 - * ?run main Test4625418 x-IBM943C - * @run main Test4625418 x-IBM948 - * @run main Test4625418 x-IBM949 - * ?run main Test4625418 x-IBM949C - * @run main Test4625418 x-IBM950 - * @run main Test4625418 x-IBM964 - * ?run main Test4625418 x-IBM970 - * ?run main Test4625418 x-ISCII91 - * -run main Test4625418 x-ISO2022-CN-CNS - * -run main Test4625418 x-ISO2022-CN-GB - * -run main Test4625418 x-JIS0208 - * -run main Test4625418 x-JISAutoDetect - * @run main Test4625418 x-Johab - * ?run main Test4625418 x-MS950-HKSCS - * @run main Test4625418 x-MacArabic - * @run main Test4625418 x-MacCentralEurope - * @run main Test4625418 x-MacCroatian - * @run main Test4625418 x-MacCyrillic - * -run main Test4625418 x-MacDingbat - * @run main Test4625418 x-MacGreek - * @run main Test4625418 x-MacHebrew - * @run main Test4625418 x-MacIceland - * @run main Test4625418 x-MacRoman - * @run main Test4625418 x-MacRomania - * -run main Test4625418 x-MacSymbol - * @run main Test4625418 x-MacThai - * @run main Test4625418 x-MacTurkish - * @run main Test4625418 x-MacUkraine - * ?run main Test4625418 x-PCK - * @run main Test4625418 x-UTF-16LE-BOM - * -run main Test4625418 x-UTF-32BE-BOM - * -run main Test4625418 x-UTF-32LE-BOM - * ?run main Test4625418 x-euc-jp-linux - * ?run main Test4625418 x-eucJP-Open - * @run main Test4625418 x-iso-8859-11 - * @run main Test4625418 x-mswin-936 - * ?run main Test4625418 x-windows-50220 - * ?run main Test4625418 x-windows-50221 - * @run main Test4625418 x-windows-874 - * @run main Test4625418 x-windows-949 - * @run main Test4625418 x-windows-950 - * ?run main Test4625418 x-windows-iso2022jp + * @run main/timeout=360 Test4625418 */ import java.beans.ExceptionListener; import java.beans.XMLDecoder; import java.beans.XMLEncoder; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; public final class Test4625418 implements ExceptionListener { - public static void main(String[] args) { - new Test4625418(args[0]).test(createString(0x10000)); - System.out.println("Test passed: " + args[0]); + + private static final String[] encodings = { + "ASCII", + "Big5", + //"Big5-HKSCS", + //"Big5_HKSCS", + "Big5_Solaris", + //"Cp037", + "Cp1006", + //"Cp1025", + //"Cp1026", + "Cp1046", + "Cp1047", + "Cp1097", + "Cp1098", + //"Cp1112", + //"Cp1122", + //"Cp1123", + "Cp1124", + //"Cp1140", + //"Cp1141", + //"Cp1142", + //"Cp1143", + //"Cp1144", + //"Cp1145", + //"Cp1146", + //"Cp1147", + //"Cp1148", + //"Cp1149", + "Cp1250", + "Cp1251", + "Cp1252", + "Cp1253", + "Cp1254", + "Cp1255", + "Cp1256", + "Cp1257", + "Cp1258", + //"Cp1381", + //"Cp1383", + //"Cp273", + //"Cp277", + //"Cp278", + //"Cp280", + //"Cp284", + //"Cp285", + //"Cp297", + //"Cp33722", + //"Cp420", + //"Cp424", + "Cp437", + //"Cp500", + //"Cp50220", + //"Cp50221", + "Cp737", + "Cp775", + //"Cp834", + //"Cp838", + "Cp850", + "Cp852", + "Cp855", + "Cp856", + "Cp857", + "Cp858", + "Cp860", + "Cp861", + "Cp862", + "Cp863", + "Cp864", + "Cp865", + "Cp866", + "Cp868", + "Cp869", + //"Cp870", + //"Cp871", + "Cp874", + //"Cp875", + //"Cp918", + "Cp921", + "Cp922", + //"Cp930", + "Cp933", + //"Cp935", + //"Cp937", + //"Cp939", + //"Cp942", + //"Cp942C", + "Cp943", + //"Cp943C", + "Cp948", + "Cp949", + //"Cp949C", + "Cp950", + "Cp964", + //"Cp970", + //"EUC-JP", + "EUC-KR", + "EUC_CN", + //"EUC_JP", + //"EUC_JP_LINUX", + //"EUC_JP_Solaris", + "EUC_KR", + //"EUC_TW", + "GB18030", + "GB2312", + "GBK", + //"IBM-Thai", + "IBM00858", + //"IBM01140", + //"IBM01141", + //"IBM01142", + //"IBM01143", + //"IBM01144", + //"IBM01145", + //"IBM01146", + //"IBM01147", + //"IBM01148", + //"IBM01149", + //"IBM037", + //"IBM1026", + "IBM1047", + //"IBM273", + //"IBM277", + //"IBM278", + //"IBM280", + //"IBM284", + //"IBM285", + //"IBM297", + //"IBM420", + //"IBM424", + "IBM437", + //"IBM500", + "IBM775", + "IBM850", + "IBM852", + "IBM855", + "IBM857", + "IBM860", + "IBM861", + "IBM862", + "IBM863", + "IBM864", + "IBM865", + "IBM866", + "IBM868", + "IBM869", + //"IBM870", + //"IBM871", + //"IBM918", + //"ISCII91", + //"ISO-2022-CN", + "ISO-2022-JP", + "ISO-2022-KR", + "ISO-8859-1", + "ISO-8859-13", + "ISO-8859-15", + "ISO-8859-2", + "ISO-8859-3", + "ISO-8859-4", + "ISO-8859-5", + "ISO-8859-6", + "ISO-8859-7", + "ISO-8859-8", + "ISO-8859-9", + //"ISO2022CN", + "ISO2022JP", + "ISO2022KR", + //"ISO2022_CN_CNS", + //"ISO2022_CN_GB", + "ISO8859_1", + "ISO8859_13", + "ISO8859_15", + "ISO8859_2", + "ISO8859_3", + "ISO8859_4", + "ISO8859_5", + "ISO8859_6", + "ISO8859_7", + "ISO8859_8", + "ISO8859_9", + //"JISAutoDetect", + //"JIS_X0201", + //"JIS_X0212-1990", + "KOI8-R", + "KOI8-U", + "KOI8_R", + "KOI8_U", + "MS874", + //"MS932", + //"MS936", + "MS949", + "MS950", + //"MS950_HKSCS", + "MacArabic", + "MacCentralEurope", + "MacCroatian", + "MacCyrillic", + //"MacDingbat", + "MacGreek", + "MacHebrew", + "MacIceland", + "MacRoman", + "MacRomania", + //"MacSymbol", + "MacThai", + "MacTurkish", + "MacUkraine", + //"PCK", + //"SJIS", + //"Shift_JIS", + "TIS-620", + "TIS620", + "US-ASCII", + "UTF-16", + "UTF-16BE", + "UTF-16LE", + "UTF-32", + "UTF-32BE", + "UTF-32LE", + "UTF-8", + "UTF8", + "UTF_32", + "UTF_32BE", + //"UTF_32BE_BOM", + "UTF_32LE", + //"UTF_32LE_BOM", + "UnicodeBig", + "UnicodeBigUnmarked", + "UnicodeLittle", + "UnicodeLittleUnmarked", + "windows-1250", + "windows-1251", + "windows-1252", + "windows-1253", + "windows-1254", + "windows-1255", + "windows-1256", + "windows-1257", + "windows-1258", + //"windows-31j", + //"x-Big5_Solaris", + //"x-EUC-TW", + "x-IBM1006", + //"x-IBM1025", + "x-IBM1046", + "x-IBM1097", + "x-IBM1098", + //"x-IBM1112", + //"x-IBM1122", + //"x-IBM1123", + "x-IBM1124", + //"x-IBM1381", + //"x-IBM1383", + //"x-IBM33722", + "x-IBM737", + //"x-IBM834", + "x-IBM856", + "x-IBM874", + //"x-IBM875", + "x-IBM921", + "x-IBM922", + //"x-IBM930", + "x-IBM933", + //"x-IBM935", + //"x-IBM937", + //"x-IBM939", + //"x-IBM942", + //"x-IBM942C", + "x-IBM943", + //"x-IBM943C", + "x-IBM948", + "x-IBM949", + //"x-IBM949C", + "x-IBM950", + "x-IBM964", + //"x-IBM970", + //"x-ISCII91", + //"x-ISO2022-CN-CNS", + //"x-ISO2022-CN-GB", + //"x-JIS0208", + //"x-JISAutoDetect", + "x-Johab", + //"x-MS950-HKSCS", + "x-MacArabic", + "x-MacCentralEurope", + "x-MacCroatian", + "x-MacCyrillic", + //"x-MacDingbat", + "x-MacGreek", + "x-MacHebrew", + "x-MacIceland", + "x-MacRoman", + "x-MacRomania", + //"x-MacSymbol", + "x-MacThai", + "x-MacTurkish", + "x-MacUkraine", + //"x-PCK", + "x-UTF-16LE-BOM", + //"x-UTF-32BE-BOM", + //"x-UTF-32LE-BOM", + //"x-euc-jp-linux", + //"x-eucJP-Open", + "x-iso-8859-11", + "x-mswin-936", + //"x-windows-50220", + //"x-windows-50221", + "x-windows-874", + "x-windows-949", + "x-windows-950", + //"x-windows-iso2022jp", + }; + + public static void main(final String[] args) { + final String string = createString(0x10000); + for (String encoding : encodings) { + System.out.println("Test encoding: " + encoding); + new Test4625418(encoding).test(string); + } } private static String createString(int length) { @@ -364,33 +370,27 @@ public final class Test4625418 implements ExceptionListener { private final String encoding; - private Test4625418(String encoding) { + private Test4625418(final String encoding) { this.encoding = encoding; } private void test(String string) { try { - File file = new File("4625418." + this.encoding + ".xml"); - - FileOutputStream output = new FileOutputStream(file); + ByteArrayOutputStream output = new ByteArrayOutputStream(); XMLEncoder encoder = new XMLEncoder(output, this.encoding, true, 0); encoder.setExceptionListener(this); encoder.writeObject(string); encoder.close(); - FileInputStream input = new FileInputStream(file); + InputStream input = new ByteArrayInputStream(output.toByteArray()); XMLDecoder decoder = new XMLDecoder(input); decoder.setExceptionListener(this); Object object = decoder.readObject(); decoder.close(); - if (!string.equals(object)) + if (!string.equals(object)) { throw new Error(this.encoding + " - can't read properly"); - - file.delete(); - } - catch (FileNotFoundException exception) { - throw new Error(this.encoding + " - file not found", exception); + } } catch (IllegalCharsetNameException exception) { throw new Error(this.encoding + " - illegal charset name", exception); diff --git a/jdk/test/java/lang/Class/forName/modules/TestLayer.java b/jdk/test/java/lang/Class/forName/modules/TestLayer.java index 8a01cb18b51..645e04d7e9b 100644 --- a/jdk/test/java/lang/Class/forName/modules/TestLayer.java +++ b/jdk/test/java/lang/Class/forName/modules/TestLayer.java @@ -46,7 +46,7 @@ public class TestLayer { ModuleFinder finder = ModuleFinder.of(MODS_DIR); Configuration parent = Layer.boot().configuration(); - Configuration cf = parent.resolveRequiresAndUses(ModuleFinder.empty(), + Configuration cf = parent.resolveRequiresAndUses(ModuleFinder.of(), finder, modules); diff --git a/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoAccess.java b/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoAccess.java index 902e92d7c00..618b2fde67a 100644 --- a/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoAccess.java +++ b/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoAccess.java @@ -51,7 +51,7 @@ public class NoAccess { Configuration parent = bootLayer.configuration(); Configuration cf = parent.resolveRequiresAndUses(finder, - ModuleFinder.empty(), + ModuleFinder.of(), Set.of("m1", "m2")); ClassLoader scl = ClassLoader.getSystemClassLoader(); diff --git a/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java b/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java index a162debb3f8..9052737aad5 100644 --- a/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java +++ b/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java @@ -228,12 +228,18 @@ public class FieldSetAccessibleTest { } static boolean test(String s, boolean addExports) { + String clsName = s.replace('/', '.').substring(0, s.length() - 6); try { + System.out.println("Loading " + clsName); final Class c = Class.forName( - s.replace('/', '.').substring(0, s.length() - 6), + clsName, false, systemClassLoader); return test(c, addExports); + } catch (VerifyError ve) { + System.err.println("VerifyError for " + clsName); + ve.printStackTrace(System.err); + failed.add(s); } catch (Exception t) { t.printStackTrace(System.err); failed.add(s); diff --git a/jdk/test/java/lang/ClassLoader/deadlock/GetResource.java b/jdk/test/java/lang/ClassLoader/deadlock/GetResource.java index a1a1b4e1730..26fbe3dd586 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/GetResource.java +++ b/jdk/test/java/lang/ClassLoader/deadlock/GetResource.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ import java.io.IOException; import java.net.URL; /* @test - * @bug 6977738 + * @bug 6977738 8029891 * @summary Test ClassLoader.getResource() that should not deadlock # if another thread is holding the system properties object * @@ -70,10 +70,6 @@ public class GetResource { go.await(); // wait until t1 holds the lock of the system properties URL u1 = Thread.currentThread().getContextClassLoader().getResource("unknownresource"); - URL u2 = Thread.currentThread().getContextClassLoader().getResource("sun/util/resources/CalendarData.class"); - if (u2 == null) { - throw new RuntimeException("Test failed: resource not found"); - } done.await(); } catch (InterruptedException e) { throw new RuntimeException(e); diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh index 3872f813ffd..a00c14077d6 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh +++ b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh @@ -106,7 +106,7 @@ done # run test ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ - -verbose:class -Xlog:classload -cp . \ + -verbose:class -Xlog:class+load -cp . \ -Dtest.classes=${TESTCLASSES} \ Starter cross # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \ diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh index 198cd70827a..1289b4c861e 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh +++ b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh @@ -102,7 +102,7 @@ done # run test ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ - -verbose:class -Xlog:classload -cp . \ + -verbose:class -Xlog:class+load -cp . \ -Dtest.classes=${TESTCLASSES} \ Starter one-way # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \ diff --git a/jdk/test/java/lang/Math/DivModTests.java b/jdk/test/java/lang/Math/DivModTests.java index fbd98e62c8a..772bb1c91f1 100644 --- a/jdk/test/java/lang/Math/DivModTests.java +++ b/jdk/test/java/lang/Math/DivModTests.java @@ -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 @@ -184,7 +184,7 @@ public class DivModTests { } /** - * Test the integer floorDiv and floorMod methods. + * Test the long floorDiv and floorMod methods. * Math and StrictMath are tested and the same results are expected for both. */ static void testLongFloorDivMod(long x, long y, Object divExpected, Object modExpected) { @@ -252,6 +252,110 @@ public class DivModTests { } } + /** + * Test the floorDiv and floorMod methods for mixed long and int. + */ + static void testLongIntFloorDivMod() { + testLongIntFloorDivMod(4L, 0, new ArithmeticException(), new ArithmeticException()); // Should throw ArithmeticException + testLongIntFloorDivMod(4L, 3, 1L, 1); + testLongIntFloorDivMod(3L, 3, 1L, 0); + testLongIntFloorDivMod(2L, 3, 0L, 2); + testLongIntFloorDivMod(1L, 3, 0L, 1); + testLongIntFloorDivMod(0L, 3, 0L, 0); + testLongIntFloorDivMod(4L, -3, -2L, -2); + testLongIntFloorDivMod(3L, -3, -1L, 0); + testLongIntFloorDivMod(2L, -3, -1L, -1); + testLongIntFloorDivMod(1L, -3, -1L, -2); + testLongIntFloorDivMod(0L, -3, 0L, 0); + testLongIntFloorDivMod(-1L, 3, -1L, 2); + testLongIntFloorDivMod(-2L, 3, -1L, 1); + testLongIntFloorDivMod(-3L, 3, -1L, 0); + testLongIntFloorDivMod(-4L, 3, -2L, 2); + testLongIntFloorDivMod(-1L, -3, 0L, -1); + testLongIntFloorDivMod(-2L, -3, 0L, -2); + testLongIntFloorDivMod(-3L, -3, 1L, 0); + testLongIntFloorDivMod(-4L, -3, 1L, -1); + + testLongIntFloorDivMod(Long.MAX_VALUE, 1, Long.MAX_VALUE, 0L); + testLongIntFloorDivMod(Long.MAX_VALUE, -1, -Long.MAX_VALUE, 0L); + testLongIntFloorDivMod(Long.MAX_VALUE, 3, Long.MAX_VALUE / 3L, 1L); + testLongIntFloorDivMod(Long.MAX_VALUE - 1L, 3, (Long.MAX_VALUE - 1L) / 3L, 0L); + testLongIntFloorDivMod(Long.MIN_VALUE, 3, Long.MIN_VALUE / 3L - 1L, 1L); + testLongIntFloorDivMod(Long.MIN_VALUE + 1L, 3, Long.MIN_VALUE / 3L - 1L, 2L); + testLongIntFloorDivMod(Long.MIN_VALUE + 1, -1, Long.MAX_VALUE, 0L); + // Special case of integer overflow + testLongIntFloorDivMod(Long.MIN_VALUE, -1, Long.MIN_VALUE, 0L); + } + + /** + * Test the integer floorDiv and floorMod methods. + * Math and StrictMath are tested and the same results are expected for both. + */ + static void testLongIntFloorDivMod(long x, int y, Object divExpected, Object modExpected) { + testLongIntFloorDiv(x, y, divExpected); + testLongIntFloorMod(x, y, modExpected); + } + + /** + * Test FloorDiv with long arguments against expected value. + * The expected value is usually a Long but in some cases is + * an ArithmeticException. + * + * @param x dividend + * @param y modulus + * @param expected expected value, + */ + static void testLongIntFloorDiv(long x, int y, Object expected) { + Object result = doFloorDiv(x, y); + if (!resultEquals(result, expected)) { + fail("FAIL: long Math.floorDiv(%d, %d) = %s; expected %s%n", x, y, result, expected); + } + + Object strict_result = doStrictFloorDiv(x, y); + if (!resultEquals(strict_result, expected)) { + fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected); + } + } + + /** + * Test FloorMod of long arguments against expected value. + * The expected value is usually a Long but in some cases is + * an ArithmeticException. + * + * @param x dividend + * @param y modulus + * @param expected expected value + */ + static void testLongIntFloorMod(long x, int y, Object expected) { + Object result = doFloorMod(x, y); + if (!resultEquals(result, expected)) { + fail("FAIL: long Math.floorMod(%d, %d) = %s; expected %s%n", x, y, result, expected); + } + + Object strict_result = doStrictFloorMod(x, y); + if (!resultEquals(strict_result, expected)) { + fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected); + } + + try { + // Verify the result against BigDecimal rounding mode. + BigDecimal xD = new BigDecimal(x); + BigDecimal yD = new BigDecimal(y); + BigDecimal resultD = xD.divide(yD, RoundingMode.FLOOR); + resultD = resultD.multiply(yD); + resultD = xD.subtract(resultD); + long fr = resultD.longValue(); + if (!result.equals(fr)) { + fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n", x, y, result, fr); + + } + } catch (ArithmeticException ae) { + if (y != 0) { + fail("FAIL: long Math.floorMod(%d, %d); unexpected ArithmeticException from bigdecimal"); + } + } + } + /** * Invoke floorDiv and return the result or any exception. * @param x the x value @@ -266,6 +370,20 @@ public class DivModTests { } } + /** + * Invoke floorDiv and return the result or any exception. + * @param x the x value + * @param y the y value + * @return the result Integer or an exception. + */ + static Object doFloorDiv(long x, int y) { + try { + return Math.floorDiv(x, y); + } catch (ArithmeticException ae) { + return ae; + } + } + /** * Invoke floorDiv and return the result or any exception. * @param x the x value @@ -294,6 +412,20 @@ public class DivModTests { } } + /** + * Invoke floorDiv and return the result or any exception. + * @param x the x value + * @param y the y value + * @return the result Integer or an exception. + */ + static Object doFloorMod(long x, int y) { + try { + return Math.floorMod(x, y); + } catch (ArithmeticException ae) { + return ae; + } + } + /** * Invoke floorDiv and return the result or any exception. * @param x the x value @@ -322,6 +454,20 @@ public class DivModTests { } } + /** + * Invoke floorDiv and return the result or any exception. + * @param x the x value + * @param y the y value + * @return the result Integer or an exception. + */ + static Object doStrictFloorDiv(long x, int y) { + try { + return StrictMath.floorDiv(x, y); + } catch (ArithmeticException ae) { + return ae; + } + } + /** * Invoke floorDiv and return the result or any exception. * @param x the x value @@ -350,6 +496,20 @@ public class DivModTests { } } + /** + * Invoke floorDiv and return the result or any exception. + * @param x the x value + * @param y the y value + * @return the result Integer or an exception. + */ + static Object doStrictFloorMod(long x, int y) { + try { + return StrictMath.floorMod(x, y); + } catch (ArithmeticException ae) { + return ae; + } + } + /** * Invoke floorDiv and return the result or any exception. * @param x the x value diff --git a/jdk/test/java/lang/Math/ExactArithTests.java b/jdk/test/java/lang/Math/ExactArithTests.java index 709ea618cb0..37a8a1f009c 100644 --- a/jdk/test/java/lang/Math/ExactArithTests.java +++ b/jdk/test/java/lang/Math/ExactArithTests.java @@ -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 @@ -43,6 +43,7 @@ public class ExactArithTests { public static void main(String[] args) { testIntegerExact(); testLongExact(); + testLongIntExact(); if (errors > 0) { throw new RuntimeException(errors + " errors found in ExactArithTests."); @@ -132,6 +133,7 @@ public class ExactArithTests { fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex); } } + try { // Test incrementExact int inc = Math.incrementExact(x); @@ -345,4 +347,60 @@ public class ExactArithTests { static boolean inLongRange(BigInteger value) { return value.bitLength() <= 63; } + + /** + * Test Math.multiplyExact method with {@code long} and {@code int} + * arguments. + */ + static void testLongIntExact() { + testLongIntExact(0, 0); + testLongIntExact(1, 1); + testLongIntExact(1, -1); + testLongIntExact(1000, 2000); + + testLongIntExact(Long.MIN_VALUE, Integer.MIN_VALUE); + testLongIntExact(Long.MAX_VALUE, Integer.MAX_VALUE); + testLongIntExact(Long.MIN_VALUE, 1); + testLongIntExact(Long.MAX_VALUE, 1); + testLongIntExact(Long.MIN_VALUE, 2); + testLongIntExact(Long.MAX_VALUE, 2); + testLongIntExact(Long.MIN_VALUE, -1); + testLongIntExact(Long.MAX_VALUE, -1); + testLongIntExact(Long.MIN_VALUE, -2); + testLongIntExact(Long.MAX_VALUE, -2); + testLongIntExact(Long.MIN_VALUE/2, 2); + testLongIntExact(Long.MAX_VALUE, 2); + testLongIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE); + testLongIntExact(Integer.MAX_VALUE, -Integer.MAX_VALUE); + testLongIntExact((long)Integer.MAX_VALUE+1L, Integer.MAX_VALUE); + testLongIntExact((long)Integer.MAX_VALUE+1L, -Integer.MAX_VALUE+1); + testLongIntExact((long)Integer.MIN_VALUE-1L, Integer.MIN_VALUE); + testLongIntExact((long)Integer.MIN_VALUE-1, Integer.MAX_VALUE); + testLongIntExact(Integer.MIN_VALUE/2, 2); + } + + /** + * Test long-int exact arithmetic by comparing with the same operations using BigInteger + * and checking that the result is the same as the long truncation. + * Errors are reported with {@link fail}. + * + * @param x first parameter + * @param y second parameter + */ + static void testLongIntExact(long x, int y) { + BigInteger resultBig = null; + final BigInteger xBig = BigInteger.valueOf(x); + final BigInteger yBig = BigInteger.valueOf(y); + + try { + // Test multiplyExact + resultBig = xBig.multiply(yBig); + long product = Math.multiplyExact(x, y); + checkResult("long Math.multiplyExact", x, y, product, resultBig); + } catch (ArithmeticException ex) { + if (inLongRange(resultBig)) { + fail("FAIL: long Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex); + } + } + } } diff --git a/jdk/test/java/lang/Math/MultiplicationTests.java b/jdk/test/java/lang/Math/MultiplicationTests.java new file mode 100644 index 00000000000..1a9c3da2a67 --- /dev/null +++ b/jdk/test/java/lang/Math/MultiplicationTests.java @@ -0,0 +1,113 @@ +/* + * 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 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.* + * @run main MultiplicationTests + * @bug 5100935 + * @summary Tests for multiplication methods (use -Dseed=X to set PRNG seed) + * @key randomness + */ + +import java.math.BigInteger; +import jdk.testlibrary.RandomFactory; + +public class MultiplicationTests { + private MultiplicationTests(){} + + // Number of random products to test. + private static final int COUNT = 1 << 16; + + // Initialize shared random number generator + private static java.util.Random rnd = RandomFactory.getRandom(); + + // Calculate high 64 bits of 128 product using BigInteger. + private static long multiplyHighBigInt(long x, long y) { + return BigInteger.valueOf(x).multiply(BigInteger.valueOf(y)) + .shiftRight(64).longValue(); + } + + // Check Math.multiplyHigh(x,y) against multiplyHighBigInt(x,y) + private static boolean check(long x, long y) { + long p1 = multiplyHighBigInt(x, y); + long p2 = Math.multiplyHigh(x, y); + if (p1 != p2) { + System.err.printf("Error - x:%d y:%d p1:%d p2:%d\n", x, y, p1, p2); + return false; + } else { + return true; + } + } + + private static int testMultiplyHigh() { + int failures = 0; + + // check some boundary cases + long[][] v = new long[][]{ + {0L, 0L}, + {-1L, 0L}, + {0L, -1L}, + {1L, 0L}, + {0L, 1L}, + {-1L, -1L}, + {-1L, 1L}, + {1L, -1L}, + {1L, 1L}, + {Long.MAX_VALUE, Long.MAX_VALUE}, + {Long.MAX_VALUE, -Long.MAX_VALUE}, + {-Long.MAX_VALUE, Long.MAX_VALUE}, + {Long.MAX_VALUE, Long.MIN_VALUE}, + {Long.MIN_VALUE, Long.MAX_VALUE}, + {Long.MIN_VALUE, Long.MIN_VALUE} + }; + + for (long[] xy : v) { + if(!check(xy[0], xy[1])) { + failures++; + } + } + + // check some random values + for (int i = 0; i < COUNT; i++) { + if (!check(rnd.nextLong(), rnd.nextLong())) { + failures++; + } + } + + return failures; + } + + public static void main(String argv[]) { + int failures = testMultiplyHigh(); + + if (failures > 0) { + System.err.println("Multiplication testing encountered " + + failures + " failures."); + throw new RuntimeException(); + } else { + System.out.println("MultiplicationTests succeeded"); + } + } +} diff --git a/jdk/test/jdk/Version/Basic.java b/jdk/test/java/lang/Runtime/Version/Basic.java similarity index 96% rename from jdk/test/jdk/Version/Basic.java rename to jdk/test/java/lang/Runtime/Version/Basic.java index b94180c8daf..0a60ad256d6 100644 --- a/jdk/test/jdk/Version/Basic.java +++ b/jdk/test/java/lang/Runtime/Version/Basic.java @@ -23,12 +23,13 @@ /* * @test - * @summary Unit test for jdk.Version. - * @bug 8072379 + * @summary Unit test for java.lang.Runtime.Version. + * @bug 8072379 8144062 */ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.Runtime.Version; import java.math.BigInteger; import java.util.stream.Collectors; import java.util.Arrays; @@ -36,7 +37,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import jdk.Version; import static java.lang.System.out; public class Basic { @@ -116,8 +116,8 @@ public class Basic { tryCatch("1.4142+-", IAE); tryCatch("2.9979+-%", IAE); - //// Test for current() - testCurrent(); + //// Test for Runtime.version() + testVersion(); //// Test for equals{IgnoreOpt}?(), hashCode(), compareTo{IgnoreOpt}?() // compare: after "<" == -1, equal == 0, before ">" == 1 @@ -219,18 +219,19 @@ public class Basic { pass(); } - private static void testCurrent() { - Version current = Version.current(); - String javaVer = System.getProperty("java.version"); + private static void testVersion() { + Version current = Runtime.version(); + String javaVer = System.getProperty("java.runtime.version"); - // java.version == $VNUM(\-$PRE) - String [] ver = javaVer.split("-"); + // java.runtime.version == $VNUM(\-$PRE)?(\+$BUILD)?(-$OPT)? + String [] jv = javaVer.split("\\+"); + String [] ver = jv[0].split("-"); List javaVerVNum = Arrays.stream(ver[0].split("\\.")) .map(v -> Integer.parseInt(v)) .collect(Collectors.toList()); if (!javaVerVNum.equals(current.version())) { - fail("testCurrent() version()", javaVerVNum.toString(), + fail("Runtime.version()", javaVerVNum.toString(), current.version().toString()); } else { pass(); diff --git a/jdk/test/java/lang/StackWalker/CountLocalSlots.java b/jdk/test/java/lang/StackWalker/CountLocalSlots.java new file mode 100644 index 00000000000..c78a4cb7bf4 --- /dev/null +++ b/jdk/test/java/lang/StackWalker/CountLocalSlots.java @@ -0,0 +1,61 @@ +/* + * 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 8147039 + * @summary Confirm locals[] always has expected length, even for "dead" locals + * @compile LocalsAndOperands.java + * @run testng/othervm -Xcomp CountLocalSlots + */ + +import org.testng.annotations.Test; +import java.lang.StackWalker.StackFrame; + +public class CountLocalSlots { + final static boolean debug = true; + + @Test(dataProvider = "provider", dataProviderClass = LocalsAndOperands.class) + public void countLocalSlots(StackFrame... frames) { + for (StackFrame frame : frames) { + if (debug) { + System.out.println("Running countLocalSlots"); + LocalsAndOperands.dumpStackWithLocals(frames); + } + // Confirm expected number of locals + String methodName = frame.getMethodName(); + Integer expectedObj = (Integer) LocalsAndOperands.Tester.NUM_LOCALS.get(methodName); + if (expectedObj == null) { + if (!debug) { LocalsAndOperands.dumpStackWithLocals(frames); } + throw new RuntimeException("No NUM_LOCALS entry for " + + methodName + "(). Update test?"); + } + Object[] locals = (Object[]) LocalsAndOperands.invokeGetLocals(frame); + if (locals.length != expectedObj) { + if (!debug) { LocalsAndOperands.dumpStackWithLocals(frames); } + throw new RuntimeException(methodName + "(): number of locals (" + + locals.length + ") did not match expected (" + expectedObj + ")"); + } + } + } +} diff --git a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java index 63a6731a164..b253ab27e81 100644 --- a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java +++ b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,17 +23,20 @@ /* * @test - * @bug 8020968 - * @summary Sanity test for locals and operands - * @run main LocalsAndOperands + * @bug 8020968 8147039 + * @summary Tests for locals and operands + * @run testng LocalsAndOperands */ +import org.testng.annotations.*; import java.lang.StackWalker.StackFrame; import java.lang.reflect.*; -import java.util.List; -import java.util.stream.Collectors; +import java.util.*; +import java.util.stream.*; public class LocalsAndOperands { + static final boolean debug = true; + static Class liveStackFrameClass; static Class primitiveValueClass; static StackWalker extendedWalker; @@ -41,92 +44,319 @@ public class LocalsAndOperands { static Method getOperands; static Method getMonitors; static Method primitiveType; - public static void main(String... args) throws Exception { - liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); - primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); - getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); - getLocals.setAccessible(true); + static { + try { + liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); + primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); - getOperands = liveStackFrameClass.getDeclaredMethod("getStack"); - getOperands.setAccessible(true); + getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); + getLocals.setAccessible(true); - getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors"); - getMonitors.setAccessible(true); + getOperands = liveStackFrameClass.getDeclaredMethod("getStack"); + getOperands.setAccessible(true); - primitiveType = primitiveValueClass.getDeclaredMethod("type"); - primitiveType.setAccessible(true); + getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors"); + getMonitors.setAccessible(true); - Method method = liveStackFrameClass.getMethod("getStackWalker"); - method.setAccessible(true); - extendedWalker = (StackWalker) method.invoke(null); - new LocalsAndOperands(extendedWalker, true).test(); + primitiveType = primitiveValueClass.getDeclaredMethod("type"); + primitiveType.setAccessible(true); - // no access to local and operands. - new LocalsAndOperands(StackWalker.getInstance(), false).test(); + Method method = liveStackFrameClass.getMethod("getStackWalker"); + method.setAccessible(true); + extendedWalker = (StackWalker) method.invoke(null); + } catch (Throwable t) { throw new RuntimeException(t); } } - private final StackWalker walker; - private final boolean extended; - LocalsAndOperands(StackWalker walker, boolean extended) { - this.walker = walker; - this.extended = extended; + /** Helper method to return a StackFrame's locals */ + static Object[] invokeGetLocals(StackFrame arg) { + try { + return (Object[]) getLocals.invoke(arg); + } catch (Exception e) { throw new RuntimeException(e); } } - synchronized void test() throws Exception { - int x = 10; - char c = 'z'; - String hi = "himom"; - long l = 1000000L; - double d = 3.1415926; + /***************** + * DataProviders * + *****************/ - List frames = walker.walk(s -> s.collect(Collectors.toList())); - if (extended) { - for (StackWalker.StackFrame f : frames) { - System.out.println("frame: " + f); - Object[] locals = (Object[]) getLocals.invoke(f); + /** Calls testLocals() and provides LiveStackFrames for testLocals* methods */ + @DataProvider + public static StackFrame[][] provider() { + return new StackFrame[][] { + new Tester().testLocals() + }; + } + + /** + * Calls testLocalsKeepAlive() and provides LiveStackFrames for testLocals* methods. + * Local variables in testLocalsKeepAlive() are ensured to not become dead. + */ + @DataProvider + public static StackFrame[][] keepAliveProvider() { + return new StackFrame[][] { + new Tester().testLocalsKeepAlive() + }; + } + + /** + * Provides StackFrames from a StackWalker without the LOCALS_AND_OPERANDS + * option. + */ + @DataProvider + public static StackFrame[][] noLocalsProvider() { + // Use default StackWalker + return new StackFrame[][] { + new Tester(StackWalker.getInstance(), true).testLocals() + }; + } + + /** + * Calls testLocals() and provides LiveStackFrames for *all* called methods, + * including test infrastructure (jtreg, testng, etc) + * + */ + @DataProvider + public static StackFrame[][] unfilteredProvider() { + return new StackFrame[][] { + new Tester(extendedWalker, false).testLocals() + }; + } + + /**************** + * Test methods * + ****************/ + + /** + * Check for expected local values and types in the LiveStackFrame + */ + @Test(dataProvider = "keepAliveProvider") + public static void checkLocalValues(StackFrame... frames) { + if (debug) { + System.out.println("Running checkLocalValues"); + dumpStackWithLocals(frames); + } + Arrays.stream(frames).filter(f -> f.getMethodName() + .equals("testLocalsKeepAlive")) + .forEach( + f -> { + Object[] locals = invokeGetLocals(f); for (int i = 0; i < locals.length; i++) { - System.out.format(" local %d: %s type %s\n", i, locals[i], type(locals[i])); + // Value + String expected = Tester.LOCAL_VALUES[i]; + Object observed = locals[i]; + if (expected != null /* skip nulls in golden values */ && + !expected.equals(observed.toString())) { + System.err.println("Local value mismatch:"); + if (!debug) { dumpStackWithLocals(frames); } + throw new RuntimeException("local " + i + " value is " + + observed + ", expected " + expected); + } - // check for non-null locals in LocalsAndOperands.test() - if (f.getClassName().equals("LocalsAndOperands") && - f.getMethodName().equals("test")) { - if (locals[i] == null) { - throw new RuntimeException("kept-alive locals should not be null"); - } + // Type + expected = Tester.LOCAL_TYPES[i]; + observed = type(locals[i]); + if (expected != null /* skip nulls in golden values */ && + !expected.equals(observed)) { + System.err.println("Local type mismatch:"); + if (!debug) { dumpStackWithLocals(frames); } + throw new RuntimeException("local " + i + " type is " + + observed + ", expected " + expected); } } - - Object[] operands = (Object[]) getOperands.invoke(f); - for (int i = 0; i < operands.length; i++) { - System.out.format(" operand %d: %s type %s%n", i, operands[i], - type(operands[i])); - } - - Object[] monitors = (Object[]) getMonitors.invoke(f); - for (int i = 0; i < monitors.length; i++) { - System.out.format(" monitor %d: %s%n", i, monitors[i]); - } } - } else { - for (StackFrame f : frames) { - if (liveStackFrameClass.isInstance(f)) { - throw new RuntimeException("should not be LiveStackFrame"); - } - } - } - // Use local variables so they stay alive - System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d); + ); } - String type(Object o) throws Exception { - if (o == null) { - return "null"; - } else if (primitiveValueClass.isInstance(o)) { - char c = (char)primitiveType.invoke(o); - return String.valueOf(c); - } else { - return o.getClass().getName(); + /** + * Basic sanity check for locals and operands + */ + @Test(dataProvider = "provider") + public static void sanityCheck(StackFrame... frames) { + if (debug) { + System.out.println("Running sanityCheck"); } + try { + Stream stream = Arrays.stream(frames); + if (debug) { + stream.forEach(LocalsAndOperands::printLocals); + } else { + System.out.println(stream.count() + " frames"); + } + } catch (Throwable t) { + dumpStackWithLocals(frames); + throw t; + } + } + + /** + * Sanity check for locals and operands, including testng/jtreg frames + */ + @Test(dataProvider = "unfilteredProvider") + public static void unfilteredSanityCheck(StackFrame... frames) { + if (debug) { + System.out.println("Running unfilteredSanityCheck"); + } + try { + Stream stream = Arrays.stream(frames); + if (debug) { + stream.forEach(f -> { System.out.println(f + ": " + + invokeGetLocals(f).length + " locals"); } ); + } else { + System.out.println(stream.count() + " frames"); + } + } catch (Throwable t) { + dumpStackWithLocals(frames); + throw t; + } + } + + /** + * Test that LiveStackFrames are not provided with the default StackWalker + * options. + */ + @Test(dataProvider = "noLocalsProvider") + public static void withoutLocalsAndOperands(StackFrame... frames) { + for (StackFrame frame : frames) { + if (liveStackFrameClass.isInstance(frame)) { + throw new RuntimeException("should not be LiveStackFrame"); + } + } + } + + static class Tester { + private StackWalker walker; + private boolean filter = true; // Filter out testng/jtreg/etc frames? + + Tester() { + this.walker = extendedWalker; + } + + Tester(StackWalker walker, boolean filter) { + this.walker = walker; + this.filter = filter; + } + + /** + * Perform stackwalk without keeping local variables alive and return an + * array of the collected StackFrames + */ + private synchronized StackFrame[] testLocals() { + // Unused local variables will become dead + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + if (filter) { + return walker.walk(s -> s.filter(f -> TEST_METHODS.contains(f + .getMethodName())).collect(Collectors.toList())) + .toArray(new StackFrame[0]); + } else { + return walker.walk(s -> s.collect(Collectors.toList())) + .toArray(new StackFrame[0]); + } + } + + /** + * Perform stackwalk, keeping local variables alive, and return a list of + * the collected StackFrames + */ + private synchronized StackFrame[] testLocalsKeepAlive() { + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + List frames; + if (filter) { + frames = walker.walk(s -> s.filter(f -> TEST_METHODS.contains(f + .getMethodName())).collect(Collectors.toList())); + } else { + frames = walker.walk(s -> s.collect(Collectors.toList())); + } + + // Use local variables so they stay alive + System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d); + return frames.toArray(new StackFrame[0]); // FIXME: convert to Array here + } + + // Expected values for locals in testLocals() & testLocalsKeepAlive() + // TODO: use real values instead of Strings, rebuild doubles & floats, etc + private final static String[] LOCAL_VALUES = new String[] { + null, // skip, LocalsAndOperands$Tester@XXX identity is different each run + "10", + "122", + "himom", + "0", + null, // skip, fix in 8156073 + null, // skip, fix in 8156073 + null, // skip, fix in 8156073 + "0" + }; + + // Expected types for locals in testLocals() & testLocalsKeepAlive() + // TODO: use real types + private final static String[] LOCAL_TYPES = new String[] { + null, // skip + "I", + "I", + "java.lang.String", + "I", + "I", + "I", + "I", + "I" + }; + + final static Map NUM_LOCALS = Map.of("testLocals", 8, + "testLocalsKeepAlive", + LOCAL_VALUES.length); + private final static Collection TEST_METHODS = NUM_LOCALS.keySet(); + } + + /** + * Print stack trace with locals + */ + public static void dumpStackWithLocals(StackFrame...frames) { + Arrays.stream(frames).forEach(LocalsAndOperands::printLocals); + } + + /** + * Print the StackFrame and an indexed list of its locals + */ + public static void printLocals(StackWalker.StackFrame frame) { + try { + System.out.println(frame); + Object[] locals = (Object[]) getLocals.invoke(frame); + for (int i = 0; i < locals.length; i++) { + System.out.format(" local %d: %s type %s\n", i, locals[i], type(locals[i])); + } + + Object[] operands = (Object[]) getOperands.invoke(frame); + for (int i = 0; i < operands.length; i++) { + System.out.format(" operand %d: %s type %s%n", i, operands[i], + type(operands[i])); + } + + Object[] monitors = (Object[]) getMonitors.invoke(frame); + for (int i = 0; i < monitors.length; i++) { + System.out.format(" monitor %d: %s%n", i, monitors[i]); + } + } catch (Exception e) { throw new RuntimeException(e); } + } + + private static String type(Object o) { + try { + if (o == null) { + return "null"; + } else if (primitiveValueClass.isInstance(o)) { + char c = (char)primitiveType.invoke(o); + return String.valueOf(c); + } else { + return o.getClass().getName(); + } + } catch(Exception e) { throw new RuntimeException(e); } } } diff --git a/jdk/test/java/lang/StackWalker/LocalsCrash.java b/jdk/test/java/lang/StackWalker/LocalsCrash.java new file mode 100644 index 00000000000..b50dd263f00 --- /dev/null +++ b/jdk/test/java/lang/StackWalker/LocalsCrash.java @@ -0,0 +1,74 @@ +/* + * 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 8147039 + * @summary Test for -Xcomp crash that happened before 8147039 fix + * @run testng/othervm -Xcomp LocalsCrash + */ + +import org.testng.annotations.*; +import java.lang.reflect.*; +import java.util.List; +import java.util.stream.Collectors; + +public class LocalsCrash { + static Class liveStackFrameClass; + static Method getStackWalker; + + static { + try { + liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); + getStackWalker = liveStackFrameClass.getMethod("getStackWalker"); + getStackWalker.setAccessible(true); + } catch (Throwable t) { throw new RuntimeException(t); } + } + + private StackWalker walker; + + LocalsCrash() { + try { + walker = (StackWalker) getStackWalker.invoke(null); + } catch (Exception e) { throw new RuntimeException(e); } + } + + @Test + public void test00() { doStackWalk(); } + + @Test + public void test01() { doStackWalk(); } + + private synchronized List doStackWalk() { + try { + // Unused local variables will become dead + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + return walker.walk(s -> s.collect(Collectors.toList())); + } catch (Exception e) { throw new RuntimeException(e); } + } +} diff --git a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java index 7d5c978b59f..829fb17b756 100644 --- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java +++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java @@ -202,7 +202,7 @@ public class VerifyStackTrace { // synthetic frames introduced by lambdas & method handles return produced.replaceAll(":[1-9][0-9]*\\)", ":00)") .replaceAll("-internal/", "/").replaceAll("-ea/", "/") - .replaceAll("java.base@[0-9]+/", "java.base/") + .replaceAll("java.base@(\\d+\\.){0,3}(\\d+)/", "java.base/") .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run") .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke") .replaceAll("\\$[0-9]+", "\\$??"); diff --git a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh index f5bb3b83179..b428a59bb28 100644 --- a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh +++ b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh @@ -80,5 +80,5 @@ $JAR ${TESTTOOLVMOPTS} -cfm "${TESTCLASSES}"/ClassUnloadTest.jar "${MANIFEST}" \ # Finally we run the test (cd "${TESTCLASSES}"; \ - $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:classunload \ + $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:class+unload \ -javaagent:ClassUnloadTest.jar ClassUnloadTest "${OTHERDIR}" Bar.jar) diff --git a/jdk/test/java/lang/invoke/ArrayLengthTest.java b/jdk/test/java/lang/invoke/ArrayLengthTest.java new file mode 100644 index 00000000000..3eabf9789c2 --- /dev/null +++ b/jdk/test/java/lang/invoke/ArrayLengthTest.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +/* @test + * @run testng/othervm -ea -esa test.java.lang.invoke.ArrayLengthTest + */ +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +public class ArrayLengthTest { + + @DataProvider + Object[][] arrayClasses() { + return new Object[][] { + {int[].class}, + {long[].class}, + {float[].class}, + {double[].class}, + {boolean[].class}, + {byte[].class}, + {short[].class}, + {char[].class}, + {Object[].class}, + {StringBuffer[].class} + }; + } + + @Test(dataProvider = "arrayClasses") + public void testArrayLength(Class arrayClass) throws Throwable { + MethodHandle arrayLength = MethodHandles.arrayLength(arrayClass); + assertEquals(int.class, arrayLength.type().returnType()); + assertEquals(arrayClass, arrayLength.type().parameterType(0)); + Object array = MethodHandles.arrayConstructor(arrayClass).invoke(10); + assertEquals(10, arrayLength.invoke(array)); + } + + @Test(dataProvider = "arrayClasses", expectedExceptions = NullPointerException.class) + public void testArrayLengthInvokeNPE(Class arrayClass) throws Throwable { + MethodHandle arrayLength = MethodHandles.arrayLength(arrayClass); + arrayLength.invoke(null); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testArrayLengthNoArray() { + MethodHandles.arrayLength(String.class); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testArrayLengthNPE() { + MethodHandles.arrayLength(null); + } + +} diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java index 59737dbeb7b..b8cbc17784d 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java @@ -40,6 +40,7 @@ import static org.testng.Assert.*; abstract class VarHandleBaseTest { static final int ITERS = Integer.getInteger("iters", 1); + static final int WEAK_ATTEMPTS = Integer.getInteger("weakAttempts", 10); interface ThrowingRunnable { void run() throws Throwable; @@ -211,7 +212,6 @@ abstract class VarHandleBaseTest { } static MethodHandle findVirtual(VarHandle vh, TestAccessMode tam, MethodType mt) { - mt = vh.accessModeType(tam.toAccessMode()); MethodHandle mh; try { mh = MethodHandles.publicLookup(). @@ -221,36 +221,26 @@ abstract class VarHandleBaseTest { } catch (Exception e) { throw new RuntimeException(e); } - return bind(vh, tam, mh, mt); + return bind(vh, mh, mt); } - static MethodHandle varHandleInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) { - mt = vh.accessModeType(tam.toAccessMode()); + static MethodHandle varHandleInvoker(VarHandle vh, TestAccessMode tam, MethodType mt) { MethodHandle mh = MethodHandles.varHandleInvoker( tam.toAccessMode(), mt); - return bind(vh, tam, mh, mt); + return bind(vh, mh, mt); } - static MethodHandle varHandleInvokerWithSymbolicTypeDescriptor(VarHandle vh, TestAccessMode tam, MethodType mt) { - MethodHandle mh = MethodHandles.varHandleInvoker( - tam.toAccessMode(), - mt); - - return bind(vh, tam, mh, mt); - } - - static MethodHandle varHandleExactInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) { - mt = vh.accessModeType(tam.toAccessMode()); + static MethodHandle varHandleExactInvoker(VarHandle vh, TestAccessMode tam, MethodType mt) { MethodHandle mh = MethodHandles.varHandleExactInvoker( tam.toAccessMode(), mt); - return bind(vh, tam, mh, mt); + return bind(vh, mh, mt); } - private static MethodHandle bind(VarHandle vh, TestAccessMode testAccessMode, MethodHandle mh, MethodType emt) { + private static MethodHandle bind(VarHandle vh, MethodHandle mh, MethodType emt) { assertEquals(mh.type(), emt.insertParameterTypes(0, VarHandle.class), "MethodHandle type differs from access mode type"); @@ -268,33 +258,30 @@ abstract class VarHandleBaseTest { enum VarHandleToMethodHandle { VAR_HANDLE_TO_METHOD_HANDLE( "VarHandle.toMethodHandle", + true, VarHandleBaseTest::toMethodHandle), METHOD_HANDLES_LOOKUP_FIND_VIRTUAL( "Lookup.findVirtual", + false, VarHandleBaseTest::findVirtual), - METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_ACCESS_MODE_TYPE( - "MethodHandles.varHandleInvoker(accessModeType)", - VarHandleBaseTest::varHandleInvokerWithAccessModeType), - METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_SYMBOLIC_TYPE_DESCRIPTOR( - "MethodHandles.varHandleInvoker(symbolicTypeDescriptor)", - VarHandleBaseTest::varHandleInvokerWithSymbolicTypeDescriptor), - METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER_WITH_ACCESS_MODE_TYPE( - "MethodHandles.varHandleExactInvoker(accessModeType)", - VarHandleBaseTest::varHandleExactInvokerWithAccessModeType); + METHOD_HANDLES_VAR_HANDLE_INVOKER( + "MethodHandles.varHandleInvoker", + false, + VarHandleBaseTest::varHandleInvoker), + METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER( + "MethodHandles.varHandleExactInvoker", + true, + VarHandleBaseTest::varHandleExactInvoker); final String desc; + final boolean isExact; final TriFunction f; - final boolean exact; - VarHandleToMethodHandle(String desc, TriFunction f) { - this(desc, f, false); - } - - VarHandleToMethodHandle(String desc, TriFunction f, - boolean exact) { + VarHandleToMethodHandle(String desc, boolean isExact, + TriFunction f) { this.desc = desc; this.f = f; - this.exact = exact; + this.isExact = isExact; } MethodHandle apply(VarHandle vh, TestAccessMode am, MethodType mt) { @@ -363,6 +350,15 @@ abstract class VarHandleBaseTest { return amToHandle.computeIfAbsent( amt, k -> f.apply(vh, am, mt)); } + + Class getWMTEOOrOther(Class c) { + return f.isExact ? WrongMethodTypeException.class : c; + } + + void checkWMTEOrCCE(ThrowingRunnable r) { + checkWithThrowable(getWMTEOOrOther(ClassCastException.class), null, r); + } + } interface AccessTestAction { @@ -475,4 +471,4 @@ abstract class VarHandleBaseTest { assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType()); } } -} \ No newline at end of file +} diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java index 021091484e6..9a02753d945 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java @@ -292,6 +292,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, true, false); }); + checkUOE(() -> { + boolean r = (boolean) vh.getAndSet(recv, true); + }); + checkUOE(() -> { boolean o = (boolean) vh.getAndAdd(recv, true); }); @@ -378,6 +382,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(true, false); }); + checkUOE(() -> { + boolean r = (boolean) vh.getAndSet(true); + }); + checkUOE(() -> { boolean o = (boolean) vh.getAndAdd(true); }); @@ -454,6 +462,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, true, false); }); + checkUOE(() -> { + boolean r = (boolean) vh.getAndSet(recv, true); + }); + checkUOE(() -> { boolean o = (boolean) vh.getAndAdd(recv, true); }); @@ -530,6 +542,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(true, false); }); + checkUOE(() -> { + boolean r = (boolean) vh.getAndSet(true); + }); + checkUOE(() -> { boolean o = (boolean) vh.getAndAdd(true); }); @@ -613,6 +629,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(array, i, true, false); }); + checkUOE(() -> { + boolean r = (boolean) vh.getAndSet(array, i, true); + }); + checkUOE(() -> { boolean o = (boolean) vh.getAndAdd(array, i, true); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java index e550815156c..17544907e8d 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java @@ -292,6 +292,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2); }); + checkUOE(() -> { + byte r = (byte) vh.getAndSet(recv, (byte)1); + }); + checkUOE(() -> { byte o = (byte) vh.getAndAdd(recv, (byte)1); }); @@ -378,6 +382,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2); }); + checkUOE(() -> { + byte r = (byte) vh.getAndSet((byte)1); + }); + checkUOE(() -> { byte o = (byte) vh.getAndAdd((byte)1); }); @@ -454,6 +462,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2); }); + checkUOE(() -> { + byte r = (byte) vh.getAndSet(recv, (byte)1); + }); + checkUOE(() -> { byte o = (byte) vh.getAndAdd(recv, (byte)1); }); @@ -530,6 +542,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2); }); + checkUOE(() -> { + byte r = (byte) vh.getAndSet((byte)1); + }); + checkUOE(() -> { byte o = (byte) vh.getAndAdd((byte)1); }); @@ -613,6 +629,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(array, i, (byte)1, (byte)2); }); + checkUOE(() -> { + byte r = (byte) vh.getAndSet(array, i, (byte)1); + }); + checkUOE(() -> { byte o = (byte) vh.getAndAdd(array, i, (byte)1); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java index 5c13c6d6677..88bad8475cb 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java @@ -292,6 +292,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b'); }); + checkUOE(() -> { + char r = (char) vh.getAndSet(recv, 'a'); + }); + checkUOE(() -> { char o = (char) vh.getAndAdd(recv, 'a'); }); @@ -378,6 +382,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease('a', 'b'); }); + checkUOE(() -> { + char r = (char) vh.getAndSet('a'); + }); + checkUOE(() -> { char o = (char) vh.getAndAdd('a'); }); @@ -454,6 +462,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b'); }); + checkUOE(() -> { + char r = (char) vh.getAndSet(recv, 'a'); + }); + checkUOE(() -> { char o = (char) vh.getAndAdd(recv, 'a'); }); @@ -530,6 +542,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease('a', 'b'); }); + checkUOE(() -> { + char r = (char) vh.getAndSet('a'); + }); + checkUOE(() -> { char o = (char) vh.getAndAdd('a'); }); @@ -613,6 +629,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(array, i, 'a', 'b'); }); + checkUOE(() -> { + char r = (char) vh.getAndSet(array, i, 'a'); + }); + checkUOE(() -> { char o = (char) vh.getAndAdd(array, i, 'a'); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java index 65125e3f62e..1861e5919dc 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java @@ -292,6 +292,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d); }); + checkUOE(() -> { + double r = (double) vh.getAndSet(recv, 1.0d); + }); + checkUOE(() -> { double o = (double) vh.getAndAdd(recv, 1.0d); }); @@ -378,6 +382,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d); }); + checkUOE(() -> { + double r = (double) vh.getAndSet(1.0d); + }); + checkUOE(() -> { double o = (double) vh.getAndAdd(1.0d); }); @@ -454,6 +462,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d); }); + checkUOE(() -> { + double r = (double) vh.getAndSet(recv, 1.0d); + }); + checkUOE(() -> { double o = (double) vh.getAndAdd(recv, 1.0d); }); @@ -530,6 +542,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d); }); + checkUOE(() -> { + double r = (double) vh.getAndSet(1.0d); + }); + checkUOE(() -> { double o = (double) vh.getAndAdd(1.0d); }); @@ -613,6 +629,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(array, i, 1.0d, 2.0d); }); + checkUOE(() -> { + double r = (double) vh.getAndSet(array, i, 1.0d); + }); + checkUOE(() -> { double o = (double) vh.getAndAdd(array, i, 1.0d); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java index 8e7491ad45a..dce87f72755 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java @@ -292,6 +292,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f); }); + checkUOE(() -> { + float r = (float) vh.getAndSet(recv, 1.0f); + }); + checkUOE(() -> { float o = (float) vh.getAndAdd(recv, 1.0f); }); @@ -378,6 +382,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(1.0f, 2.0f); }); + checkUOE(() -> { + float r = (float) vh.getAndSet(1.0f); + }); + checkUOE(() -> { float o = (float) vh.getAndAdd(1.0f); }); @@ -454,6 +462,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f); }); + checkUOE(() -> { + float r = (float) vh.getAndSet(recv, 1.0f); + }); + checkUOE(() -> { float o = (float) vh.getAndAdd(recv, 1.0f); }); @@ -530,6 +542,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(1.0f, 2.0f); }); + checkUOE(() -> { + float r = (float) vh.getAndSet(1.0f); + }); + checkUOE(() -> { float o = (float) vh.getAndAdd(1.0f); }); @@ -613,6 +629,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(array, i, 1.0f, 2.0f); }); + checkUOE(() -> { + float r = (float) vh.getAndSet(array, i, 1.0f); + }); + checkUOE(() -> { float o = (float) vh.getAndAdd(array, i, 1.0f); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java index bfcb5feec4c..1897821dc06 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java @@ -402,29 +402,41 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(recv, 1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, 1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(recv); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = vh.weakCompareAndSetAcquire(recv, 2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(recv); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = vh.weakCompareAndSetRelease(recv, 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, 1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(recv); assertEquals(x, 2, "weakCompareAndSetRelease int"); } { - boolean r = vh.weakCompareAndSetVolatile(recv, 2, 1); - assertEquals(r, true, "weakCompareAndSetVolatile int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetVolatile(recv, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetVolatile int"); int x = (int) vh.get(recv); assertEquals(x, 1, "weakCompareAndSetVolatile int value"); } @@ -543,36 +555,48 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSet(1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = (boolean) vh.weakCompareAndSetAcquire(2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = (boolean) vh.weakCompareAndSetRelease(1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(); assertEquals(x, 2, "weakCompareAndSetRelease int"); } { - boolean r = (boolean) vh.weakCompareAndSetVolatile(2, 1); - assertEquals(r, true, "weakCompareAndSetVolatile int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(2, 1); + } + assertEquals(success, true, "weakCompareAndSetVolatile int"); int x = (int) vh.get(); - assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + assertEquals(x, 1, "weakCompareAndSetVolatile int"); } // Compare set and get { - int o = (int) vh.getAndSet( 2); + int o = (int) vh.getAndSet(2); assertEquals(o, 1, "getAndSet int"); int x = (int) vh.get(); assertEquals(x, 2, "getAndSet int value"); @@ -687,31 +711,43 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(array, i, 1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, 1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(array, i); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, 2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, 1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); assertEquals(x, 2, "weakCompareAndSetRelease int"); } { - boolean r = vh.weakCompareAndSetVolatile(array, i, 2, 1); - assertEquals(r, true, "weakCompareAndSetVolatile int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetVolatile(array, i, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetVolatile int"); int x = (int) vh.get(array, i); - assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + assertEquals(x, 1, "weakCompareAndSetVolatile int"); } // Compare set and get diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java index 1f02bed9045..adea5ed82a1 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java @@ -402,29 +402,41 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(recv, 1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(recv); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = vh.weakCompareAndSetAcquire(recv, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(recv); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = vh.weakCompareAndSetRelease(recv, 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(recv); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } { - boolean r = vh.weakCompareAndSetVolatile(recv, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetVolatile long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetVolatile(recv, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetVolatile long"); long x = (long) vh.get(recv); assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); } @@ -543,36 +555,48 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSet(1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = (boolean) vh.weakCompareAndSetAcquire(2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = (boolean) vh.weakCompareAndSetRelease(1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } { - boolean r = (boolean) vh.weakCompareAndSetVolatile(2L, 1L); - assertEquals(r, true, "weakCompareAndSetVolatile long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetVolatile long"); long x = (long) vh.get(); - assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + assertEquals(x, 1L, "weakCompareAndSetVolatile long"); } // Compare set and get { - long o = (long) vh.getAndSet( 2L); + long o = (long) vh.getAndSet(2L); assertEquals(o, 1L, "getAndSet long"); long x = (long) vh.get(); assertEquals(x, 2L, "getAndSet long value"); @@ -687,31 +711,43 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(array, i, 1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(array, i); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } { - boolean r = vh.weakCompareAndSetVolatile(array, i, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetVolatile long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetVolatile(array, i, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetVolatile long"); long x = (long) vh.get(array, i); - assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + assertEquals(x, 1L, "weakCompareAndSetVolatile long"); } // Compare set and get diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java index 822252f7a7d..a8091a838cb 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java @@ -292,6 +292,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, (short)1, (short)2); }); + checkUOE(() -> { + short r = (short) vh.getAndSet(recv, (short)1); + }); + checkUOE(() -> { short o = (short) vh.getAndAdd(recv, (short)1); }); @@ -378,6 +382,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease((short)1, (short)2); }); + checkUOE(() -> { + short r = (short) vh.getAndSet((short)1); + }); + checkUOE(() -> { short o = (short) vh.getAndAdd((short)1); }); @@ -454,6 +462,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(recv, (short)1, (short)2); }); + checkUOE(() -> { + short r = (short) vh.getAndSet(recv, (short)1); + }); + checkUOE(() -> { short o = (short) vh.getAndAdd(recv, (short)1); }); @@ -530,6 +542,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease((short)1, (short)2); }); + checkUOE(() -> { + short r = (short) vh.getAndSet((short)1); + }); + checkUOE(() -> { short o = (short) vh.getAndAdd((short)1); }); @@ -613,6 +629,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSetRelease(array, i, (short)1, (short)2); }); + checkUOE(() -> { + short r = (short) vh.getAndSet(array, i, (short)1); + }); + checkUOE(() -> { short o = (short) vh.getAndAdd(array, i, (short)1); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java index 9e4ec77768b..405206ef22c 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java @@ -416,29 +416,41 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(recv, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) vh.get(recv); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = vh.weakCompareAndSetAcquire(recv, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) vh.get(recv); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = vh.weakCompareAndSetRelease(recv, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) vh.get(recv); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } { - boolean r = vh.weakCompareAndSetVolatile(recv, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetVolatile String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetVolatile(recv, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetVolatile String"); String x = (String) vh.get(recv); assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); } @@ -555,36 +567,48 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSet("foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet("foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) vh.get(); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = (boolean) vh.weakCompareAndSetAcquire("bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire("bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) vh.get(); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = (boolean) vh.weakCompareAndSetRelease("foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease("foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) vh.get(); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } { - boolean r = (boolean) vh.weakCompareAndSetVolatile("bar", "foo"); - assertEquals(r, true, "weakCompareAndSetVolatile String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease("bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetVolatile String"); String x = (String) vh.get(); - assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + assertEquals(x, "foo", "weakCompareAndSetVolatile String"); } // Compare set and get { - String o = (String) vh.getAndSet( "bar"); + String o = (String) vh.getAndSet("bar"); assertEquals(o, "foo", "getAndSet String"); String x = (String) vh.get(); assertEquals(x, "bar", "getAndSet String value"); @@ -697,31 +721,43 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(array, i, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) vh.get(array, i); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) vh.get(array, i); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) vh.get(array, i); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } { - boolean r = vh.weakCompareAndSetVolatile(array, i, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetVolatile String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetVolatile(array, i, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetVolatile String"); String x = (String) vh.get(array, i); - assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + assertEquals(x, "foo", "weakCompareAndSetVolatile String"); } // Compare set and get diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java index 8159e16ff62..8038315e391 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java @@ -50,7 +50,7 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { static final char VALUE_2 = (char)0x1112; - static final char VALUE_3 = (char)0x2122; + static final char VALUE_3 = (char)0xFFFE; @Override @@ -253,6 +253,10 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { checkROBE(() -> { vh.setOpaque(array, ci, VALUE_1); }); + checkUOE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { char r = (char) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java index a327b00fb77..53db9cd239b 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java @@ -50,7 +50,7 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { static final double VALUE_2 = 0x1112131415161718L; - static final double VALUE_3 = 0x2122232425262728L; + static final double VALUE_3 = 0xFFFEFDFCFBFAF9F8L; @Override @@ -254,9 +254,7 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { checkROBE(() -> { double o = (double) vh.getAndSet(array, ci, VALUE_1); }); - checkUOE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkUOE(() -> { double o = (double) vh.getAndAdd(array, ci, VALUE_1); @@ -700,22 +698,31 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet double value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease double"); } @@ -840,22 +847,31 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet double value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease double"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java index 196c8101723..d2688cf925a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java @@ -50,7 +50,7 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { static final float VALUE_2 = 0x11121314; - static final float VALUE_3 = 0x21222324; + static final float VALUE_3 = 0xFFFEFDFC; @Override @@ -254,9 +254,7 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { checkROBE(() -> { float o = (float) vh.getAndSet(array, ci, VALUE_1); }); - checkUOE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkUOE(() -> { float o = (float) vh.getAndAdd(array, ci, VALUE_1); @@ -700,22 +698,31 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet float value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease float"); } @@ -840,22 +847,31 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet float value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease float"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java index 400c20605c5..9e47532c20b 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java @@ -50,7 +50,7 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { static final int VALUE_2 = 0x11121314; - static final int VALUE_3 = 0x21222324; + static final int VALUE_3 = 0xFFFEFDFC; @Override @@ -247,9 +247,7 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { checkROBE(() -> { int o = (int) vh.getAndSet(array, ci, VALUE_1); }); - checkUOE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkROBE(() -> { int o = (int) vh.getAndAdd(array, ci, VALUE_1); @@ -714,22 +712,31 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet int value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease int"); } @@ -863,22 +870,31 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet int value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease int"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java index a0cabc8653a..f9ed92f0e07 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java @@ -50,7 +50,7 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { static final long VALUE_2 = 0x1112131415161718L; - static final long VALUE_3 = 0x2122232425262728L; + static final long VALUE_3 = 0xFFFEFDFCFBFAF9F8L; @Override @@ -247,9 +247,7 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { checkROBE(() -> { long o = (long) vh.getAndSet(array, ci, VALUE_1); }); - checkUOE(() -> { - boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); - }); + checkROBE(() -> { long o = (long) vh.getAndAdd(array, ci, VALUE_1); @@ -714,22 +712,31 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet long value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease long"); } @@ -863,22 +870,31 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet long value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease long"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java index 2632b00bd23..0a9aa6e871c 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java @@ -50,7 +50,7 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { static final short VALUE_2 = (short)0x1112; - static final short VALUE_3 = (short)0x2122; + static final short VALUE_3 = (short)0xFFFE; @Override @@ -253,6 +253,10 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { checkROBE(() -> { vh.setOpaque(array, ci, VALUE_1); }); + checkUOE(() -> { + boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java index 8ccf7983056..00f78a57159 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java @@ -208,31 +208,43 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 2, "weakCompareAndSetRelease int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2, 1); - assertEquals(r, true, "weakCompareAndSetVolatile int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetVolatile int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + assertEquals(x, 1, "weakCompareAndSetVolatile int"); } // Compare set and get @@ -349,36 +361,48 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2, "weakCompareAndSetRelease int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2, 1); - assertEquals(r, true, "weakCompareAndSetVolatile int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2, 1); + } + assertEquals(success, true, "weakCompareAndSetVolatile int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + assertEquals(x, 1, "weakCompareAndSetVolatile int"); } // Compare set and get { - int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2); + int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 2); assertEquals(o, 1, "getAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2, "getAndSet int value"); @@ -493,31 +517,43 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 2, "weakCompareAndSetRelease int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2, 1); - assertEquals(r, true, "weakCompareAndSetVolatile int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetVolatile int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + assertEquals(x, 1, "weakCompareAndSetVolatile int"); } // Compare set and get diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java index 65493ec2b49..2bb8b9a1ee8 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java @@ -208,31 +208,43 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetVolatile long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetVolatile long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + assertEquals(x, 1L, "weakCompareAndSetVolatile long"); } // Compare set and get @@ -349,36 +361,48 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2L, 1L); - assertEquals(r, true, "weakCompareAndSetVolatile long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetVolatile long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + assertEquals(x, 1L, "weakCompareAndSetVolatile long"); } // Compare set and get { - long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2L); + long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 2L); assertEquals(o, 1L, "getAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2L, "getAndSet long value"); @@ -493,31 +517,43 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetVolatile long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetVolatile long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + assertEquals(x, 1L, "weakCompareAndSetVolatile long"); } // Compare set and get diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java index 5ae7c877854..dc6f8ec1861 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java @@ -208,31 +208,43 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetVolatile String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetVolatile String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + assertEquals(x, "foo", "weakCompareAndSetVolatile String"); } // Compare set and get @@ -345,36 +357,48 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact("bar", "foo"); - assertEquals(r, true, "weakCompareAndSetVolatile String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact("bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetVolatile String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + assertEquals(x, "foo", "weakCompareAndSetVolatile String"); } // Compare set and get { - String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact("bar"); + String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact( "bar"); assertEquals(o, "foo", "getAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, "bar", "getAndSet String value"); @@ -485,31 +509,43 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetVolatile String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetVolatile String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + assertEquals(x, "foo", "weakCompareAndSetVolatile String"); } // Compare set and get diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java index 75ba7ae3dc2..df680146374 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeBoolean * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeBoolean */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType, false)); } @@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean x = (boolean) hs.get(am, methodType(boolean.class, Void.class)). - invoke(null); + boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class)). + invokeExact((VarHandleTestMethodTypeBoolean) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type checkWMTE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class)). - invoke(recv); + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeBoolean.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeBoolean.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, boolean.class)). - invoke(null, true); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, boolean.class)). + invokeExact((VarHandleTestMethodTypeBoolean) null, true); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, boolean.class)). - invoke(Void.class, true); + invokeExact(Void.class, true); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, boolean.class)). - invoke(0, true); + invokeExact(0, true); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, boolean.class, Class.class)). - invoke(recv, true, Void.class); + invokeExact(recv, true, Void.class); }); } @@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest { // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > boolean x = (boolean) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, boolean.class, Class.class)). - invoke(true, Void.class); + invokeExact(true, Void.class); }); } @@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - boolean x = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class)). - invoke(null, 0); + boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class)). + invokeExact((boolean[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, boolean[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class int x = (int) hs.get(am, methodType(int.class, boolean[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, boolean.class)). - invoke(null, 0, true); + hs.get(am, methodType(void.class, boolean[].class, int.class, boolean.class)). + invokeExact((boolean[]) null, 0, true); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, boolean.class)). - invoke(Void.class, 0, true); + invokeExact(Void.class, 0, true); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, boolean.class)). - invoke(0, 0, true); + invokeExact(0, 0, true); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, boolean[].class, Class.class, boolean.class)). - invoke(array, Void.class, true); + invokeExact(array, Void.class, true); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)). - invoke(array, 0, true, Void.class); + invokeExact(array, 0, true, Void.class); }); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java index b212bfc9d7d..0bfddc7ad27 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeByte * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeByte */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeByte::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeByte::testArrayWrongMethodType, false)); } @@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - byte x = (byte) hs.get(am, methodType(byte.class, Void.class)). - invoke(null); + byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class)). + invokeExact((VarHandleTestMethodTypeByte) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class byte x = (byte) hs.get(am, methodType(byte.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class byte x = (byte) hs.get(am, methodType(byte.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type checkWMTE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class)). - invoke(recv); + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeByte.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 byte x = (byte) hs.get(am, methodType(byte.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, byte.class)). - invoke(null, (byte)1); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, byte.class)). + invokeExact((VarHandleTestMethodTypeByte) null, (byte)1); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, byte.class)). - invoke(Void.class, (byte)1); + invokeExact(Void.class, (byte)1); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, byte.class)). - invoke(0, (byte)1); + invokeExact(0, (byte)1); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, byte.class, Class.class)). - invoke(recv, (byte)1, Void.class); + invokeExact(recv, (byte)1, Void.class); }); } @@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest { // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > byte x = (byte) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, byte.class, Class.class)). - invoke((byte)1, Void.class); + invokeExact((byte)1, Void.class); }); } @@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - byte x = (byte) hs.get(am, methodType(byte.class, Void.class, int.class)). - invoke(null, 0); + byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class)). + invokeExact((byte[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 byte x = (byte) hs.get(am, methodType(byte.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, byte.class)). - invoke(null, 0, (byte)1); + hs.get(am, methodType(void.class, byte[].class, int.class, byte.class)). + invokeExact((byte[]) null, 0, (byte)1); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, byte.class)). - invoke(Void.class, 0, (byte)1); + invokeExact(Void.class, 0, (byte)1); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, byte.class)). - invoke(0, 0, (byte)1); + invokeExact(0, 0, (byte)1); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, byte[].class, Class.class, byte.class)). - invoke(array, Void.class, (byte)1); + invokeExact(array, Void.class, (byte)1); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)). - invoke(array, 0, (byte)1, Void.class); + invokeExact(array, 0, (byte)1, Void.class); }); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java index 6ac8a0fed70..8d5166d8644 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeChar * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeChar */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeChar::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeChar::testArrayWrongMethodType, false)); } @@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - char x = (char) hs.get(am, methodType(char.class, Void.class)). - invoke(null); + char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class)). + invokeExact((VarHandleTestMethodTypeChar) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class char x = (char) hs.get(am, methodType(char.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class char x = (char) hs.get(am, methodType(char.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type checkWMTE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class)). - invoke(recv); + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeChar.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 char x = (char) hs.get(am, methodType(char.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, char.class)). - invoke(null, 'a'); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, char.class)). + invokeExact((VarHandleTestMethodTypeChar) null, 'a'); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, char.class)). - invoke(Void.class, 'a'); + invokeExact(Void.class, 'a'); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, char.class)). - invoke(0, 'a'); + invokeExact(0, 'a'); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, char.class, Class.class)). - invoke(recv, 'a', Void.class); + invokeExact(recv, 'a', Void.class); }); } @@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest { // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > char x = (char) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, char.class, Class.class)). - invoke('a', Void.class); + invokeExact('a', Void.class); }); } @@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - char x = (char) hs.get(am, methodType(char.class, Void.class, int.class)). - invoke(null, 0); + char x = (char) hs.get(am, methodType(char.class, char[].class, int.class)). + invokeExact((char[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class char x = (char) hs.get(am, methodType(char.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class char x = (char) hs.get(am, methodType(char.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, char[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 char x = (char) hs.get(am, methodType(char.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, char.class)). - invoke(null, 0, 'a'); + hs.get(am, methodType(void.class, char[].class, int.class, char.class)). + invokeExact((char[]) null, 0, 'a'); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, char.class)). - invoke(Void.class, 0, 'a'); + invokeExact(Void.class, 0, 'a'); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, char[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, char.class)). - invoke(0, 0, 'a'); + invokeExact(0, 0, 'a'); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, char[].class, Class.class, char.class)). - invoke(array, Void.class, 'a'); + invokeExact(array, Void.class, 'a'); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, char[].class, int.class, Class.class)). - invoke(array, 0, 'a', Void.class); + invokeExact(array, 0, 'a', Void.class); }); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java index e5fc073d191..f3531016262 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeDouble * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeDouble */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeDouble::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeDouble::testArrayWrongMethodType, false)); } @@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - double x = (double) hs.get(am, methodType(double.class, Void.class)). - invoke(null); + double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class)). + invokeExact((VarHandleTestMethodTypeDouble) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class double x = (double) hs.get(am, methodType(double.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class double x = (double) hs.get(am, methodType(double.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type checkWMTE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class)). - invoke(recv); + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeDouble.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 double x = (double) hs.get(am, methodType(double.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, double.class)). - invoke(null, 1.0d); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, double.class)). + invokeExact((VarHandleTestMethodTypeDouble) null, 1.0d); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, double.class)). - invoke(Void.class, 1.0d); + invokeExact(Void.class, 1.0d); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, double.class)). - invoke(0, 1.0d); + invokeExact(0, 1.0d); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, double.class, Class.class)). - invoke(recv, 1.0d, Void.class); + invokeExact(recv, 1.0d, Void.class); }); } @@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest { // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > double x = (double) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, double.class, Class.class)). - invoke(1.0d, Void.class); + invokeExact(1.0d, Void.class); }); } @@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - double x = (double) hs.get(am, methodType(double.class, Void.class, int.class)). - invoke(null, 0); + double x = (double) hs.get(am, methodType(double.class, double[].class, int.class)). + invokeExact((double[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class double x = (double) hs.get(am, methodType(double.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class double x = (double) hs.get(am, methodType(double.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class double x = (double) hs.get(am, methodType(double.class, double[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, double[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 double x = (double) hs.get(am, methodType(double.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, double.class)). - invoke(null, 0, 1.0d); + hs.get(am, methodType(void.class, double[].class, int.class, double.class)). + invokeExact((double[]) null, 0, 1.0d); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, double.class)). - invoke(Void.class, 0, 1.0d); + invokeExact(Void.class, 0, 1.0d); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, double[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, double.class)). - invoke(0, 0, 1.0d); + invokeExact(0, 0, 1.0d); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, double[].class, Class.class, double.class)). - invoke(array, Void.class, 1.0d); + invokeExact(array, Void.class, 1.0d); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, double[].class, int.class, Class.class)). - invoke(array, 0, 1.0d, Void.class); + invokeExact(array, 0, 1.0d, Void.class); }); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java index c1bee039b73..b07049d64b0 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeFloat * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeFloat */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeFloat::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeFloat::testArrayWrongMethodType, false)); } @@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - float x = (float) hs.get(am, methodType(float.class, Void.class)). - invoke(null); + float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class)). + invokeExact((VarHandleTestMethodTypeFloat) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class float x = (float) hs.get(am, methodType(float.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class float x = (float) hs.get(am, methodType(float.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type checkWMTE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class)). - invoke(recv); + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeFloat.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 float x = (float) hs.get(am, methodType(float.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, float.class)). - invoke(null, 1.0f); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, float.class)). + invokeExact((VarHandleTestMethodTypeFloat) null, 1.0f); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, float.class)). - invoke(Void.class, 1.0f); + invokeExact(Void.class, 1.0f); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, float.class)). - invoke(0, 1.0f); + invokeExact(0, 1.0f); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, float.class, Class.class)). - invoke(recv, 1.0f, Void.class); + invokeExact(recv, 1.0f, Void.class); }); } @@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest { // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > float x = (float) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, float.class, Class.class)). - invoke(1.0f, Void.class); + invokeExact(1.0f, Void.class); }); } @@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - float x = (float) hs.get(am, methodType(float.class, Void.class, int.class)). - invoke(null, 0); + float x = (float) hs.get(am, methodType(float.class, float[].class, int.class)). + invokeExact((float[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class float x = (float) hs.get(am, methodType(float.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class float x = (float) hs.get(am, methodType(float.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class float x = (float) hs.get(am, methodType(float.class, float[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, float[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 float x = (float) hs.get(am, methodType(float.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, float.class)). - invoke(null, 0, 1.0f); + hs.get(am, methodType(void.class, float[].class, int.class, float.class)). + invokeExact((float[]) null, 0, 1.0f); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, float.class)). - invoke(Void.class, 0, 1.0f); + invokeExact(Void.class, 0, 1.0f); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, float[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, float.class)). - invoke(0, 0, 1.0f); + invokeExact(0, 0, 1.0f); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, float[].class, Class.class, float.class)). - invoke(array, Void.class, 1.0f); + invokeExact(array, Void.class, 1.0f); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, float[].class, int.class, Class.class)). - invoke(array, 0, 1.0f, Void.class); + invokeExact(array, 0, 1.0f, Void.class); }); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java index 13b6b0607b0..67fca94c49a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeInt * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeInt */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeInt::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeInt::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeInt::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeInt::testArrayWrongMethodType, false)); } @@ -644,211 +646,211 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - int x = (int) hs.get(am, methodType(int.class, Void.class)). - invoke(null); + int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class)). + invokeExact((VarHandleTestMethodTypeInt) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class int x = (int) hs.get(am, methodType(int.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class int x = (int) hs.get(am, methodType(int.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type checkWMTE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class)). - invoke(recv); + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, int.class)). - invoke(null, 1); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, int.class)). + invokeExact((VarHandleTestMethodTypeInt) null, 1); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, int.class)). - invoke(Void.class, 1); + invokeExact(Void.class, 1); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class)). - invoke(0, 1); + invokeExact(0, 1); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)). - invoke(recv, 1, Void.class); + invokeExact(recv, 1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, int.class)). - invoke(null, 1, 1); + boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, int.class)). + invokeExact((VarHandleTestMethodTypeInt) null, 1, 1); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, int.class)). - invoke(Void.class, 1, 1); + invokeExact(Void.class, 1, 1); }); checkWMTE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, Class.class, int.class)). - invoke(recv, Void.class, 1); + invokeExact(recv, Void.class, 1); }); checkWMTE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)). - invoke(recv, 1, Void.class); + invokeExact(recv, 1, Void.class); }); checkWMTE(() -> { // receiver primitive class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , int.class, int.class)). - invoke(0, 1, 1); + invokeExact(0, 1, 1); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, int.class, Class.class)). - invoke(recv, 1, 1, Void.class); + invokeExact(recv, 1, 1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { checkNPE(() -> { // null receiver - int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)). - invoke(null, 1, 1); + int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, int.class)). + invokeExact((VarHandleTestMethodTypeInt) null, 1, 1); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)). - invoke(Void.class, 1, 1); + invokeExact(Void.class, 1, 1); }); checkWMTE(() -> { // expected reference class int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class, int.class)). - invoke(recv, Void.class, 1); + invokeExact(recv, Void.class, 1); }); checkWMTE(() -> { // actual reference class int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)). - invoke(recv, 1, Void.class); + invokeExact(recv, 1, Void.class); }); checkWMTE(() -> { // reciever primitive class int x = (int) hs.get(am, methodType(int.class, int.class , int.class, int.class)). - invoke(0, 1, 1); + invokeExact(0, 1, 1); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class , int.class, int.class)). - invoke(recv, 1, 1); + invokeExact(recv, 1, 1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class , int.class, int.class)). - invoke(recv, 1, 1); + invokeExact(recv, 1, 1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, int.class, Class.class)). - invoke(recv, 1, 1, Void.class); + invokeExact(recv, 1, 1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { checkNPE(() -> { // null receiver - int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)). - invoke(null, 1); + int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)). + invokeExact((VarHandleTestMethodTypeInt) null, 1); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)). - invoke(Void.class, 1); + invokeExact(Void.class, 1); }); checkWMTE(() -> { // value reference class int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // reciever primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class)). - invoke(0, 1); + invokeExact(0, 1); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)). - invoke(recv, 1); + invokeExact(recv, 1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)). - invoke(recv, 1); + invokeExact(recv, 1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)). - invoke(recv, 1, Void.class); + invokeExact(recv, 1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { checkNPE(() -> { // null receiver - int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)). - invoke(null, 1); + int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)). + invokeExact((VarHandleTestMethodTypeInt) null, 1); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)). - invoke(Void.class, 1); + invokeExact(Void.class, 1); }); checkWMTE(() -> { // value reference class int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // reciever primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class)). - invoke(0, 1); + invokeExact(0, 1); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)). - invoke(recv, 1); + invokeExact(recv, 1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)). - invoke(recv, 1); + invokeExact(recv, 1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)). - invoke(recv, 1, Void.class); + invokeExact(recv, 1, Void.class); }); } } @@ -1190,52 +1192,52 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, int.class, Class.class)). - invoke(1, Void.class); + invokeExact(1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkWMTE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)). - invoke(Void.class, 1); + invokeExact(Void.class, 1); }); checkWMTE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, Class.class)). - invoke(1, Void.class); + invokeExact(1, Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, Class.class)). - invoke(1, 1, Void.class); + invokeExact(1, 1, Void.class); }); } @@ -1243,29 +1245,29 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { // Incorrect argument types checkWMTE(() -> { // expected reference class int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)). - invoke(Void.class, 1); + invokeExact(Void.class, 1); }); checkWMTE(() -> { // actual reference class int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)). - invoke(1, Void.class); + invokeExact(1, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, int.class, int.class)). - invoke(1, 1); + invokeExact(1, 1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)). - invoke(1, 1); + invokeExact(1, 1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, int.class, int.class, Class.class)). - invoke(1, 1, Void.class); + invokeExact(1, 1, Void.class); }); } @@ -1273,25 +1275,25 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { // Incorrect argument types checkWMTE(() -> { // value reference class int x = (int) hs.get(am, methodType(int.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, int.class)). - invoke(1); + invokeExact(1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)). - invoke(1); + invokeExact(1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)). - invoke(1, Void.class); + invokeExact(1, Void.class); }); } @@ -1299,25 +1301,25 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { // Incorrect argument types checkWMTE(() -> { // value reference class int x = (int) hs.get(am, methodType(int.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, int.class)). - invoke(1); + invokeExact(1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)). - invoke(1); + invokeExact(1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)). - invoke(1, Void.class); + invokeExact(1, Void.class); }); } } @@ -1909,237 +1911,237 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)). - invoke(null, 0); + int x = (int) hs.get(am, methodType(int.class, int[].class, int.class)). + invokeExact((int[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, int[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, int.class)). - invoke(null, 0, 1); + hs.get(am, methodType(void.class, int[].class, int.class, int.class)). + invokeExact((int[]) null, 0, 1); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, int.class)). - invoke(Void.class, 0, 1); + invokeExact(Void.class, 0, 1); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, int[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, int.class)). - invoke(0, 0, 1); + invokeExact(0, 0, 1); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, int[].class, Class.class, int.class)). - invoke(array, Void.class, 1); + invokeExact(array, Void.class, 1); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, int[].class, int.class, Class.class)). - invoke(array, 0, 1, Void.class); + invokeExact(array, 0, 1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, int.class, int.class)). - invoke(null, 0, 1, 1); + boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class)). + invokeExact((int[]) null, 0, 1, 1); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, int.class, int.class)). - invoke(Void.class, 0, 1, 1); + invokeExact(Void.class, 0, 1, 1); }); checkWMTE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, Class.class, int.class)). - invoke(array, 0, Void.class, 1); + invokeExact(array, 0, Void.class, 1); }); checkWMTE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, Class.class)). - invoke(array, 0, 1, Void.class); + invokeExact(array, 0, 1, Void.class); }); checkWMTE(() -> { // receiver primitive class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, int.class, int.class)). - invoke(0, 0, 1, 1); + invokeExact(0, 0, 1, 1); }); checkWMTE(() -> { // index reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, Class.class, int.class, int.class)). - invoke(array, Void.class, 1, 1); + invokeExact(array, Void.class, 1, 1); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class, Class.class)). - invoke(array, 0, 1, 1, Void.class); + invokeExact(array, 0, 1, 1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { // Incorrect argument types checkNPE(() -> { // null receiver - int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class, int.class)). - invoke(null, 0, 1, 1); + int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, int.class)). + invokeExact((int[]) null, 0, 1, 1); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class, int.class)). - invoke(Void.class, 0, 1, 1); + invokeExact(Void.class, 0, 1, 1); }); checkWMTE(() -> { // expected reference class int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class, int.class)). - invoke(array, 0, Void.class, 1); + invokeExact(array, 0, Void.class, 1); }); checkWMTE(() -> { // actual reference class int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)). - invoke(array, 0, 1, Void.class); + invokeExact(array, 0, 1, Void.class); }); checkWMTE(() -> { // array primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class, int.class)). - invoke(0, 0, 1, 1); + invokeExact(0, 0, 1, 1); }); checkWMTE(() -> { // index reference class int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class, int.class)). - invoke(array, Void.class, 1, 1); + invokeExact(array, Void.class, 1, 1); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class, int.class)). - invoke(array, 0, 1, 1); + invokeExact(array, 0, 1, 1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class)). - invoke(array, 0, 1, 1); + invokeExact(array, 0, 1, 1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, int.class, Class.class)). - invoke(array, 0, 1, 1, Void.class); + invokeExact(array, 0, 1, 1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null array - int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)). - invoke(null, 0, 1); + int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class)). + invokeExact((int[]) null, 0, 1); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)). - invoke(Void.class, 0, 1); + invokeExact(Void.class, 0, 1); }); checkWMTE(() -> { // value reference class int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // array primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)). - invoke(0, 0, 1); + invokeExact(0, 0, 1); }); checkWMTE(() -> { // index reference class int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)). - invoke(array, Void.class, 1); + invokeExact(array, Void.class, 1); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)). - invoke(array, 0, 1); + invokeExact(array, 0, 1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)). - invoke(array, 0, 1); + invokeExact(array, 0, 1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)). - invoke(array, 0, 1, Void.class); + invokeExact(array, 0, 1, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { // Incorrect argument types checkNPE(() -> { // null array - int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)). - invoke(null, 0, 1); + int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class)). + invokeExact((int[]) null, 0, 1); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)). - invoke(Void.class, 0, 1); + invokeExact(Void.class, 0, 1); }); checkWMTE(() -> { // value reference class int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // array primitive class int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)). - invoke(0, 0, 1); + invokeExact(0, 0, 1); }); checkWMTE(() -> { // index reference class int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)). - invoke(array, Void.class, 1); + invokeExact(array, Void.class, 1); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)). - invoke(array, 0, 1); + invokeExact(array, 0, 1); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)). - invoke(array, 0, 1); + invokeExact(array, 0, 1); }); // Incorrect arity checkWMTE(() -> { // 0 int x = (int) hs.get(am, methodType(int.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)). - invoke(array, 0, 1, Void.class); + invokeExact(array, 0, 1, Void.class); }); } } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java index 44151683133..0972e663cc7 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeLong * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeLong */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeLong::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeLong::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeLong::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeLong::testArrayWrongMethodType, false)); } @@ -644,211 +646,211 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - long x = (long) hs.get(am, methodType(long.class, Void.class)). - invoke(null); + long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class)). + invokeExact((VarHandleTestMethodTypeLong) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class long x = (long) hs.get(am, methodType(long.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class long x = (long) hs.get(am, methodType(long.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type checkWMTE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class)). - invoke(recv); + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, long.class)). - invoke(null, 1L); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, long.class)). + invokeExact((VarHandleTestMethodTypeLong) null, 1L); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, long.class)). - invoke(Void.class, 1L); + invokeExact(Void.class, 1L); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, long.class)). - invoke(0, 1L); + invokeExact(0, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)). - invoke(recv, 1L, Void.class); + invokeExact(recv, 1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, long.class, long.class)). - invoke(null, 1L, 1L); + boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, long.class)). + invokeExact((VarHandleTestMethodTypeLong) null, 1L, 1L); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, long.class, long.class)). - invoke(Void.class, 1L, 1L); + invokeExact(Void.class, 1L, 1L); }); checkWMTE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, Class.class, long.class)). - invoke(recv, Void.class, 1L); + invokeExact(recv, Void.class, 1L); }); checkWMTE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)). - invoke(recv, 1L, Void.class); + invokeExact(recv, 1L, Void.class); }); checkWMTE(() -> { // receiver primitive class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , long.class, long.class)). - invoke(0, 1L, 1L); + invokeExact(0, 1L, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, long.class, Class.class)). - invoke(recv, 1L, 1L, Void.class); + invokeExact(recv, 1L, 1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { checkNPE(() -> { // null receiver - long x = (long) hs.get(am, methodType(long.class, Void.class, long.class, long.class)). - invoke(null, 1L, 1L); + long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, long.class)). + invokeExact((VarHandleTestMethodTypeLong) null, 1L, 1L); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class long x = (long) hs.get(am, methodType(long.class, Class.class, long.class, long.class)). - invoke(Void.class, 1L, 1L); + invokeExact(Void.class, 1L, 1L); }); checkWMTE(() -> { // expected reference class long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class, long.class)). - invoke(recv, Void.class, 1L); + invokeExact(recv, Void.class, 1L); }); checkWMTE(() -> { // actual reference class long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)). - invoke(recv, 1L, Void.class); + invokeExact(recv, 1L, Void.class); }); checkWMTE(() -> { // reciever primitive class long x = (long) hs.get(am, methodType(long.class, int.class , long.class, long.class)). - invoke(0, 1L, 1L); + invokeExact(0, 1L, 1L); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class , long.class, long.class)). - invoke(recv, 1L, 1L); + invokeExact(recv, 1L, 1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class , long.class, long.class)). - invoke(recv, 1L, 1L); + invokeExact(recv, 1L, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, long.class, Class.class)). - invoke(recv, 1L, 1L, Void.class); + invokeExact(recv, 1L, 1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { checkNPE(() -> { // null receiver - long x = (long) hs.get(am, methodType(long.class, Void.class, long.class)). - invoke(null, 1L); + long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)). + invokeExact((VarHandleTestMethodTypeLong) null, 1L); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)). - invoke(Void.class, 1L); + invokeExact(Void.class, 1L); }); checkWMTE(() -> { // value reference class long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // reciever primitive class long x = (long) hs.get(am, methodType(long.class, int.class, long.class)). - invoke(0, 1L); + invokeExact(0, 1L); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)). - invoke(recv, 1L); + invokeExact(recv, 1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)). - invoke(recv, 1L); + invokeExact(recv, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)). - invoke(recv, 1L, Void.class); + invokeExact(recv, 1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { checkNPE(() -> { // null receiver - long x = (long) hs.get(am, methodType(long.class, Void.class, long.class)). - invoke(null, 1L); + long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)). + invokeExact((VarHandleTestMethodTypeLong) null, 1L); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)). - invoke(Void.class, 1L); + invokeExact(Void.class, 1L); }); checkWMTE(() -> { // value reference class long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // reciever primitive class long x = (long) hs.get(am, methodType(long.class, int.class, long.class)). - invoke(0, 1L); + invokeExact(0, 1L); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)). - invoke(recv, 1L); + invokeExact(recv, 1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)). - invoke(recv, 1L); + invokeExact(recv, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)). - invoke(recv, 1L, Void.class); + invokeExact(recv, 1L, Void.class); }); } } @@ -1190,52 +1192,52 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, long.class, Class.class)). - invoke(1L, Void.class); + invokeExact(1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkWMTE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, long.class)). - invoke(Void.class, 1L); + invokeExact(Void.class, 1L); }); checkWMTE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, long.class, Class.class)). - invoke(1L, Void.class); + invokeExact(1L, Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, long.class, long.class, Class.class)). - invoke(1L, 1L, Void.class); + invokeExact(1L, 1L, Void.class); }); } @@ -1243,29 +1245,29 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { // Incorrect argument types checkWMTE(() -> { // expected reference class long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)). - invoke(Void.class, 1L); + invokeExact(Void.class, 1L); }); checkWMTE(() -> { // actual reference class long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)). - invoke(1L, Void.class); + invokeExact(1L, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, long.class, long.class)). - invoke(1L, 1L); + invokeExact(1L, 1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class, long.class)). - invoke(1L, 1L); + invokeExact(1L, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, long.class, long.class, Class.class)). - invoke(1L, 1L, Void.class); + invokeExact(1L, 1L, Void.class); }); } @@ -1273,25 +1275,25 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { // Incorrect argument types checkWMTE(() -> { // value reference class long x = (long) hs.get(am, methodType(long.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, long.class)). - invoke(1L); + invokeExact(1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)). - invoke(1L); + invokeExact(1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)). - invoke(1L, Void.class); + invokeExact(1L, Void.class); }); } @@ -1299,25 +1301,25 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { // Incorrect argument types checkWMTE(() -> { // value reference class long x = (long) hs.get(am, methodType(long.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, long.class)). - invoke(1L); + invokeExact(1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)). - invoke(1L); + invokeExact(1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)). - invoke(1L, Void.class); + invokeExact(1L, Void.class); }); } } @@ -1909,237 +1911,237 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - long x = (long) hs.get(am, methodType(long.class, Void.class, int.class)). - invoke(null, 0); + long x = (long) hs.get(am, methodType(long.class, long[].class, int.class)). + invokeExact((long[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class long x = (long) hs.get(am, methodType(long.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class long x = (long) hs.get(am, methodType(long.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, long[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, long.class)). - invoke(null, 0, 1L); + hs.get(am, methodType(void.class, long[].class, int.class, long.class)). + invokeExact((long[]) null, 0, 1L); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, long.class)). - invoke(Void.class, 0, 1L); + invokeExact(Void.class, 0, 1L); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, long[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, long.class)). - invoke(0, 0, 1L); + invokeExact(0, 0, 1L); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, long[].class, Class.class, long.class)). - invoke(array, Void.class, 1L); + invokeExact(array, Void.class, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, long[].class, int.class, Class.class)). - invoke(array, 0, 1L, Void.class); + invokeExact(array, 0, 1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, long.class, long.class)). - invoke(null, 0, 1L, 1L); + boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class)). + invokeExact((long[]) null, 0, 1L, 1L); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, long.class, long.class)). - invoke(Void.class, 0, 1L, 1L); + invokeExact(Void.class, 0, 1L, 1L); }); checkWMTE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, Class.class, long.class)). - invoke(array, 0, Void.class, 1L); + invokeExact(array, 0, Void.class, 1L); }); checkWMTE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, Class.class)). - invoke(array, 0, 1L, Void.class); + invokeExact(array, 0, 1L, Void.class); }); checkWMTE(() -> { // receiver primitive class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, long.class, long.class)). - invoke(0, 0, 1L, 1L); + invokeExact(0, 0, 1L, 1L); }); checkWMTE(() -> { // index reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, Class.class, long.class, long.class)). - invoke(array, Void.class, 1L, 1L); + invokeExact(array, Void.class, 1L, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class, Class.class)). - invoke(array, 0, 1L, 1L, Void.class); + invokeExact(array, 0, 1L, 1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { // Incorrect argument types checkNPE(() -> { // null receiver - long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class, long.class)). - invoke(null, 0, 1L, 1L); + long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, long.class)). + invokeExact((long[]) null, 0, 1L, 1L); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class, long.class)). - invoke(Void.class, 0, 1L, 1L); + invokeExact(Void.class, 0, 1L, 1L); }); checkWMTE(() -> { // expected reference class long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class, long.class)). - invoke(array, 0, Void.class, 1L); + invokeExact(array, 0, Void.class, 1L); }); checkWMTE(() -> { // actual reference class long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)). - invoke(array, 0, 1L, Void.class); + invokeExact(array, 0, 1L, Void.class); }); checkWMTE(() -> { // array primitive class long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class, long.class)). - invoke(0, 0, 1L, 1L); + invokeExact(0, 0, 1L, 1L); }); checkWMTE(() -> { // index reference class long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class, long.class)). - invoke(array, Void.class, 1L, 1L); + invokeExact(array, Void.class, 1L, 1L); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class, long.class)). - invoke(array, 0, 1L, 1L); + invokeExact(array, 0, 1L, 1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class)). - invoke(array, 0, 1L, 1L); + invokeExact(array, 0, 1L, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, long.class, Class.class)). - invoke(array, 0, 1L, 1L, Void.class); + invokeExact(array, 0, 1L, 1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null array - long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class)). - invoke(null, 0, 1L); + long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class)). + invokeExact((long[]) null, 0, 1L); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)). - invoke(Void.class, 0, 1L); + invokeExact(Void.class, 0, 1L); }); checkWMTE(() -> { // value reference class long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // array primitive class long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)). - invoke(0, 0, 1L); + invokeExact(0, 0, 1L); }); checkWMTE(() -> { // index reference class long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)). - invoke(array, Void.class, 1L); + invokeExact(array, Void.class, 1L); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)). - invoke(array, 0, 1L); + invokeExact(array, 0, 1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)). - invoke(array, 0, 1L); + invokeExact(array, 0, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)). - invoke(array, 0, 1L, Void.class); + invokeExact(array, 0, 1L, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { // Incorrect argument types checkNPE(() -> { // null array - long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class)). - invoke(null, 0, 1L); + long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class)). + invokeExact((long[]) null, 0, 1L); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)). - invoke(Void.class, 0, 1L); + invokeExact(Void.class, 0, 1L); }); checkWMTE(() -> { // value reference class long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // array primitive class long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)). - invoke(0, 0, 1L); + invokeExact(0, 0, 1L); }); checkWMTE(() -> { // index reference class long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)). - invoke(array, Void.class, 1L); + invokeExact(array, Void.class, 1L); }); // Incorrect return type checkWMTE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)). - invoke(array, 0, 1L); + invokeExact(array, 0, 1L); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)). - invoke(array, 0, 1L); + invokeExact(array, 0, 1L); }); // Incorrect arity checkWMTE(() -> { // 0 long x = (long) hs.get(am, methodType(long.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)). - invoke(array, 0, 1L, Void.class); + invokeExact(array, 0, 1L, Void.class); }); } } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java index 634646e78c1..16efabe0917 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeShort * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeShort */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeShort::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeShort::testArrayWrongMethodType, false)); } @@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - short x = (short) hs.get(am, methodType(short.class, Void.class)). - invoke(null); + short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class)). + invokeExact((VarHandleTestMethodTypeShort) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class short x = (short) hs.get(am, methodType(short.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class short x = (short) hs.get(am, methodType(short.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type checkWMTE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class)). - invoke(recv); + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeShort.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 short x = (short) hs.get(am, methodType(short.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, short.class)). - invoke(null, (short)1); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, short.class)). + invokeExact((VarHandleTestMethodTypeShort) null, (short)1); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, short.class)). - invoke(Void.class, (short)1); + invokeExact(Void.class, (short)1); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, short.class)). - invoke(0, (short)1); + invokeExact(0, (short)1); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, short.class, Class.class)). - invoke(recv, (short)1, Void.class); + invokeExact(recv, (short)1, Void.class); }); } @@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest { // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > short x = (short) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, short.class, Class.class)). - invoke((short)1, Void.class); + invokeExact((short)1, Void.class); }); } @@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - short x = (short) hs.get(am, methodType(short.class, Void.class, int.class)). - invoke(null, 0); + short x = (short) hs.get(am, methodType(short.class, short[].class, int.class)). + invokeExact((short[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class short x = (short) hs.get(am, methodType(short.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class short x = (short) hs.get(am, methodType(short.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type checkWMTE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, short[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 short x = (short) hs.get(am, methodType(short.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, short.class)). - invoke(null, 0, (short)1); + hs.get(am, methodType(void.class, short[].class, int.class, short.class)). + invokeExact((short[]) null, 0, (short)1); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, short.class)). - invoke(Void.class, 0, (short)1); + invokeExact(Void.class, 0, (short)1); }); checkWMTE(() -> { // value reference class hs.get(am, methodType(void.class, short[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, short.class)). - invoke(0, 0, (short)1); + invokeExact(0, 0, (short)1); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, short[].class, Class.class, short.class)). - invoke(array, Void.class, (short)1); + invokeExact(array, Void.class, (short)1); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, short[].class, int.class, Class.class)). - invoke(array, 0, (short)1, Void.class); + invokeExact(array, 0, (short)1, Void.class); }); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java index f3b58c9e2f9..2cc853349ce 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodTypeString * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeString */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodTypeString::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodTypeString::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodTypeString::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodTypeString::testArrayWrongMethodType, false)); } @@ -586,174 +588,174 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - String x = (String) hs.get(am, methodType(String.class, Void.class)). - invoke(null); + String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class)). + invokeExact((VarHandleTestMethodTypeString) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class String x = (String) hs.get(am, methodType(String.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class String x = (String) hs.get(am, methodType(String.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type - checkCCE(() -> { // reference class - Void x = (Void) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class)). - invoke(recv); + hs.checkWMTEOrCCE(() -> { // reference class + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 String x = (String) hs.get(am, methodType(String.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, String.class)). - invoke(null, "foo"); + hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, String.class)). + invokeExact((VarHandleTestMethodTypeString) null, "foo"); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, String.class)). - invoke(Void.class, "foo"); + invokeExact(Void.class, "foo"); }); - checkCCE(() -> { // value reference class + hs.checkWMTEOrCCE(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, String.class)). - invoke(0, "foo"); + invokeExact(0, "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, String.class, Class.class)). - invoke(recv, "foo", Void.class); + invokeExact(recv, "foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, String.class, String.class)). - invoke(null, "foo", "foo"); + boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, String.class)). + invokeExact((VarHandleTestMethodTypeString) null, "foo", "foo"); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, String.class, String.class)). - invoke(Void.class, "foo", "foo"); + invokeExact(Void.class, "foo", "foo"); }); - checkCCE(() -> { // expected reference class + hs.checkWMTEOrCCE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, Class.class, String.class)). - invoke(recv, Void.class, "foo"); + invokeExact(recv, Void.class, "foo"); }); - checkCCE(() -> { // actual reference class + hs.checkWMTEOrCCE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, Class.class)). - invoke(recv, "foo", Void.class); + invokeExact(recv, "foo", Void.class); }); checkWMTE(() -> { // receiver primitive class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , String.class, String.class)). - invoke(0, "foo", "foo"); + invokeExact(0, "foo", "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, String.class, Class.class)). - invoke(recv, "foo", "foo", Void.class); + invokeExact(recv, "foo", "foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { checkNPE(() -> { // null receiver - String x = (String) hs.get(am, methodType(String.class, Void.class, String.class, String.class)). - invoke(null, "foo", "foo"); + String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, String.class)). + invokeExact((VarHandleTestMethodTypeString) null, "foo", "foo"); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class String x = (String) hs.get(am, methodType(String.class, Class.class, String.class, String.class)). - invoke(Void.class, "foo", "foo"); + invokeExact(Void.class, "foo", "foo"); }); - checkCCE(() -> { // expected reference class + hs.checkWMTEOrCCE(() -> { // expected reference class String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class, String.class)). - invoke(recv, Void.class, "foo"); + invokeExact(recv, Void.class, "foo"); }); - checkCCE(() -> { // actual reference class + hs.checkWMTEOrCCE(() -> { // actual reference class String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, Class.class)). - invoke(recv, "foo", Void.class); + invokeExact(recv, "foo", Void.class); }); checkWMTE(() -> { // reciever primitive class String x = (String) hs.get(am, methodType(String.class, int.class , String.class, String.class)). - invoke(0, "foo", "foo"); + invokeExact(0, "foo", "foo"); }); // Incorrect return type - checkCCE(() -> { // reference class + hs.checkWMTEOrCCE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class , String.class, String.class)). - invoke(recv, "foo", "foo"); + invokeExact(recv, "foo", "foo"); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class , String.class, String.class)). - invoke(recv, "foo", "foo"); + invokeExact(recv, "foo", "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 String x = (String) hs.get(am, methodType(String.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, String.class, Class.class)). - invoke(recv, "foo", "foo", Void.class); + invokeExact(recv, "foo", "foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { checkNPE(() -> { // null receiver - String x = (String) hs.get(am, methodType(String.class, Void.class, String.class)). - invoke(null, "foo"); + String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class)). + invokeExact((VarHandleTestMethodTypeString) null, "foo"); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class String x = (String) hs.get(am, methodType(String.class, Class.class, String.class)). - invoke(Void.class, "foo"); + invokeExact(Void.class, "foo"); }); - checkCCE(() -> { // value reference class + hs.checkWMTEOrCCE(() -> { // value reference class String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // reciever primitive class String x = (String) hs.get(am, methodType(String.class, int.class, String.class)). - invoke(0, "foo"); + invokeExact(0, "foo"); }); // Incorrect return type - checkCCE(() -> { // reference class + hs.checkWMTEOrCCE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class, String.class)). - invoke(recv, "foo"); + invokeExact(recv, "foo"); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class)). - invoke(recv, "foo"); + invokeExact(recv, "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 String x = (String) hs.get(am, methodType(String.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class)). - invoke(recv, "foo", Void.class); + invokeExact(recv, "foo", Void.class); }); } @@ -1054,110 +1056,110 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect return type - checkCCE(() -> { // reference class + hs.checkWMTEOrCCE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { - checkCCE(() -> { // value reference class + hs.checkWMTEOrCCE(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, String.class, Class.class)). - invoke("foo", Void.class); + invokeExact("foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types - checkCCE(() -> { // expected reference class + hs.checkWMTEOrCCE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, String.class)). - invoke(Void.class, "foo"); + invokeExact(Void.class, "foo"); }); - checkCCE(() -> { // actual reference class + hs.checkWMTEOrCCE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, String.class, Class.class)). - invoke("foo", Void.class); + invokeExact("foo", Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, String.class, String.class, Class.class)). - invoke("foo", "foo", Void.class); + invokeExact("foo", "foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { // Incorrect argument types - checkCCE(() -> { // expected reference class + hs.checkWMTEOrCCE(() -> { // expected reference class String x = (String) hs.get(am, methodType(String.class, Class.class, String.class)). - invoke(Void.class, "foo"); + invokeExact(Void.class, "foo"); }); - checkCCE(() -> { // actual reference class + hs.checkWMTEOrCCE(() -> { // actual reference class String x = (String) hs.get(am, methodType(String.class, String.class, Class.class)). - invoke("foo", Void.class); + invokeExact("foo", Void.class); }); // Incorrect return type - checkCCE(() -> { // reference class + hs.checkWMTEOrCCE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, String.class, String.class)). - invoke("foo", "foo"); + invokeExact("foo", "foo"); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, String.class, String.class)). - invoke("foo", "foo"); + invokeExact("foo", "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 String x = (String) hs.get(am, methodType(String.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(String.class, String.class, String.class, Class.class)). - invoke("foo", "foo", Void.class); + invokeExact("foo", "foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { // Incorrect argument types - checkCCE(() -> { // value reference class + hs.checkWMTEOrCCE(() -> { // value reference class String x = (String) hs.get(am, methodType(String.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect return type - checkCCE(() -> { // reference class + hs.checkWMTEOrCCE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, String.class)). - invoke("foo"); + invokeExact("foo"); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, String.class)). - invoke("foo"); + invokeExact("foo"); }); // Incorrect arity checkWMTE(() -> { // 0 String x = (String) hs.get(am, methodType(String.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(String.class, String.class, Class.class)). - invoke("foo", Void.class); + invokeExact("foo", Void.class); }); } @@ -1686,195 +1688,195 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - String x = (String) hs.get(am, methodType(String.class, Void.class, int.class)). - invoke(null, 0); + String x = (String) hs.get(am, methodType(String.class, String[].class, int.class)). + invokeExact((String[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class String x = (String) hs.get(am, methodType(String.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class String x = (String) hs.get(am, methodType(String.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type - checkCCE(() -> { // reference class + hs.checkWMTEOrCCE(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, String[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 String x = (String) hs.get(am, methodType(String.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, String.class)). - invoke(null, 0, "foo"); + hs.get(am, methodType(void.class, String[].class, int.class, String.class)). + invokeExact((String[]) null, 0, "foo"); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, String.class)). - invoke(Void.class, 0, "foo"); + invokeExact(Void.class, 0, "foo"); }); - checkCCE(() -> { // value reference class + hs.checkWMTEOrCCE(() -> { // value reference class hs.get(am, methodType(void.class, String[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, String.class)). - invoke(0, 0, "foo"); + invokeExact(0, 0, "foo"); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, String[].class, Class.class, String.class)). - invoke(array, Void.class, "foo"); + invokeExact(array, Void.class, "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, String[].class, int.class, Class.class)). - invoke(array, 0, "foo", Void.class); + invokeExact(array, 0, "foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, String.class, String.class)). - invoke(null, 0, "foo", "foo"); + boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class)). + invokeExact((String[]) null, 0, "foo", "foo"); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, String.class, String.class)). - invoke(Void.class, 0, "foo", "foo"); + invokeExact(Void.class, 0, "foo", "foo"); }); - checkCCE(() -> { // expected reference class + hs.checkWMTEOrCCE(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, Class.class, String.class)). - invoke(array, 0, Void.class, "foo"); + invokeExact(array, 0, Void.class, "foo"); }); - checkCCE(() -> { // actual reference class + hs.checkWMTEOrCCE(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, Class.class)). - invoke(array, 0, "foo", Void.class); + invokeExact(array, 0, "foo", Void.class); }); checkWMTE(() -> { // receiver primitive class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, String.class, String.class)). - invoke(0, 0, "foo", "foo"); + invokeExact(0, 0, "foo", "foo"); }); checkWMTE(() -> { // index reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, Class.class, String.class, String.class)). - invoke(array, Void.class, "foo", "foo"); + invokeExact(array, Void.class, "foo", "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class, Class.class)). - invoke(array, 0, "foo", "foo", Void.class); + invokeExact(array, 0, "foo", "foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { // Incorrect argument types checkNPE(() -> { // null receiver - String x = (String) hs.get(am, methodType(String.class, Void.class, int.class, String.class, String.class)). - invoke(null, 0, "foo", "foo"); + String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, String.class)). + invokeExact((String[]) null, 0, "foo", "foo"); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class String x = (String) hs.get(am, methodType(String.class, Class.class, int.class, String.class, String.class)). - invoke(Void.class, 0, "foo", "foo"); + invokeExact(Void.class, 0, "foo", "foo"); }); - checkCCE(() -> { // expected reference class + hs.checkWMTEOrCCE(() -> { // expected reference class String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class, String.class)). - invoke(array, 0, Void.class, "foo"); + invokeExact(array, 0, Void.class, "foo"); }); - checkCCE(() -> { // actual reference class + hs.checkWMTEOrCCE(() -> { // actual reference class String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, Class.class)). - invoke(array, 0, "foo", Void.class); + invokeExact(array, 0, "foo", Void.class); }); checkWMTE(() -> { // array primitive class String x = (String) hs.get(am, methodType(String.class, int.class, int.class, String.class, String.class)). - invoke(0, 0, "foo", "foo"); + invokeExact(0, 0, "foo", "foo"); }); checkWMTE(() -> { // index reference class String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class, String.class, String.class)). - invoke(array, Void.class, "foo", "foo"); + invokeExact(array, Void.class, "foo", "foo"); }); // Incorrect return type - checkCCE(() -> { // reference class + hs.checkWMTEOrCCE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, String[].class, int.class, String.class, String.class)). - invoke(array, 0, "foo", "foo"); + invokeExact(array, 0, "foo", "foo"); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class)). - invoke(array, 0, "foo", "foo"); + invokeExact(array, 0, "foo", "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 String x = (String) hs.get(am, methodType(String.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, String.class, Class.class)). - invoke(array, 0, "foo", "foo", Void.class); + invokeExact(array, 0, "foo", "foo", Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null array - String x = (String) hs.get(am, methodType(String.class, Void.class, int.class, String.class)). - invoke(null, 0, "foo"); + String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class)). + invokeExact((String[]) null, 0, "foo"); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class String x = (String) hs.get(am, methodType(String.class, Class.class, int.class, String.class)). - invoke(Void.class, 0, "foo"); + invokeExact(Void.class, 0, "foo"); }); - checkCCE(() -> { // value reference class + hs.checkWMTEOrCCE(() -> { // value reference class String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // array primitive class String x = (String) hs.get(am, methodType(String.class, int.class, int.class, String.class)). - invoke(0, 0, "foo"); + invokeExact(0, 0, "foo"); }); checkWMTE(() -> { // index reference class String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class, String.class)). - invoke(array, Void.class, "foo"); + invokeExact(array, Void.class, "foo"); }); // Incorrect return type - checkCCE(() -> { // reference class + hs.checkWMTEOrCCE(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, String[].class, int.class, String.class)). - invoke(array, 0, "foo"); + invokeExact(array, 0, "foo"); }); checkWMTE(() -> { // primitive class boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class)). - invoke(array, 0, "foo"); + invokeExact(array, 0, "foo"); }); // Incorrect arity checkWMTE(() -> { // 0 String x = (String) hs.get(am, methodType(String.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, Class.class)). - invoke(array, 0, "foo", Void.class); + invokeExact(array, 0, "foo", Void.class); }); } diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template index 391dc1a5197..5dfd82f6cd7 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template @@ -309,6 +309,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$); }); + + checkUOE(() -> { + $type$ r = ($type$) vh.getAndSet(recv, $value1$); + }); #end[CAS] #if[!AtomicAdd] @@ -399,6 +403,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease($value1$, $value2$); }); + + checkUOE(() -> { + $type$ r = ($type$) vh.getAndSet($value1$); + }); #end[CAS] #if[!AtomicAdd] @@ -504,29 +512,41 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(recv); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(recv); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(recv); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } { - boolean r = vh.weakCompareAndSetVolatile(recv, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetVolatile(recv, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetVolatile $type$"); $type$ x = ($type$) vh.get(recv); assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); } @@ -586,6 +606,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$); }); + + checkUOE(() -> { + $type$ r = ($type$) vh.getAndSet(recv, $value1$); + }); #end[CAS] #if[!AtomicAdd] @@ -691,36 +715,48 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSet($value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet($value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = (boolean) vh.weakCompareAndSetAcquire($value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire($value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = (boolean) vh.weakCompareAndSetRelease($value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease($value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } { - boolean r = (boolean) vh.weakCompareAndSetVolatile($value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease($value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetVolatile $type$"); $type$ x = ($type$) vh.get(); - assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$"); } // Compare set and get { - $type$ o = ($type$) vh.getAndSet( $value2$); + $type$ o = ($type$) vh.getAndSet($value2$); assertEquals(o, $value1$, "getAndSet $type$"); $type$ x = ($type$) vh.get(); assertEquals(x, $value2$, "getAndSet $type$ value"); @@ -773,6 +809,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease($value1$, $value2$); }); + + checkUOE(() -> { + $type$ r = ($type$) vh.getAndSet($value1$); + }); #end[CAS] #if[!AtomicAdd] @@ -881,31 +921,43 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(array, i, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } { - boolean r = vh.weakCompareAndSetVolatile(array, i, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetVolatile(array, i, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetVolatile $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$"); } // Compare set and get @@ -967,6 +1019,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { checkUOE(() -> { boolean r = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$); }); + + checkUOE(() -> { + $type$ r = ($type$) vh.getAndSet(array, i, $value1$); + }); #end[CAS] #if[!AtomicAdd] diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template index e433789f8cd..615bb528e06 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template @@ -311,10 +311,12 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { checkROBE(() -> { $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); }); + +#else[CAS] checkUOE(() -> { boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); }); -#else[CAS] + checkUOE(() -> { $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); }); @@ -884,22 +886,31 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); } @@ -1037,22 +1048,31 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template index f56d9a641a7..e4bd78e8f45 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template @@ -209,31 +209,43 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetVolatile $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$"); } // Compare set and get @@ -380,36 +392,48 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact($value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact($value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetVolatile $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$"); } // Compare set and get { - $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact($value2$); + $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact( $value2$); assertEquals(o, $value1$, "getAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, $value2$, "getAndSet $type$ value"); @@ -554,31 +578,43 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetVolatile $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$"); } // Compare set and get diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template index fe504902f10..5bec8b46a10 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template @@ -23,6 +23,7 @@ /* * @test + * @bug 8156486 * @run testng/othervm VarHandleTestMethodType$Type$ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodType$Type$ */ @@ -81,27 +82,28 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { public Object[][] accessTestCaseProvider() throws Exception { List> cases = new ArrayList<>(); - cases.add(new VarHandleAccessTestCase("Instance field wrong method type", + cases.add(new VarHandleAccessTestCase("Instance field", vhField, vh -> testInstanceFieldWrongMethodType(this, vh), false)); - cases.add(new VarHandleAccessTestCase("Static field wrong method type", + cases.add(new VarHandleAccessTestCase("Static field", vhStaticField, VarHandleTestMethodType$Type$::testStaticFieldWrongMethodType, false)); - cases.add(new VarHandleAccessTestCase("Array wrong method type", + cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestMethodType$Type$::testArrayWrongMethodType, false)); + for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) { - cases.add(new MethodHandleAccessTestCase("Instance field wrong method type", + cases.add(new MethodHandleAccessTestCase("Instance field", vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs), false)); - cases.add(new MethodHandleAccessTestCase("Static field wrong method type", + cases.add(new MethodHandleAccessTestCase("Static field", vhStaticField, f, VarHandleTestMethodType$Type$::testStaticFieldWrongMethodType, false)); - cases.add(new MethodHandleAccessTestCase("Array wrong method type", + cases.add(new MethodHandleAccessTestCase("Array", vhArray, f, VarHandleTestMethodType$Type$::testArrayWrongMethodType, false)); } @@ -648,63 +650,63 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null receiver - $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class)). - invoke(null); + $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class)). + invokeExact((VarHandleTestMethodType$Type$) null); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); checkWMTE(() -> { // receiver primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class)). - invoke(0); + invokeExact(0); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class - Void x = (Void) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class)). - invoke(recv); + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class + Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class)). + invokeExact(recv); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class)). - invoke(recv); + invokeExact(recv); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - hs.get(am, methodType(void.class, Void.class, $type$.class)). - invoke(null, $value1$); + hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, $type$.class)). + invokeExact((VarHandleTestMethodType$Type$) null, $value1$); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class hs.get(am, methodType(void.class, Class.class, $type$.class)). - invoke(Void.class, $value1$); + invokeExact(Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // value reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, $type$.class)). - invoke(0, $value1$); + invokeExact(0, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)). - invoke(recv, $value1$, Void.class); + invokeExact(recv, $value1$, Void.class); }); } @@ -712,111 +714,111 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, $type$.class, $type$.class)). - invoke(null, $value1$, $value1$); + boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class)). + invokeExact((VarHandleTestMethodType$Type$) null, $value1$, $value1$); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, $type$.class, $type$.class)). - invoke(Void.class, $value1$, $value1$); + invokeExact(Void.class, $value1$, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // expected reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, Class.class, $type$.class)). - invoke(recv, Void.class, $value1$); + invokeExact(recv, Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // actual reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)). - invoke(recv, $value1$, Void.class); + invokeExact(recv, $value1$, Void.class); }); checkWMTE(() -> { // receiver primitive class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , $type$.class, $type$.class)). - invoke(0, $value1$, $value1$); + invokeExact(0, $value1$, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class, Class.class)). - invoke(recv, $value1$, $value1$, Void.class); + invokeExact(recv, $value1$, $value1$, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { checkNPE(() -> { // null receiver - $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class, $type$.class)). - invoke(null, $value1$, $value1$); + $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class)). + invokeExact((VarHandleTestMethodType$Type$) null, $value1$, $value1$); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class, $type$.class)). - invoke(Void.class, $value1$, $value1$); + invokeExact(Void.class, $value1$, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // expected reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class, $type$.class)). - invoke(recv, Void.class, $value1$); + invokeExact(recv, Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // actual reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)). - invoke(recv, $value1$, Void.class); + invokeExact(recv, $value1$, Void.class); }); checkWMTE(() -> { // reciever primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class , $type$.class, $type$.class)). - invoke(0, $value1$, $value1$); + invokeExact(0, $value1$, $value1$); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class , $type$.class, $type$.class)). - invoke(recv, $value1$, $value1$); + invokeExact(recv, $value1$, $value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class , $type$.class, $type$.class)). - invoke(recv, $value1$, $value1$); + invokeExact(recv, $value1$, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class, Class.class)). - invoke(recv, $value1$, $value1$, Void.class); + invokeExact(recv, $value1$, $value1$, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { checkNPE(() -> { // null receiver - $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class)). - invoke(null, $value1$); + $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)). + invokeExact((VarHandleTestMethodType$Type$) null, $value1$); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)). - invoke(Void.class, $value1$); + invokeExact(Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // value reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // reciever primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)). - invoke(0, $value1$); + invokeExact(0, $value1$); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)). - invoke(recv, $value1$); + invokeExact(recv, $value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)). - invoke(recv, $value1$); + invokeExact(recv, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)). - invoke(recv, $value1$, Void.class); + invokeExact(recv, $value1$, Void.class); }); } #end[CAS] @@ -824,38 +826,38 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { #if[AtomicAdd] for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { checkNPE(() -> { // null receiver - $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class)). - invoke(null, $value1$); + $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)). + invokeExact((VarHandleTestMethodType$Type$) null, $value1$); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)). - invoke(Void.class, $value1$); + invokeExact(Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // value reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)). - invoke(recv, Void.class); + invokeExact(recv, Void.class); }); checkWMTE(() -> { // reciever primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)). - invoke(0, $value1$); + invokeExact(0, $value1$); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)). - invoke(recv, $value1$); + invokeExact(recv, $value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)). - invoke(recv, $value1$); + invokeExact(recv, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)). - invoke(recv, $value1$, Void.class); + invokeExact(recv, $value1$, Void.class); }); } #end[AtomicAdd] @@ -1200,111 +1202,111 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class)). - invoke(); + invokeExact(); }); // Incorrect arity checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType(Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { - check{#if[String]?CCE:WMTE}(() -> { // value reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class hs.get(am, methodType(void.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, $type$.class, Class.class)). - invoke($value1$, Void.class); + invokeExact($value1$, Void.class); }); } #if[CAS] for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types - check{#if[String]?CCE:WMTE}(() -> { // expected reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, $type$.class)). - invoke(Void.class, $value1$); + invokeExact(Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // actual reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$.class, Class.class)). - invoke($value1$, Void.class); + invokeExact($value1$, Void.class); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$.class, $type$.class, Class.class)). - invoke($value1$, $value1$, Void.class); + invokeExact($value1$, $value1$, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { // Incorrect argument types - check{#if[String]?CCE:WMTE}(() -> { // expected reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)). - invoke(Void.class, $value1$); + invokeExact(Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // actual reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)). - invoke($value1$, Void.class); + invokeExact($value1$, Void.class); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, $type$.class, $type$.class)). - invoke($value1$, $value1$); + invokeExact($value1$, $value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class, $type$.class)). - invoke($value1$, $value1$); + invokeExact($value1$, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, $type$.class, Class.class)). - invoke($value1$, $value1$, Void.class); + invokeExact($value1$, $value1$, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { // Incorrect argument types - check{#if[String]?CCE:WMTE}(() -> { // value reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)). - invoke($value1$); + invokeExact($value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)). - invoke($value1$); + invokeExact($value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)). - invoke($value1$, Void.class); + invokeExact($value1$, Void.class); }); } #end[CAS] @@ -1314,25 +1316,25 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { // Incorrect argument types check{#if[String]?CCE:WMTE}(() -> { // value reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)). - invoke(Void.class); + invokeExact(Void.class); }); // Incorrect return type check{#if[String]?CCE:WMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)). - invoke($value1$); + invokeExact($value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)). - invoke($value1$); + invokeExact($value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)). - invoke($value1$, Void.class); + invokeExact($value1$, Void.class); }); } #end[AtomicAdd] @@ -1929,196 +1931,196 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) { // Incorrect argument types checkNPE(() -> { // null array - $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class)). - invoke(null, 0); + $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class)). + invokeExact(($type$[]) null, 0); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class)). - invoke(Void.class, 0); + invokeExact(Void.class, 0); }); checkWMTE(() -> { // array primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class)). - invoke(0, 0); + invokeExact(0, 0); }); checkWMTE(() -> { // index reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class)). - invoke(array, Void.class); + invokeExact(array, Void.class); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void x = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class)). - invoke(array, 0); + invokeExact(array, 0); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) { // Incorrect argument types checkNPE(() -> { // null array - hs.get(am, methodType(void.class, Void.class, int.class, $type$.class)). - invoke(null, 0, $value1$); + hs.get(am, methodType(void.class, $type$[].class, int.class, $type$.class)). + invokeExact(($type$[]) null, 0, $value1$); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class hs.get(am, methodType(void.class, Class.class, int.class, $type$.class)). - invoke(Void.class, 0, $value1$); + invokeExact(Void.class, 0, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // value reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class hs.get(am, methodType(void.class, $type$[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // receiver primitive class hs.get(am, methodType(void.class, int.class, int.class, $type$.class)). - invoke(0, 0, $value1$); + invokeExact(0, 0, $value1$); }); checkWMTE(() -> { // index reference class hs.get(am, methodType(void.class, $type$[].class, Class.class, $type$.class)). - invoke(array, Void.class, $value1$); + invokeExact(array, Void.class, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 hs.get(am, methodType(void.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > hs.get(am, methodType(void.class, $type$[].class, int.class, Class.class)). - invoke(array, 0, $value1$, Void.class); + invokeExact(array, 0, $value1$, Void.class); }); } #if[CAS] for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null receiver - boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, $type$.class, $type$.class)). - invoke(null, 0, $value1$, $value1$); + boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, $type$.class)). + invokeExact(($type$[]) null, 0, $value1$, $value1$); }); - checkCCE(() -> { // receiver reference class + hs.checkWMTEOrCCE(() -> { // receiver reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, $type$.class, $type$.class)). - invoke(Void.class, 0, $value1$, $value1$); + invokeExact(Void.class, 0, $value1$, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // expected reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, Class.class, $type$.class)). - invoke(array, 0, Void.class, $value1$); + invokeExact(array, 0, Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // actual reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, Class.class)). - invoke(array, 0, $value1$, Void.class); + invokeExact(array, 0, $value1$, Void.class); }); checkWMTE(() -> { // receiver primitive class boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, $type$.class, $type$.class)). - invoke(0, 0, $value1$, $value1$); + invokeExact(0, 0, $value1$, $value1$); }); checkWMTE(() -> { // index reference class boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, Class.class, $type$.class, $type$.class)). - invoke(array, Void.class, $value1$, $value1$); + invokeExact(array, Void.class, $value1$, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 boolean r = (boolean) hs.get(am, methodType(boolean.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, $type$.class, Class.class)). - invoke(array, 0, $value1$, $value1$, Void.class); + invokeExact(array, 0, $value1$, $value1$, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) { // Incorrect argument types checkNPE(() -> { // null receiver - $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class, $type$.class)). - invoke(null, 0, $value1$, $value1$); + $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, $type$.class)). + invokeExact(($type$[]) null, 0, $value1$, $value1$); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class, $type$.class)). - invoke(Void.class, 0, $value1$, $value1$); + invokeExact(Void.class, 0, $value1$, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // expected reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class, $type$.class)). - invoke(array, 0, Void.class, $value1$); + invokeExact(array, 0, Void.class, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // actual reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)). - invoke(array, 0, $value1$, Void.class); + invokeExact(array, 0, $value1$, Void.class); }); checkWMTE(() -> { // array primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class, $type$.class)). - invoke(0, 0, $value1$, $value1$); + invokeExact(0, 0, $value1$, $value1$); }); checkWMTE(() -> { // index reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class, $type$.class)). - invoke(array, Void.class, $value1$, $value1$); + invokeExact(array, Void.class, $value1$, $value1$); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class, $type$.class)). - invoke(array, 0, $value1$, $value1$); + invokeExact(array, 0, $value1$, $value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class, $type$.class)). - invoke(array, 0, $value1$, $value1$); + invokeExact(array, 0, $value1$, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, $type$.class, Class.class)). - invoke(array, 0, $value1$, $value1$, Void.class); + invokeExact(array, 0, $value1$, $value1$, Void.class); }); } for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) { // Incorrect argument types checkNPE(() -> { // null array - $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class)). - invoke(null, 0, $value1$); + $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class)). + invokeExact(($type$[]) null, 0, $value1$); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)). - invoke(Void.class, 0, $value1$); + invokeExact(Void.class, 0, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // value reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // array primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)). - invoke(0, 0, $value1$); + invokeExact(0, 0, $value1$); }); checkWMTE(() -> { // index reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)). - invoke(array, Void.class, $value1$); + invokeExact(array, Void.class, $value1$); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)). - invoke(array, 0, $value1$); + invokeExact(array, 0, $value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)). - invoke(array, 0, $value1$); + invokeExact(array, 0, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)). - invoke(array, 0, $value1$, Void.class); + invokeExact(array, 0, $value1$, Void.class); }); } #end[CAS] @@ -2127,42 +2129,42 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) { // Incorrect argument types checkNPE(() -> { // null array - $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class)). - invoke(null, 0, $value1$); + $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class)). + invokeExact(($type$[]) null, 0, $value1$); }); - checkCCE(() -> { // array reference class + hs.checkWMTEOrCCE(() -> { // array reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)). - invoke(Void.class, 0, $value1$); + invokeExact(Void.class, 0, $value1$); }); - check{#if[String]?CCE:WMTE}(() -> { // value reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)). - invoke(array, 0, Void.class); + invokeExact(array, 0, Void.class); }); checkWMTE(() -> { // array primitive class $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)). - invoke(0, 0, $value1$); + invokeExact(0, 0, $value1$); }); checkWMTE(() -> { // index reference class $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)). - invoke(array, Void.class, $value1$); + invokeExact(array, Void.class, $value1$); }); // Incorrect return type - check{#if[String]?CCE:WMTE}(() -> { // reference class + {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)). - invoke(array, 0, $value1$); + invokeExact(array, 0, $value1$); }); checkWMTE(() -> { // primitive class $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)). - invoke(array, 0, $value1$); + invokeExact(array, 0, $value1$); }); // Incorrect arity checkWMTE(() -> { // 0 $type$ x = ($type$) hs.get(am, methodType($type$.class)). - invoke(); + invokeExact(); }); checkWMTE(() -> { // > $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)). - invoke(array, 0, $value1$, Void.class); + invokeExact(array, 0, $value1$, Void.class); }); } #end[AtomicAdd] diff --git a/jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh b/jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh index 7d6afc7b206..436d2d371d9 100644 --- a/jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh +++ b/jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh @@ -113,36 +113,40 @@ do ;; esac + # The value of `value3` is chosen such that when added to `value1` or `value2` + # it will result in carrying of bits over to the next byte, thereby detecting + # possible errors in endianness conversion e.g. if say for atomic addition the + # augend is incorrectly processed case $type in short) value1=(short)0x0102 value2=(short)0x1112 - value3=(short)0x2122 + value3=(short)0xFFFE ;; char) value1=(char)0x0102 value2=(char)0x1112 - value3=(char)0x2122 + value3=(char)0xFFFE ;; int) value1=0x01020304 value2=0x11121314 - value3=0x21222324 + value3=0xFFFEFDFC ;; long) value1=0x0102030405060708L value2=0x1112131415161718L - value3=0x2122232425262728L + value3=0xFFFEFDFCFBFAF9F8L ;; float) value1=0x01020304 value2=0x11121314 - value3=0x21222324 + value3=0xFFFEFDFC ;; double) value1=0x0102030405060708L value2=0x1112131415161718L - value3=0x2122232425262728L + value3=0xFFFEFDFCFBFAF9F8L ;; esac diff --git a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java index 195cb3a2fd8..2d52eeb4299 100644 --- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java +++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java @@ -36,9 +36,13 @@ * @modules jdk.management * @build jdk.testlibrary.* ResetPeakMemoryUsage MemoryUtil RunUtil * @run main ResetPeakMemoryUsage + * @requires vm.opt.ExplicitGCInvokesConcurrent != "true" + * @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true" + * @requires vm.opt.DisableExplicitGC != "true" */ import java.lang.management.*; +import java.lang.ref.WeakReference; import java.util.*; public class ResetPeakMemoryUsage { @@ -100,6 +104,7 @@ public class ResetPeakMemoryUsage { printMemoryUsage(usage0, peak0); obj = new Object[largeArraySize]; + WeakReference weakRef = new WeakReference<>(obj); MemoryUsage usage1 = mpool.getUsage(); MemoryUsage peak1 = mpool.getPeakUsage(); @@ -124,7 +129,11 @@ public class ResetPeakMemoryUsage { // The object is now garbage and do a GC // memory usage should drop obj = null; - mbean.gc(); + + //This will cause sure shot GC unlike Runtime.gc() invoked by mbean.gc() + while(weakRef.get() != null) { + mbean.gc(); + } MemoryUsage usage2 = mpool.getUsage(); MemoryUsage peak2 = mpool.getPeakUsage(); diff --git a/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java b/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java index ac0bc89f98c..63f5c5fbc31 100644 --- a/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java +++ b/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java @@ -270,8 +270,7 @@ public class PlatformLoggingMXBeanTest // Calling getMBeanInfo will throw exception if not found. platformMBS.getMBeanInfo(objName); - if (!platformMBS.isInstanceOf(objName, "java.lang.management.PlatformLoggingMXBean") || - !platformMBS.isInstanceOf(objName, "java.util.logging.LoggingMXBean")) { + if (!platformMBS.isInstanceOf(objName, "java.lang.management.PlatformLoggingMXBean")) { throw new RuntimeException(objName + " is of unexpected type"); } diff --git a/jdk/test/java/lang/module/AutomaticModulesTest.java b/jdk/test/java/lang/module/AutomaticModulesTest.java index d400ffb86cf..93dd5f7685d 100644 --- a/jdk/test/java/lang/module/AutomaticModulesTest.java +++ b/jdk/test/java/lang/module/AutomaticModulesTest.java @@ -469,7 +469,7 @@ public class AutomaticModulesTest { static Configuration resolve(Configuration parent, ModuleFinder finder, String... roots) { - return parent.resolveRequires(finder, ModuleFinder.empty(), Set.of(roots)); + return parent.resolveRequires(finder, ModuleFinder.of(), Set.of(roots)); } /** diff --git a/jdk/test/java/lang/module/ConfigurationTest.java b/jdk/test/java/lang/module/ConfigurationTest.java index 9e7e9d4357c..4d885cd7e59 100644 --- a/jdk/test/java/lang/module/ConfigurationTest.java +++ b/jdk/test/java/lang/module/ConfigurationTest.java @@ -721,7 +721,7 @@ public class ConfigurationTest { // finder2 is the after ModuleFinder and so p@2.0 should not be located // as module p is in parent configuration. - cf2 = resolveRequiresAndUses(cf1, ModuleFinder.empty(), finder2, "m1"); + cf2 = resolveRequiresAndUses(cf1, ModuleFinder.of(), finder2, "m1"); assertTrue(cf2.parent().get() == cf1); assertTrue(cf2.modules().size() == 1); @@ -865,7 +865,7 @@ public class ConfigurationTest { ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); - Configuration cf2 = resolveRequires(cf1, ModuleFinder.empty(), finder2, "m2"); + Configuration cf2 = resolveRequires(cf1, ModuleFinder.of(), finder2, "m2"); assertTrue(cf2.modules().size() == 1); assertTrue(cf2.findModule("m2").isPresent()); @@ -967,7 +967,7 @@ public class ConfigurationTest { */ @Test(expectedExceptions = { ResolutionException.class }) public void testRootNotFound() { - resolveRequires(ModuleFinder.empty(), "m1"); + resolveRequires(ModuleFinder.of(), "m1"); } @@ -1440,22 +1440,22 @@ public class ConfigurationTest { @Test(expectedExceptions = { NullPointerException.class }) public void testResolveRequiresWithNull1() { - resolveRequires((ModuleFinder)null, ModuleFinder.empty()); + resolveRequires((ModuleFinder)null, ModuleFinder.of()); } @Test(expectedExceptions = { NullPointerException.class }) public void testResolveRequiresWithNull2() { - resolveRequires(ModuleFinder.empty(), (ModuleFinder)null); + resolveRequires(ModuleFinder.of(), (ModuleFinder)null); } @Test(expectedExceptions = { NullPointerException.class }) public void testResolveRequiresAndUsesWithNull1() { - resolveRequiresAndUses((ModuleFinder) null, ModuleFinder.empty()); + resolveRequiresAndUses((ModuleFinder) null, ModuleFinder.of()); } @Test(expectedExceptions = { NullPointerException.class }) public void testResolveRequiresAndUsesWithNull2() { - resolveRequiresAndUses(ModuleFinder.empty(), (ModuleFinder) null); + resolveRequiresAndUses(ModuleFinder.of(), (ModuleFinder) null); } @Test(expectedExceptions = { NullPointerException.class }) @@ -1493,7 +1493,7 @@ public class ConfigurationTest { private Configuration resolveRequires(Configuration parent, ModuleFinder before, String... roots) { - return resolveRequires(parent, before, ModuleFinder.empty(), roots); + return resolveRequires(parent, before, ModuleFinder.of(), roots); } private Configuration resolveRequires(ModuleFinder before, @@ -1521,7 +1521,7 @@ public class ConfigurationTest { private Configuration resolveRequiresAndUses(Configuration parent, ModuleFinder before, String... roots) { - return resolveRequiresAndUses(parent, before, ModuleFinder.empty(), roots); + return resolveRequiresAndUses(parent, before, ModuleFinder.of(), roots); } private Configuration resolveRequiresAndUses(ModuleFinder before, diff --git a/jdk/test/java/lang/module/ModuleFinderTest.java b/jdk/test/java/lang/module/ModuleFinderTest.java index 3270dfd4085..58c2ae56334 100644 --- a/jdk/test/java/lang/module/ModuleFinderTest.java +++ b/jdk/test/java/lang/module/ModuleFinderTest.java @@ -76,9 +76,9 @@ public class ModuleFinderTest { /** - * Test ModuleFinder.of with zero entries + * Test ModuleFinder.of with no entries */ - public void testOfZeroEntries() { + public void testOfNoEntries() { ModuleFinder finder = ModuleFinder.of(); assertTrue(finder.findAll().isEmpty()); assertFalse(finder.find("java.rhubarb").isPresent()); @@ -454,18 +454,46 @@ public class ModuleFinderTest { /** - * Test ModuleFinder.compose + * Test ModuleFinder.compose with no module finders */ - public void testCompose() throws Exception { + public void testComposeOfNone() throws Exception { + ModuleFinder finder = ModuleFinder.of(); + assertTrue(finder.findAll().isEmpty()); + assertFalse(finder.find("java.rhubarb").isPresent()); + } + + + /** + * Test ModuleFinder.compose with one module finder + */ + public void testComposeOfOne() throws Exception { + Path dir = Files.createTempDirectory(USER_DIR, "mods"); + createModularJar(dir.resolve("m1.jar"), "m1"); + createModularJar(dir.resolve("m2.jar"), "m2"); + + ModuleFinder finder1 = ModuleFinder.of(dir); + + ModuleFinder finder = ModuleFinder.compose(finder1); + assertTrue(finder.findAll().size() == 2); + assertTrue(finder.find("m1").isPresent()); + assertTrue(finder.find("m2").isPresent()); + assertFalse(finder.find("java.rhubarb").isPresent()); + } + + + /** + * Test ModuleFinder.compose with two module finders + */ + public void testComposeOfTwo() throws Exception { Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); - createExplodedModule(dir1.resolve("m1"), "m1@1.0"); - createExplodedModule(dir1.resolve("m2"), "m2@1.0"); + createModularJar(dir1.resolve("m1.jar"), "m1@1.0"); + createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); - createExplodedModule(dir2.resolve("m1"), "m1@2.0"); - createExplodedModule(dir2.resolve("m2"), "m2@2.0"); - createExplodedModule(dir2.resolve("m3"), "m3"); - createExplodedModule(dir2.resolve("m4"), "m4"); + createModularJar(dir2.resolve("m1.jar"), "m1@2.0"); + createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); + createModularJar(dir2.resolve("m3.jar"), "m3"); + createModularJar(dir2.resolve("m4.jar"), "m4"); ModuleFinder finder1 = ModuleFinder.of(dir1); ModuleFinder finder2 = ModuleFinder.of(dir2); @@ -478,23 +506,65 @@ public class ModuleFinderTest { assertTrue(finder.find("m4").isPresent()); assertFalse(finder.find("java.rhubarb").isPresent()); - // check that m1@1.0 (and not m1@2.0) is found + // check that m1@1.0 is found ModuleDescriptor m1 = finder.find("m1").get().descriptor(); assertEquals(m1.version().get().toString(), "1.0"); - // check that m2@1.0 (and not m2@2.0) is found + // check that m2@1.0 is found ModuleDescriptor m2 = finder.find("m2").get().descriptor(); assertEquals(m2.version().get().toString(), "1.0"); } /** - * Test ModuleFinder.empty + * Test ModuleFinder.compose with three module finders */ - public void testEmpty() { - ModuleFinder finder = ModuleFinder.empty(); - assertTrue(finder.findAll().isEmpty()); + public void testComposeOfThree() throws Exception { + Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); + createModularJar(dir1.resolve("m1.jar"), "m1@1.0"); + createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); + + Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); + createModularJar(dir2.resolve("m1.jar"), "m1@2.0"); + createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); + createModularJar(dir2.resolve("m3.jar"), "m3@2.0"); + createModularJar(dir2.resolve("m4.jar"), "m4@2.0"); + + Path dir3 = Files.createTempDirectory(USER_DIR, "mods3"); + createModularJar(dir3.resolve("m3.jar"), "m3@3.0"); + createModularJar(dir3.resolve("m4.jar"), "m4@3.0"); + createModularJar(dir3.resolve("m5.jar"), "m5"); + createModularJar(dir3.resolve("m6.jar"), "m6"); + + ModuleFinder finder1 = ModuleFinder.of(dir1); + ModuleFinder finder2 = ModuleFinder.of(dir2); + ModuleFinder finder3 = ModuleFinder.of(dir3); + + ModuleFinder finder = ModuleFinder.compose(finder1, finder2, finder3); + assertTrue(finder.findAll().size() == 6); + assertTrue(finder.find("m1").isPresent()); + assertTrue(finder.find("m2").isPresent()); + assertTrue(finder.find("m3").isPresent()); + assertTrue(finder.find("m4").isPresent()); + assertTrue(finder.find("m5").isPresent()); + assertTrue(finder.find("m6").isPresent()); assertFalse(finder.find("java.rhubarb").isPresent()); + + // check that m1@1.0 is found + ModuleDescriptor m1 = finder.find("m1").get().descriptor(); + assertEquals(m1.version().get().toString(), "1.0"); + + // check that m2@1.0 is found + ModuleDescriptor m2 = finder.find("m2").get().descriptor(); + assertEquals(m2.version().get().toString(), "1.0"); + + // check that m3@2.0 is found + ModuleDescriptor m3 = finder.find("m3").get().descriptor(); + assertEquals(m3.version().get().toString(), "2.0"); + + // check that m4@2.0 is found + ModuleDescriptor m4 = finder.find("m4").get().descriptor(); + assertEquals(m4.version().get().toString(), "2.0"); } @@ -503,33 +573,45 @@ public class ModuleFinderTest { */ public void testNulls() { + // ofSystem try { ModuleFinder.ofSystem().find(null); assertTrue(false); } catch (NullPointerException expected) { } + // of + Path dir = Paths.get("d"); try { ModuleFinder.of().find(null); assertTrue(false); } catch (NullPointerException expected) { } - try { - ModuleFinder.empty().find(null); + ModuleFinder.of((Path)null); assertTrue(false); } catch (NullPointerException expected) { } - try { ModuleFinder.of((Path[])null); assertTrue(false); } catch (NullPointerException expected) { } - try { - ModuleFinder.of((Path)null); + ModuleFinder.of(dir, null); + assertTrue(false); + } catch (NullPointerException expected) { } + try { + ModuleFinder.of(null, dir); assertTrue(false); } catch (NullPointerException expected) { } // compose ModuleFinder finder = ModuleFinder.of(); + try { + ModuleFinder.compose((ModuleFinder)null); + assertTrue(false); + } catch (NullPointerException expected) { } + try { + ModuleFinder.compose((ModuleFinder[])null); + assertTrue(false); + } catch (NullPointerException expected) { } try { ModuleFinder.compose(finder, null); assertTrue(false); diff --git a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java index ecaf6f45dff..cdeb61b899a 100644 --- a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java +++ b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import java.io.InputStream; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReader; import java.lang.module.ModuleReference; +import java.lang.reflect.Module; import java.net.URI; import java.net.URL; import java.net.URLConnection; @@ -64,16 +65,24 @@ public class ModuleReaderTest { private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); private static final Path MODS_DIR = Paths.get("mods"); + // the module name of the base module + private static final String BASE_MODULE = "java.base"; + // the module name of the test module private static final String TEST_MODULE = "m"; + // resources in the base module + private static final String[] BASE_RESOURCES = { + "java/lang/Object.class" + }; + // resources in test module (can't use module-info.class as a test // resource as it will be modified by the jmod tool) - private static final String[] RESOURCES = { + private static final String[] TEST_RESOURCES = { "p/Main.class" }; - // a resource that is not in the test module + // a resource that is not in the base or test module private static final String NOT_A_RESOURCE = "NotAResource"; @@ -89,7 +98,74 @@ public class ModuleReaderTest { /** - * Test exploded module + * Test ModuleReader to module in runtime image + */ + public void testImage() throws Exception { + + ModuleFinder finder = ModuleFinder.ofSystem(); + ModuleReference mref = finder.find(BASE_MODULE).get(); + ModuleReader reader = mref.open(); + + try (reader) { + + for (String name : BASE_RESOURCES) { + byte[] expectedBytes; + Module baseModule = Object.class.getModule(); + try (InputStream in = baseModule.getResourceAsStream(name)) { + expectedBytes = in.readAllBytes(); + } + + testFind(reader, name, expectedBytes); + testOpen(reader, name, expectedBytes); + testRead(reader, name, expectedBytes); + + } + + // test "not found" + assertFalse(reader.find(NOT_A_RESOURCE).isPresent()); + assertFalse(reader.open(NOT_A_RESOURCE).isPresent()); + assertFalse(reader.read(NOT_A_RESOURCE).isPresent()); + + + // test nulls + try { + reader.find(null); + assertTrue(false); + } catch (NullPointerException expected) { } + + try { + reader.open(null); + assertTrue(false); + } catch (NullPointerException expected) { } + + try { + reader.read(null); + assertTrue(false); + } catch (NullPointerException expected) { } + + try { + reader.release(null); + assertTrue(false); + } catch (NullPointerException expected) { } + + } + + // test closed ModuleReader + try { + reader.open(BASE_RESOURCES[0]); + assertTrue(false); + } catch (IOException expected) { } + + + try { + reader.read(BASE_RESOURCES[0]); + assertTrue(false); + } catch (IOException expected) { } + } + + + /** + * Test ModuleReader to exploded module */ public void testExplodedModule() throws Exception { test(MODS_DIR); @@ -97,7 +173,7 @@ public class ModuleReaderTest { /** - * Test modular JAR + * Test ModuleReader to modular JAR */ public void testModularJar() throws Exception { Path dir = Files.createTempDirectory(USER_DIR, "mlib"); @@ -111,7 +187,7 @@ public class ModuleReaderTest { /** - * Test JMOD + * Test ModuleReader to JMOD */ public void testJMod() throws Exception { Path dir = Files.createTempDirectory(USER_DIR, "mlib"); @@ -145,7 +221,7 @@ public class ModuleReaderTest { try (reader) { // test each of the known resources in the module - for (String name : RESOURCES) { + for (String name : TEST_RESOURCES) { byte[] expectedBytes = Files.readAllBytes(MODS_DIR .resolve(TEST_MODULE) @@ -157,6 +233,7 @@ public class ModuleReaderTest { } // test "not found" + assertFalse(reader.find(NOT_A_RESOURCE).isPresent()); assertFalse(reader.open(NOT_A_RESOURCE).isPresent()); assertFalse(reader.read(NOT_A_RESOURCE).isPresent()); @@ -176,19 +253,22 @@ public class ModuleReaderTest { assertTrue(false); } catch (NullPointerException expected) { } - // should release(null) throw NPE? + try { + reader.release(null); + throw new RuntimeException(); + } catch (NullPointerException expected) { } } // test closed ModuleReader try { - reader.open(RESOURCES[0]); + reader.open(TEST_RESOURCES[0]); assertTrue(false); } catch (IOException expected) { } try { - reader.read(RESOURCES[0]); + reader.read(TEST_RESOURCES[0]); assertTrue(false); } catch (IOException expected) { } } diff --git a/jdk/test/java/lang/module/ModuleReader/MultiReleaseJarTest.java b/jdk/test/java/lang/module/ModuleReader/MultiReleaseJarTest.java new file mode 100644 index 00000000000..4bb6ceaf34f --- /dev/null +++ b/jdk/test/java/lang/module/ModuleReader/MultiReleaseJarTest.java @@ -0,0 +1,216 @@ +/* + * 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 + * @library /lib/testlibrary + * @modules java.base/jdk.internal.module + * @build MultiReleaseJarTest JarUtils + * @run testng MultiReleaseJarTest + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarTest + * @summary Basic test of ModuleReader with a modular JAR that is also a + * multi-release JAR + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.net.URI; +import java.net.URLConnection; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.Manifest; +import java.util.stream.Collectors; + +import jdk.internal.module.ModuleInfoWriter; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * Exercises ModuleReader with a modular JAR containing the following files: + * + *
    {@code
    + *     module-info.class
    + *     META-INF/versions//module.class
    + * }
    + * + * The module-info.class in the top-level directory is the binary form of: + *
    {@code
    + *     module jdk.test {
    + *         requires java.base;
    + *     }
    + * }
    + * + * The module-info.class in the versioned section is the binary form of: + *
    {@code
    + *     module jdk.test {
    + *         requires java.base;
    + *         requires jdk.unsupported;
    + *     }
    + * }
    + */ + +@Test +public class MultiReleaseJarTest { + + // Java SE/JDK major release + private static final int RELEASE = Runtime.version().major(); + + // the name of the test module + private static final String MODULE_NAME = "jdk.test"; + + private static final String MODULE_INFO_CLASS = "module-info.class"; + + /** + * Uses the ModuleFinder API to locate the module packaged as a modular + * and mutli-release JAR and then creates a ModuleReader to access the + * contents of the module. + */ + public void testMultiReleaseJar() throws IOException { + + // are multi-release JARs enabled? + String s = System.getProperty("jdk.util.jar.enableMultiRelease"); + boolean multiRelease = (s == null || Boolean.parseBoolean(s)); + + // create the multi-release modular JAR + Path jarfile = createJarFile(); + + // find the module + ModuleFinder finder = ModuleFinder.of(jarfile); + Optional omref = finder.find(MODULE_NAME); + assertTrue((omref.isPresent())); + ModuleReference mref = omref.get(); + + // test that correct module-info.class was read + checkDescriptor(mref.descriptor(), multiRelease); + + // test ModuleReader + try (ModuleReader reader = mref.open()) { + + // open resource + Optional oin = reader.open(MODULE_INFO_CLASS); + assertTrue(oin.isPresent()); + try (InputStream in = oin.get()) { + checkDescriptor(ModuleDescriptor.read(in), multiRelease); + } + + // read resource + Optional obb = reader.read(MODULE_INFO_CLASS); + assertTrue(obb.isPresent()); + ByteBuffer bb = obb.get(); + try { + checkDescriptor(ModuleDescriptor.read(bb), multiRelease); + } finally { + reader.release(bb); + } + + // find resource + Optional ouri = reader.find(MODULE_INFO_CLASS); + assertTrue(ouri.isPresent()); + URI uri = ouri.get(); + + String expectedTail = "!/"; + if (multiRelease) + expectedTail += "META-INF/versions/" + RELEASE + "/"; + expectedTail += MODULE_INFO_CLASS; + assertTrue(uri.toString().endsWith(expectedTail)); + + URLConnection uc = uri.toURL().openConnection(); + uc.setUseCaches(false); + try (InputStream in = uc.getInputStream()) { + checkDescriptor(ModuleDescriptor.read(in), multiRelease); + } + + } + + } + + /** + * Checks that the module descriptor is the expected module descriptor. + * When the multi release JAR feature is enabled then the module + * descriptor is expected to have been read from the versioned section + * of the JAR file. + */ + private void checkDescriptor(ModuleDescriptor descriptor, boolean multiRelease) { + Set requires = descriptor.requires().stream() + .map(ModuleDescriptor.Requires::name) + .collect(Collectors.toSet()); + assertTrue(requires.contains("java.base")); + assertTrue(requires.contains("jdk.unsupported") == multiRelease); + } + + /** + * Creates the modular JAR for the test, returning the Path to the JAR file. + */ + private Path createJarFile() throws IOException { + + // module descriptor for top-level directory + ModuleDescriptor descriptor1 + = new ModuleDescriptor.Builder(MODULE_NAME) + .requires("java.base") + .build(); + + // module descriptor for versioned section + ModuleDescriptor descriptor2 + = new ModuleDescriptor.Builder(MODULE_NAME) + .requires("java.base") + .requires("jdk.unsupported") + .build(); + + Path top = Paths.get(MODULE_NAME); + Files.createDirectories(top); + + Path mi1 = Paths.get(MODULE_INFO_CLASS); + try (OutputStream out = Files.newOutputStream(top.resolve(mi1))) { + ModuleInfoWriter.write(descriptor1, out); + } + + Path vdir = Paths.get("META-INF", "versions", Integer.toString(RELEASE)); + Files.createDirectories(top.resolve(vdir)); + + Path mi2 = vdir.resolve(MODULE_INFO_CLASS); + try (OutputStream out = Files.newOutputStream(top.resolve(mi2))) { + ModuleInfoWriter.write(descriptor2, out); + } + + Manifest man = new Manifest(); + Attributes attrs = man.getMainAttributes(); + attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0"); + attrs.put(Attributes.Name.MULTI_RELEASE, "true"); + + Path jarfile = Paths.get(MODULE_NAME + ".jar"); + JarUtils.createJarFile(jarfile, man, top, mi1, mi2); + + return jarfile; + } +} diff --git a/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java b/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java index f54a320a3f8..1241f235325 100644 --- a/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java +++ b/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java @@ -33,7 +33,6 @@ import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; -import static java.lang.module.ModuleFinder.empty; import java.lang.reflect.Layer; import java.lang.reflect.LayerInstantiationException; import java.lang.reflect.Module; @@ -104,7 +103,7 @@ public class BasicLayerTest { /** - * Exercise Layer.create, created on an empty layer + * Exercise Layer defineModules, created with empty layer as parent */ public void testLayerOnEmpty() { ModuleDescriptor descriptor1 @@ -185,7 +184,7 @@ public class BasicLayerTest { /** - * Exercise Layer.create, created over the boot layer + * Exercise Layer defineModules, created with boot layer as parent */ public void testLayerOnBoot() { ModuleDescriptor descriptor1 @@ -248,8 +247,8 @@ public class BasicLayerTest { /** - * Layer.create with a configuration of two modules that have the same - * module-private package. + * Exercise Layer defineModules with a configuration of two modules that + * have the same module-private package. */ public void testSameConcealedPackage() { ModuleDescriptor descriptor1 @@ -282,8 +281,8 @@ public class BasicLayerTest { /** - * Layer.create with a configuration with a partitioned graph. The same - * package is exported in both partitions. + * Exercise Layer defineModules with a configuration that is a partitioned + * graph. The same package is exported in both partitions. */ public void testSameExportInPartitionedGraph() { @@ -339,9 +338,9 @@ public class BasicLayerTest { /** - * Layer.create with a configuration that contains a module that has a - * concealed package that is the same name as a non-exported package - * in a parent layer. + * Exercise Layer defineModules with a configuration that contains a module + * that has a concealed package that is the same name as a non-exported + * package in a parent layer. */ public void testConcealSamePackageAsBootLayer() { @@ -358,7 +357,7 @@ public class BasicLayerTest { ModuleFinder finder = ModuleUtils.finderOf(descriptor); Configuration parent = Layer.boot().configuration(); - Configuration cf = parent.resolveRequires(finder, empty(), Set.of("m1")); + Configuration cf = parent.resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); assertTrue(cf.modules().size() == 1); ClassLoader loader = new ClassLoader() { }; @@ -668,9 +667,9 @@ public class BasicLayerTest { /** - * Attempt to use Layer.create to create a layer with a module defined to a - * class loader that already has a module of the same name defined to the - * class loader. + * Attempt to use Layer defineModules to create a layer with a module + * defined to a class loader that already has a module of the same name + * defined to the class loader. */ @Test(expectedExceptions = { LayerInstantiationException.class }) public void testModuleAlreadyDefinedToLoader() { @@ -684,7 +683,7 @@ public class BasicLayerTest { Configuration parent = Layer.boot().configuration(); - Configuration cf = parent.resolveRequires(finder, empty(), Set.of("m")); + Configuration cf = parent.resolveRequires(finder, ModuleFinder.of(), Set.of("m")); ClassLoader loader = new ClassLoader() { }; @@ -697,9 +696,9 @@ public class BasicLayerTest { /** - * Attempt to use Layer.create to create a Layer with a module containing - * package {@code p} where the class loader already has a module defined - * to it containing package {@code p}. + * Attempt to use Layer defineModules to create a Layer with a module + * containing package {@code p} where the class loader already has a module + * defined to it containing package {@code p}. */ @Test(expectedExceptions = { LayerInstantiationException.class }) public void testPackageAlreadyInNamedModule() { @@ -724,13 +723,13 @@ public class BasicLayerTest { Configuration parent = Layer.boot().configuration(); - Configuration cf1 = parent.resolveRequires(finder, empty(), Set.of("m1")); + Configuration cf1 = parent.resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); Layer layer1 = Layer.boot().defineModules(cf1, mn -> loader); // attempt to define m2 containing package p to class loader - Configuration cf2 = parent.resolveRequires(finder, empty(), Set.of("m2")); + Configuration cf2 = parent.resolveRequires(finder, ModuleFinder.of(), Set.of("m2")); // should throw exception because p already in m1 Layer layer2 = Layer.boot().defineModules(cf2, mn -> loader); @@ -739,8 +738,9 @@ public class BasicLayerTest { /** - * Attempt to use Layer.create to create a Layer with a module containing - * a package in which a type is already loaded by the class loader. + * Attempt to use Layer defineModules to create a Layer with a module + * containing a package in which a type is already loaded by the class + * loader. */ @Test(expectedExceptions = { LayerInstantiationException.class }) public void testPackageAlreadyInUnnamedModule() throws Exception { @@ -757,12 +757,52 @@ public class BasicLayerTest { ModuleFinder finder = ModuleUtils.finderOf(md); Configuration parent = Layer.boot().configuration(); - Configuration cf = parent.resolveRequires(finder, empty(), Set.of("m")); + Configuration cf = parent.resolveRequires(finder, ModuleFinder.of(), Set.of("m")); Layer.boot().defineModules(cf, mn -> c.getClassLoader()); } + /** + * Attempt to create a Layer with a module named "java.base". + */ + public void testLayerWithJavaBase() { + ModuleDescriptor descriptor + = new ModuleDescriptor.Builder("java.base") + .exports("java.lang") + .build(); + + ModuleFinder finder = ModuleUtils.finderOf(descriptor); + + Configuration cf = Layer.boot() + .configuration() + .resolveRequires(finder, ModuleFinder.of(), Set.of("java.base")); + assertTrue(cf.modules().size() == 1); + + ClassLoader scl = ClassLoader.getSystemClassLoader(); + + try { + Layer.boot().defineModules(cf, loader -> null ); + assertTrue(false); + } catch (LayerInstantiationException e) { } + + try { + Layer.boot().defineModules(cf, loader -> new ClassLoader() { }); + assertTrue(false); + } catch (LayerInstantiationException e) { } + + try { + Layer.boot().defineModulesWithOneLoader(cf, scl); + assertTrue(false); + } catch (LayerInstantiationException e) { } + + try { + Layer.boot().defineModulesWithManyLoaders(cf, scl); + assertTrue(false); + } catch (LayerInstantiationException e) { } + } + + /** * Parent of configuration != configuration of parent Layer */ @@ -777,7 +817,7 @@ public class BasicLayerTest { ModuleFinder finder = ModuleUtils.finderOf(descriptor1); Configuration parent = Layer.boot().configuration(); - Configuration cf = parent.resolveRequires(finder, empty(), Set.of("m1")); + Configuration cf = parent.resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); ClassLoader loader = new ClassLoader() { }; Layer.empty().defineModules(cf, mn -> loader); @@ -813,8 +853,7 @@ public class BasicLayerTest { @Test(expectedExceptions = { NullPointerException.class }) public void testCreateWithNull2() { - ClassLoader loader = new ClassLoader() { }; - Configuration cf = resolveRequires(Layer.boot().configuration(), empty()); + Configuration cf = resolveRequires(Layer.boot().configuration(), ModuleFinder.of()); Layer.boot().defineModules(cf, null); } @@ -857,7 +896,7 @@ public class BasicLayerTest { private static Configuration resolveRequires(Configuration cf, ModuleFinder finder, String... roots) { - return cf.resolveRequires(finder, empty(), Set.of(roots)); + return cf.resolveRequires(finder, ModuleFinder.of(), Set.of(roots)); } private static Configuration resolveRequires(ModuleFinder finder, diff --git a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java index b37813fd290..a7dea9961cc 100644 --- a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java +++ b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java @@ -24,6 +24,7 @@ /** * @test * @library /lib/testlibrary + * @modules jdk.compiler * @build LayerAndLoadersTest CompilerUtils ModuleUtils * @run testng LayerAndLoadersTest * @summary Tests for java.lang.reflect.Layer@createWithXXX methods @@ -32,7 +33,6 @@ import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; -import static java.lang.module.ModuleFinder.empty; import java.lang.module.ModuleReference; import java.lang.reflect.Layer; import java.lang.reflect.LayerInstantiationException; @@ -70,7 +70,7 @@ public class LayerAndLoadersTest { /** - * Basic test of Layer.createWithOneLoader + * Basic test of Layer defineModulesWithOneLoader * * Test scenario: * m1 requires m2 and m3 @@ -99,7 +99,7 @@ public class LayerAndLoadersTest { /** - * Basic test of Layer.createWithManyLoaders + * Basic test of Layer defineModulesWithManyLoaders * * Test scenario: * m1 requires m2 and m3 @@ -131,7 +131,7 @@ public class LayerAndLoadersTest { /** - * Basic test of Layer.createWithOneLoader where one of the modules + * Basic test of Layer defineModulesWithOneLoader where one of the modules * is a service provider module. * * Test scenario: @@ -172,8 +172,8 @@ public class LayerAndLoadersTest { /** - * Basic test of Layer.createWithManyLoaders where one of the modules - * is a service provider module. + * Basic test of Layer defineModulesWithManyLoaders where one of the + * modules is a service provider module. * * Test scenario: * m1 requires m2 and m3 @@ -224,7 +224,7 @@ public class LayerAndLoadersTest { /** - * Tests that the class loaders created by Layer.createWithXXX delegate + * Tests that the class loaders created by defineModulesWithXXX delegate * to the given parent class loader. */ public void testDelegationToParent() throws Exception { @@ -254,7 +254,7 @@ public class LayerAndLoadersTest { /** - * Test Layer.createWithXXX when modules that have overlapping packages. + * Test defineModulesWithXXX when modules that have overlapping packages. * * Test scenario: * m1 exports p @@ -272,7 +272,7 @@ public class LayerAndLoadersTest { Configuration cf = Layer.boot() .configuration() - .resolveRequires(finder, empty(), Set.of("m1", "m2")); + .resolveRequires(finder, ModuleFinder.of(), Set.of("m1", "m2")); // cannot define both module m1 and m2 to the same class loader try { @@ -288,7 +288,7 @@ public class LayerAndLoadersTest { /** - * Test Layer.createWithXXX with split delegation. + * Test Layer defineModulesWithXXX with split delegation. * * Test scenario: * layer1: m1 exports p, m2 exports p @@ -306,7 +306,7 @@ public class LayerAndLoadersTest { Configuration cf1 = Layer.boot() .configuration() - .resolveRequires(finder1, empty(), Set.of("m1", "m2")); + .resolveRequires(finder1, ModuleFinder.of(), Set.of("m1", "m2")); Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, null); checkLayer(layer1, "m1", "m2"); @@ -319,7 +319,8 @@ public class LayerAndLoadersTest { ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4); - Configuration cf2 = cf1.resolveRequires(finder2, empty(), Set.of("m3", "m4")); + Configuration cf2 = cf1.resolveRequires(finder2, ModuleFinder.of(), + Set.of("m3", "m4")); // package p cannot be supplied by two class loaders try { @@ -335,8 +336,8 @@ public class LayerAndLoadersTest { /** - * Test Layer.createWithXXX when the modules that override same named - * modules in the parent layer. + * Test Layer defineModulesWithXXX when the modules that override same + * named modules in the parent layer. * * Test scenario: * layer1: m1, m2, m3 => same loader @@ -350,7 +351,8 @@ public class LayerAndLoadersTest { checkLayer(layer1, "m1", "m2", "m3"); ModuleFinder finder = ModuleFinder.of(MODS_DIR); - Configuration cf2 = cf1.resolveRequires(finder, empty(), Set.of("m1")); + Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), + Set.of("m1")); Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null); checkLayer(layer2, "m1", "m2", "m3"); @@ -383,8 +385,8 @@ public class LayerAndLoadersTest { /** - * Test Layer.createWithXXX when the modules that override same named - * modules in the parent layer. + * Test Layer defineModulesWithXXX when the modules that override same + * named modules in the parent layer. * * Test scenario: * layer1: m1, m2, m3 => loader pool @@ -398,7 +400,8 @@ public class LayerAndLoadersTest { checkLayer(layer1, "m1", "m2", "m3"); ModuleFinder finder = ModuleFinder.of(MODS_DIR); - Configuration cf2 = cf1.resolveRequires(finder, empty(), Set.of("m1")); + Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), + Set.of("m1")); Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); checkLayer(layer2, "m1", "m2", "m3"); @@ -477,8 +480,8 @@ public class LayerAndLoadersTest { /** - * Test Layer.createWithXXX when the modules that override same named - * modules in the parent layer. + * Test Layer defineModulesWithXXX when the modules that override same + * named modules in the parent layer. * * layer1: m1, m2, m3 => same loader * layer2: m1, m3 => same loader @@ -492,7 +495,8 @@ public class LayerAndLoadersTest { ModuleFinder finder = finderFor("m1", "m3"); - Configuration cf2 = cf1.resolveRequires(finder, empty(), Set.of("m1")); + Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), + Set.of("m1")); Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null); checkLayer(layer2, "m1", "m3"); @@ -513,8 +517,8 @@ public class LayerAndLoadersTest { /** - * Test Layer.createWithXXX when the modules that override same named - * modules in the parent layer. + * Test Layer defineModulesWithXXX when the modules that override same + * named modules in the parent layer. * * layer1: m1, m2, m3 => loader pool * layer2: m1, m3 => loader pool @@ -528,7 +532,8 @@ public class LayerAndLoadersTest { ModuleFinder finder = finderFor("m1", "m3"); - Configuration cf2 = cf1.resolveRequires(finder, empty(), Set.of("m1")); + Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), + Set.of("m1")); Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); checkLayer(layer2, "m1", "m3"); @@ -574,7 +579,7 @@ public class LayerAndLoadersTest { ModuleFinder finder = ModuleFinder.of(MODS_DIR); return Layer.boot() .configuration() - .resolveRequires(finder, empty(), Set.of(roots)); + .resolveRequires(finder, ModuleFinder.of(), Set.of(roots)); } /** @@ -585,7 +590,7 @@ public class LayerAndLoadersTest { ModuleFinder finder = ModuleFinder.of(MODS_DIR); return Layer.boot() .configuration() - .resolveRequiresAndUses(finder, empty(), Set.of(roots)); + .resolveRequiresAndUses(finder, ModuleFinder.of(), Set.of(roots)); } diff --git a/jdk/test/java/lang/reflect/Module/WithSecurityManager.java b/jdk/test/java/lang/reflect/Module/WithSecurityManager.java new file mode 100644 index 00000000000..9c95fee5113 --- /dev/null +++ b/jdk/test/java/lang/reflect/Module/WithSecurityManager.java @@ -0,0 +1,147 @@ +/* + * 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 + * @modules java.logging + * @summary Test java.lang.reflect.Module methods that specify permission checks + * @run main/othervm -Djava.security.policy=${test.src}/allow.policy WithSecurityManager allow + * @run main/othervm WithSecurityManager deny + */ + +import java.io.IOException; +import java.io.InputStream; +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReference; +import java.lang.reflect.Layer; +import java.lang.reflect.Module; +import java.util.Collections; +import java.util.Optional; +import java.util.Set; + +/** + * Test java.lang.reflect.Module methods that specify permission checks. + */ + +public class WithSecurityManager { + + // a module that will be loaded into a child layer + static final String ANOTHER_MODULE = "java.logging"; + static final String ANOTHER_MODULE_RESOURCE = "java/util/logging/Logger.class"; + + public static void main(String[] args) throws IOException { + boolean allow = args[0].equals("allow"); + + // base module, in the boot layer + Module base = Object.class.getModule(); + + // another module, in a child layer + Module other = loadModuleInChildLayer(ANOTHER_MODULE); + assertTrue(other.getLayer() != Layer.boot()); + + System.setSecurityManager(new SecurityManager()); + + test(base, "java/lang/Object.class", allow); + test(other, ANOTHER_MODULE_RESOURCE, allow); + } + + /** + * Test the permission checks by invoking methods on the given module. + * + * If {@code allow} is {@code true} then the permission checks should succeed. + */ + static void test(Module m, String name, boolean allow) throws IOException { + + // test Module::getClassLoader + System.out.format("Test getClassLoader on %s ...%n", m); + try { + ClassLoader cl = m.getClassLoader(); + System.out.println(cl); + if (!allow) + assertTrue("getClassLoader should have failed", false); + } catch (SecurityException e) { + System.out.println(e + " thrown"); + if (allow) + throw e; + } + + // test Module::getResourceAsStream + System.out.format("Test getResourceAsStream(\"%s\") on %s ...%n", name, m); + try (InputStream in = m.getResourceAsStream(name)) { + System.out.println(in); + if (allow && (in == null)) + assertTrue(name + " not found", false); + if (!allow && (in != null)) + assertTrue(name + " should not be found", false); + } + + } + + /** + * Create a module layer that contains the given system module. + */ + static Module loadModuleInChildLayer(String mn) { + Optional omref = ModuleFinder.ofSystem().find(mn); + assertTrue("module " + mn + " not a system module", omref.isPresent()); + + // create a ModuleFinder that only finds this module + ModuleReference mref = omref.get(); + ModuleFinder finder = new ModuleFinder() { + @Override + public Optional find(String name) { + if (name.equals(mn)) + return Optional.of(mref); + else + return Optional.empty(); + } + + @Override + public Set findAll() { + return Collections.singleton(mref); + } + }; + + // create a child configuration and layer with this module + Layer bootLayer = Layer.boot(); + Configuration cf = bootLayer + .configuration() + .resolveRequires(finder, ModuleFinder.of(), Set.of(ANOTHER_MODULE)); + Layer layer = bootLayer.defineModulesWithOneLoader(cf, null); + + Optional om = layer.findModule(mn); + assertTrue("module " + mn + " not in child layer", om.isPresent()); + return om.get(); + } + + static void assertTrue(String msg, boolean e) { + if (!e) + throw new RuntimeException(msg); + } + + static void assertTrue(boolean e) { + if (!e) + throw new RuntimeException(); + } + +} \ No newline at end of file diff --git a/jdk/test/java/lang/reflect/Module/allow.policy b/jdk/test/java/lang/reflect/Module/allow.policy new file mode 100644 index 00000000000..08998cfa728 --- /dev/null +++ b/jdk/test/java/lang/reflect/Module/allow.policy @@ -0,0 +1,27 @@ +/* + * 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. + */ + +grant { + permission java.lang.RuntimePermission "getClassLoader"; + permission java.io.FilePermission "${java.home}/-", "read"; +}; diff --git a/jdk/test/java/lang/reflect/Proxy/ProxyClassAccessTest.java b/jdk/test/java/lang/reflect/Proxy/ProxyClassAccessTest.java index 529f294401d..fcc673909fa 100644 --- a/jdk/test/java/lang/reflect/Proxy/ProxyClassAccessTest.java +++ b/jdk/test/java/lang/reflect/Proxy/ProxyClassAccessTest.java @@ -91,7 +91,7 @@ public class ProxyClassAccessTest { Layer bootLayer = Layer.boot(); Configuration cf = bootLayer .configuration() - .resolveRequiresAndUses(ModuleFinder.empty(), finder, modules); + .resolveRequiresAndUses(ModuleFinder.of(), finder, modules); ClassLoader parentLoader = this.getClass().getClassLoader(); Layer layer = bootLayer.defineModulesWithOneLoader(cf, parentLoader); diff --git a/jdk/test/java/lang/reflect/Proxy/ProxyLayerTest.java b/jdk/test/java/lang/reflect/Proxy/ProxyLayerTest.java index 4ee43ea11c1..37c0bd59b23 100644 --- a/jdk/test/java/lang/reflect/Proxy/ProxyLayerTest.java +++ b/jdk/test/java/lang/reflect/Proxy/ProxyLayerTest.java @@ -79,7 +79,7 @@ public class ProxyLayerTest { Layer bootLayer = Layer.boot(); Configuration cf = bootLayer .configuration() - .resolveRequiresAndUses(ModuleFinder.empty(), finder, Arrays.asList(modules)); + .resolveRequiresAndUses(ModuleFinder.of(), finder, Arrays.asList(modules)); ClassLoader scl = ClassLoader.getSystemClassLoader(); Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl); @@ -113,7 +113,7 @@ public class ProxyLayerTest { Layer bootLayer = Layer.boot(); Configuration cf = bootLayer .configuration() - .resolveRequiresAndUses(ModuleFinder.empty(), finder, Arrays.asList(modules)); + .resolveRequiresAndUses(ModuleFinder.of(), finder, Arrays.asList(modules)); ClassLoader scl = ClassLoader.getSystemClassLoader(); Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl); @@ -143,7 +143,7 @@ public class ProxyLayerTest { Layer bootLayer = Layer.boot(); Configuration cf = bootLayer .configuration() - .resolveRequiresAndUses(ModuleFinder.empty(), finder, Arrays.asList(modules)); + .resolveRequiresAndUses(ModuleFinder.of(), finder, Arrays.asList(modules)); ClassLoader scl = ClassLoader.getSystemClassLoader(); Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl); diff --git a/jdk/test/java/math/BigDecimal/SquareRootTests.java b/jdk/test/java/math/BigDecimal/SquareRootTests.java new file mode 100644 index 00000000000..1ad72d0f8ea --- /dev/null +++ b/jdk/test/java/math/BigDecimal/SquareRootTests.java @@ -0,0 +1,227 @@ +/* + * 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 4851777 + * @summary Tests of BigDecimal.sqrt(). + */ + +import java.math.*; +import java.util.*; + +public class SquareRootTests { + + public static void main(String... args) { + int failures = 0; + + failures += negativeTests(); + failures += zeroTests(); + failures += evenPowersOfTenTests(); + failures += squareRootTwoTests(); + failures += lowPrecisionPerfectSquares(); + + if (failures > 0 ) { + throw new RuntimeException("Incurred " + failures + " failures" + + " testing BigDecimal.sqrt()."); + } + } + + private static int negativeTests() { + int failures = 0; + + for (long i = -10; i < 0; i++) { + for (int j = -5; j < 5; j++) { + try { + BigDecimal input = BigDecimal.valueOf(i, j); + BigDecimal result = input.sqrt(MathContext.DECIMAL64); + System.err.println("Unexpected sqrt of negative: (" + + input + ").sqrt() = " + result ); + failures += 1; + } catch (ArithmeticException e) { + ; // Expected + } + } + } + + return failures; + } + + private static int zeroTests() { + int failures = 0; + + for (int i = -100; i < 100; i++) { + BigDecimal expected = BigDecimal.valueOf(0L, i/2); + // These results are independent of rounding mode + failures += compare(BigDecimal.valueOf(0L, i).sqrt(MathContext.UNLIMITED), + expected, true, "zeros"); + + failures += compare(BigDecimal.valueOf(0L, i).sqrt(MathContext.DECIMAL64), + expected, true, "zeros"); + } + + return failures; + } + + /** + * sqrt(10^2N) is 10^N + * Both numerical value and representation should be verified + */ + private static int evenPowersOfTenTests() { + int failures = 0; + MathContext oneDigitExactly = new MathContext(1, RoundingMode.UNNECESSARY); + + for (int scale = -100; scale <= 100; scale++) { + BigDecimal testValue = BigDecimal.valueOf(1, 2*scale); + BigDecimal expectedNumericalResult = BigDecimal.valueOf(1, scale); + + BigDecimal result; + + + failures += equalNumerically(expectedNumericalResult, + result = testValue.sqrt(MathContext.DECIMAL64), + "Even powers of 10, DECIMAL64"); + + // Can round to one digit of precision exactly + failures += equalNumerically(expectedNumericalResult, + result = testValue.sqrt(oneDigitExactly), + "even powers of 10, 1 digit"); + if (result.precision() > 1) { + failures += 1; + System.err.println("Excess precision for " + result); + } + + + // If rounding to more than one digit, do precision / scale checking... + + } + + return failures; + } + + private static int squareRootTwoTests() { + int failures = 0; + BigDecimal TWO = new BigDecimal(2); + + // Square root of 2 truncated to 65 digits + BigDecimal highPrecisionRoot2 = + new BigDecimal("1.41421356237309504880168872420969807856967187537694807317667973799"); + + + RoundingMode[] modes = { + RoundingMode.UP, RoundingMode.DOWN, + RoundingMode.CEILING, RoundingMode.FLOOR, + RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN + }; + + // For each iteresting rounding mode, for precisions 1 to, say + // 63 numerically compare TWO.sqrt(mc) to + // highPrecisionRoot2.round(mc) + + for (RoundingMode mode : modes) { + for (int precision = 1; precision < 63; precision++) { + MathContext mc = new MathContext(precision, mode); + BigDecimal expected = highPrecisionRoot2.round(mc); + BigDecimal computed = TWO.sqrt(mc); + + equalNumerically(expected, computed, "sqrt(2)"); + } + } + + return failures; + } + + private static int lowPrecisionPerfectSquares() { + int failures = 0; + + // For 5^2 through 9^2, if the input is rounded to one digit + // first before the root is computed, the wrong answer will + // result. Verify results and scale for different rounding + // modes and precisions. + long[][] squaresWithOneDigitRoot = {{ 4, 2}, + { 9, 3}, + {25, 5}, + {36, 6}, + {49, 7}, + {64, 8}, + {81, 9}}; + + for (long[] squareAndRoot : squaresWithOneDigitRoot) { + BigDecimal square = new BigDecimal(squareAndRoot[0]); + BigDecimal expected = new BigDecimal(squareAndRoot[1]); + + for (int scale = 0; scale <= 4; scale++) { + BigDecimal scaledSquare = square.setScale(scale, RoundingMode.UNNECESSARY); + int expectedScale = scale/2; + for (int precision = 0; precision <= 5; precision++) { + for (RoundingMode rm : RoundingMode.values()) { + MathContext mc = new MathContext(precision, rm); + BigDecimal computedRoot = scaledSquare.sqrt(mc); + failures += equalNumerically(expected, computedRoot, "simple squares"); + int computedScale = computedRoot.scale(); + if (precision >= expectedScale + 1 && + computedScale != expectedScale) { + System.err.printf("%s\tprecision=%d\trm=%s%n", + computedRoot.toString(), precision, rm); + failures++; + System.err.printf("\t%s does not have expected scale of %d%n.", + computedRoot, expectedScale); + } + } + } + } + } + + return failures; + } + + private static int compare(BigDecimal a, BigDecimal b, boolean expected, String prefix) { + boolean result = a.equals(b); + int failed = (result==expected) ? 0 : 1; + if (failed == 1) { + System.err.println("Testing " + prefix + + "(" + a + ").compareTo(" + b + ") => " + result + + "\n\tExpected " + expected); + } + return failed; + } + + private static int equalNumerically(BigDecimal a, BigDecimal b, + String prefix) { + return compareNumerically(a, b, 0, prefix); + } + + + private static int compareNumerically(BigDecimal a, BigDecimal b, + int expected, String prefix) { + int result = a.compareTo(b); + int failed = (result==expected) ? 0 : 1; + if (failed == 1) { + System.err.println("Testing " + prefix + + "(" + a + ").compareTo(" + b + ") => " + result + + "\n\tExpected " + expected); + } + return failed; + } + +} diff --git a/jdk/test/java/net/DatagramSocket/PortUnreachable.java b/jdk/test/java/net/DatagramSocket/PortUnreachable.java index 91e68472af8..143c842d45e 100644 --- a/jdk/test/java/net/DatagramSocket/PortUnreachable.java +++ b/jdk/test/java/net/DatagramSocket/PortUnreachable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013 Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /** * @test * @bug 4361783 + * @key intermittent * @summary Test to see if ICMP Port Unreachable on non-connected * DatagramSocket causes a SocketException "socket closed" * exception on Windows 2000. diff --git a/jdk/test/java/net/Inet6Address/PreferIPv6AddressesTest.java b/jdk/test/java/net/Inet6Address/PreferIPv6AddressesTest.java new file mode 100644 index 00000000000..d028867bfb2 --- /dev/null +++ b/jdk/test/java/net/Inet6Address/PreferIPv6AddressesTest.java @@ -0,0 +1,132 @@ +/* + * 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 8016521 + * @summary InetAddress should not always re-order addresses returned from name + * service + * @run main/othervm -Djava.net.preferIPv6Addresses=false PreferIPv6AddressesTest + * @run main/othervm -Djava.net.preferIPv6Addresses=true PreferIPv6AddressesTest + * @run main/othervm -Djava.net.preferIPv6Addresses=system PreferIPv6AddressesTest + * @run main/othervm PreferIPv6AddressesTest + */ + +import java.io.IOException; +import java.net.*; +import java.nio.channels.DatagramChannel; +import java.util.Arrays; +import java.util.stream.IntStream; +import static java.lang.System.out; + +public class PreferIPv6AddressesTest { + + // A name, that if resolves, returns both IPv4 and IPv6 addresses. + static final String HOST_NAME = "www.google.com"; + + static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress(); + + static final String preferIPV6Address = + System.getProperty("java.net.preferIPv6Addresses", "false"); + + public static void main(String args[]) throws IOException { + + InetAddress addrs[]; + try { + addrs = InetAddress.getAllByName(HOST_NAME); + } catch (UnknownHostException e) { + out.println("Unknown host " + HOST_NAME + ", cannot run test."); + return; + } + + int firstIPv4Address = IntStream.range(0, addrs.length) + .filter(x -> addrs[x] instanceof Inet4Address) + .findFirst().orElse(-1); + int firstIPv6Address = IntStream.range(0, addrs.length) + .filter(x -> addrs[x] instanceof Inet6Address) + .findFirst().orElse(-1); + + out.println("IPv6 supported: " + IPv6Supported()); + out.println("Addresses: " + Arrays.asList(addrs)); + + if (preferIPV6Address.equalsIgnoreCase("true") && firstIPv6Address != -1) { + int off = firstIPv4Address != -1 ? firstIPv4Address : addrs.length; + assertAllv6Addresses(addrs, 0, off); + assertAllv4Addresses(addrs, off, addrs.length); + assertLoopbackAddress(Inet6Address.class); + assertAnyLocalAddress(Inet6Address.class); + } else if (preferIPV6Address.equalsIgnoreCase("false") && firstIPv4Address != -1) { + int off = firstIPv6Address != -1 ? firstIPv6Address : addrs.length; + assertAllv4Addresses(addrs, 0, off); + assertAllv6Addresses(addrs, off, addrs.length); + assertLoopbackAddress(Inet4Address.class); + assertAnyLocalAddress(Inet4Address.class); + } else if (preferIPV6Address.equalsIgnoreCase("system") && IPv6Supported()) { + assertLoopbackAddress(Inet6Address.class); + assertAnyLocalAddress(Inet6Address.class); + } else if (preferIPV6Address.equalsIgnoreCase("system") && !IPv6Supported()) { + assertLoopbackAddress(Inet4Address.class); + assertAnyLocalAddress(Inet4Address.class); + } + } + + static void assertAllv4Addresses(InetAddress[] addrs, int off, int len) { + IntStream.range(off, len) + .mapToObj(x -> addrs[x]) + .forEach(x -> { + if (!(x instanceof Inet4Address)) + throw new RuntimeException("Expected IPv4, got " + x); + }); + } + + static void assertAllv6Addresses(InetAddress[] addrs, int off, int len) { + IntStream.range(off, len) + .mapToObj(x -> addrs[x]) + .forEach(x -> { + if (!(x instanceof Inet6Address)) + throw new RuntimeException("Expected IPv6, got " + x); + }); + } + + static void assertLoopbackAddress(Class expectedType) { + if (!LOOPBACK.getClass().isAssignableFrom(expectedType)) + throw new RuntimeException("Expected " + expectedType + + ", got " + LOOPBACK.getClass()); + } + + static void assertAnyLocalAddress(Class expectedType) { + InetAddress anyAddr = (new InetSocketAddress(0)).getAddress(); + if (!anyAddr.getClass().isAssignableFrom(expectedType)) + throw new RuntimeException("Expected " + expectedType + + ", got " + anyAddr.getClass()); + } + + static boolean IPv6Supported() throws IOException { + try { + DatagramChannel.open(StandardProtocolFamily.INET6); + return true; + } catch (UnsupportedOperationException x) { + return false; + } + } +} diff --git a/jdk/test/java/net/InetAddress/IsReachableViaLoopbackTest.java b/jdk/test/java/net/InetAddress/IsReachableViaLoopbackTest.java index 4d7f266ec1d..5364ba7895e 100644 --- a/jdk/test/java/net/InetAddress/IsReachableViaLoopbackTest.java +++ b/jdk/test/java/net/InetAddress/IsReachableViaLoopbackTest.java @@ -5,6 +5,7 @@ import java.util.*; /** * @test * @bug 8135305 + * @key intermittent * @summary ensure we can't ping external hosts via loopback if */ diff --git a/jdk/test/java/net/MulticastSocket/TestInterfaces.java b/jdk/test/java/net/MulticastSocket/TestInterfaces.java index b9b641d40cc..2d90cb8a58e 100644 --- a/jdk/test/java/net/MulticastSocket/TestInterfaces.java +++ b/jdk/test/java/net/MulticastSocket/TestInterfaces.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /* * @test * @bug 4422122 + * @key intermittent * @summary Test that MulticastSocket.getInterface returns the * same InetAddress set by MulticastSocket.setInterface */ diff --git a/jdk/test/java/net/SocketOption/OptionsTest.java b/jdk/test/java/net/SocketOption/OptionsTest.java index 81f33f73b9f..f1309f11b50 100644 --- a/jdk/test/java/net/SocketOption/OptionsTest.java +++ b/jdk/test/java/net/SocketOption/OptionsTest.java @@ -26,7 +26,7 @@ * @bug 8036979 8072384 8044773 * @run main/othervm -Xcheck:jni OptionsTest * @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest - * @run main/othervm -Djdk.launcher.limitmods=java.base OptionsTest + * @run main/othervm -limitmods java.base OptionsTest */ import java.lang.reflect.Method; diff --git a/jdk/test/java/net/SocketOption/SupportedOptionsSet.java b/jdk/test/java/net/SocketOption/SupportedOptionsSet.java new file mode 100644 index 00000000000..eaa31e1246c --- /dev/null +++ b/jdk/test/java/net/SocketOption/SupportedOptionsSet.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.net.*; +import java.util.Set; +import static java.lang.System.out; + +/* + * @test + * @bug 8143923 + * @summary java.net socket supportedOptions set depends on call order + * @run main/othervm SupportedOptionsSet first + * @run main/othervm SupportedOptionsSet second + */ + +// Run with othervm as the implementation of the supported options sets, once +// calculated, stores them in a private static fields. + +public class SupportedOptionsSet { + + public static void main(String[] args) throws IOException { + if (args[0].equals("first")) + first(); + else if (args[0].equals("second")) + second(); + } + + static void first() throws IOException { + try (Socket s = new Socket(); + ServerSocket ss = new ServerSocket(); + DatagramSocket ds = new DatagramSocket(); + MulticastSocket ms = new MulticastSocket()) { + + Set first = s.supportedOptions(); + Set second = ss.supportedOptions(); + assertNotEqual(first, second, + "Socket and ServerSocket should have different options."); + + first = ds.supportedOptions(); + second = ms.supportedOptions(); + assertNotEqual(first, second, + "DatagramSocket and MulticastSocket should have different options."); + } + } + + /** Tests with the order of access to supportedOptions reversed. */ + static void second() throws IOException { + try (ServerSocket ss = new ServerSocket(); + Socket s = new Socket(); + DatagramSocket ds = new DatagramSocket(); + MulticastSocket ms = new MulticastSocket()) { + + Set first = ss.supportedOptions(); + Set second = s.supportedOptions(); + assertNotEqual(first, second, + "ServerSocket and Socket should have different options."); + + first = ms.supportedOptions(); + second = ds.supportedOptions(); + assertNotEqual(first, second, + "MulticastSocket and DatagramSocket should have different options."); + + } + } + + static void assertNotEqual(Set s1, Set s2, String message) { + if (s1.equals(s2)) { + out.println("s1: " + s1); + out.println("s2: " + s2); + throw new RuntimeException(message); + } + } +} diff --git a/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java b/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java index 0ab43f6ff27..488960c4bb3 100644 --- a/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java +++ b/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java @@ -33,7 +33,7 @@ import java.util.List; * @summary Test checks that UnsupportedOperationException for unsupported * SOCKET_OPTIONS is thrown by both getOption() and setOption() methods. * @run main UnsupportedOptionsTest - * @run main/othervm -Djdk.launcher.limitmods=java.base UnsupportedOptionsTest + * @run main/othervm -limitmods java.base UnsupportedOptionsTest */ public class UnsupportedOptionsTest { diff --git a/jdk/test/java/net/httpclient/HeadersTest1.java b/jdk/test/java/net/httpclient/HeadersTest1.java new file mode 100644 index 00000000000..79f62006722 --- /dev/null +++ b/jdk/test/java/net/httpclient/HeadersTest1.java @@ -0,0 +1,115 @@ +/* + * 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 + */ + +/** + * @test + * @bug 8153142 + * @run main/othervm HeadersTest1 + * @summary HeadersTest1 + */ + +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.Headers; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.List; +import static java.nio.charset.StandardCharsets.US_ASCII; + +public class HeadersTest1 { + + final static String RESPONSE = "Hello world"; + + public static void main(String[] args) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 10); + ExecutorService e = Executors.newCachedThreadPool(); + Handler h = new Handler(); + HttpContext serverContext = server.createContext("/test", h); + int port = server.getAddress().getPort(); + System.out.println("Server port = " + port); + + server.setExecutor(e); + server.start(); + HttpClient client = HttpClient.create() + .build(); + + try { + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/test/foo"); + HttpRequest req = client.request(uri) + .headers("X-Bar", "foo1") + .headers("X-Bar", "foo2") + .GET(); + + HttpResponse resp = req.response(); + if (resp.statusCode() != 200) + throw new RuntimeException("Test failed: status code"); + HttpHeaders hd = resp.headers(); + List v = hd.allValues("X-Foo-Response"); + if (!v.contains("resp1")) + throw new RuntimeException("Test failed: resp1"); + if (!v.contains("resp2")) + throw new RuntimeException("Test failed: resp2"); + + } finally { + client.executorService().shutdownNow(); + server.stop(0); + e.shutdownNow(); + } + System.out.println("OK"); + } + + static class Handler implements HttpHandler { + + @Override + public void handle(HttpExchange he) throws IOException { + String method = he.getRequestMethod(); + InputStream is = he.getRequestBody(); + List l = he.getRequestHeaders().get("X-Bar"); + if (!l.contains("foo1") || !l.contains("foo2")) { + for (String s : l) + System.out.println("HH: " + s); + he.sendResponseHeaders(500, -1); + he.close(); + return; + } + Headers h = he.getResponseHeaders(); + h.add("X-Foo-Response", "resp1"); + h.add("X-Foo-Response", "resp2"); + he.sendResponseHeaders(200, RESPONSE.length()); + OutputStream os = he.getResponseBody(); + os.write(RESPONSE.getBytes(US_ASCII)); + os.close(); + } + + } +} diff --git a/jdk/test/java/net/httpclient/http2/ErrorTest.java b/jdk/test/java/net/httpclient/http2/ErrorTest.java new file mode 100644 index 00000000000..578dc4df797 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/ErrorTest.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8157105 + * @library /lib/testlibrary + * @build jdk.testlibrary.SimpleSSLContext + * @modules java.httpclient + * @compile/module=java.httpclient java/net/http/BodyOutputStream.java + * @compile/module=java.httpclient java/net/http/BodyInputStream.java + * @compile/module=java.httpclient java/net/http/EchoHandler.java + * @compile/module=java.httpclient java/net/http/Http2Handler.java + * @compile/module=java.httpclient java/net/http/Http2TestExchange.java + * @compile/module=java.httpclient java/net/http/Http2TestServerConnection.java + * @compile/module=java.httpclient java/net/http/Http2TestServer.java + * @compile/module=java.httpclient java/net/http/OutgoingPushPromise.java + * @compile/module=java.httpclient java/net/http/TestUtil.java + * @run testng/othervm -Djava.net.http.HttpClient.log=ssl,errors ErrorTest + * @summary check exception thrown when bad TLS parameters selected + */ + +import java.io.*; +import java.net.*; +import java.net.http.*; +import static java.net.http.HttpClient.Version.HTTP_2; +import javax.net.ssl.*; +import java.nio.file.*; +import java.util.concurrent.*; +import jdk.testlibrary.SimpleSSLContext; + + +import org.testng.annotations.Test; +import org.testng.annotations.Parameters; + +/** + * When selecting an unacceptable cipher suite the TLS handshake will fail. + * But, the exception that was thrown was not being returned up to application + * causing hang problems + */ +@Test +public class ErrorTest { + static int httpsPort; + static Http2TestServer httpsServer; + static HttpClient client = null; + static ExecutorService exec; + static SSLContext sslContext; + + static String httpsURIString; + + static HttpClient getClient() { + if (client == null) { + client = HttpClient.create() + .sslContext(sslContext) + .sslParameters(new SSLParameters( + new String[]{"TLS_KRB5_WITH_3DES_EDE_CBC_SHA"})) + .version(HTTP_2) + .build(); + } + return client; + } + + static URI getURI() { + return URI.create(httpsURIString); + } + + static final String SIMPLE_STRING = "Hello world Goodbye world"; + + @Test(timeOut=5000) + static void test() throws Exception { + try { + SimpleSSLContext sslct = new SimpleSSLContext(); + sslContext = sslct.get(); + client = getClient(); + exec = client.executorService(); + + httpsServer = new Http2TestServer(true, 0, new EchoHandler(), + exec, sslContext); + + httpsPort = httpsServer.getAddress().getPort(); + httpsURIString = "https://127.0.0.1:" + + Integer.toString(httpsPort) + "/bar/"; + + httpsServer.start(); + URI uri = getURI(); + System.err.println("Request to " + uri); + + HttpClient client = getClient(); + HttpRequest req = client.request(uri) + .body(HttpRequest.fromString(SIMPLE_STRING)) + .POST(); + HttpResponse response = null; + try { + response = req.response(); + throw new RuntimeException("Expected exception"); + } catch (IOException e) { + System.err.println("Expected IOException received " + e); + } + System.err.println("DONE"); + } finally { + httpsServer.stop(); + exec.shutdownNow(); + } + } +} diff --git a/jdk/test/java/net/httpclient/http2/TLSConnection.java b/jdk/test/java/net/httpclient/http2/TLSConnection.java new file mode 100644 index 00000000000..f2721eb268e --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/TLSConnection.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.Http2Handler; +import java.net.http.Http2TestExchange; +import java.net.http.Http2TestServer; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSession; + +/* + * @test + * @bug 8150769 8157107 + * @summary Checks that SSL parameters can be set for HTTP/2 connection + * @modules java.httpclient + * @compile/module=java.httpclient java/net/http/Http2Handler.java + * @compile/module=java.httpclient java/net/http/Http2TestExchange.java + * @compile/module=java.httpclient java/net/http/Http2TestServer.java + * @run main/othervm TLSConnection + */ +public class TLSConnection { + + private static final String KEYSTORE = System.getProperty("test.src") + + File.separator + "keystore.p12"; + private static final String PASSWORD = "password"; + + public static void main(String[] args) throws Exception { + + // enable all logging + System.setProperty("java.net.http.HttpClient.log", "all,frames:all"); + + // initialize JSSE + System.setProperty("javax.net.ssl.keyStore", KEYSTORE); + System.setProperty("javax.net.ssl.keyStorePassword", PASSWORD); + System.setProperty("javax.net.ssl.trustStore", KEYSTORE); + System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD); + + Handler handler = new Handler(); + + try (Http2TestServer server = new Http2TestServer(true, 0, handler)) { + server.start(); + + int port = server.getAddress().getPort(); + String uriString = "https://127.0.0.1:" + Integer.toString(port); + + // run test cases + boolean success = true; + + SSLParameters parameters = null; + success &= expectFailure( + "Test #1: SSL parameters is null, expect NPE", + () -> connect(uriString, parameters), + NullPointerException.class); + + success &= expectSuccess( + "Test #2: default SSL parameters, " + + "expect successful connection", + () -> connect(uriString, new SSLParameters())); + success &= checkProtocol(handler.getSSLSession(), "TLSv1.2"); + + // set SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA cipher suite + // which has less priority in default cipher suite list + success &= expectSuccess( + "Test #3: SSL parameters with " + + "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA cipher suite, " + + "expect successful connection", + () -> connect(uriString, new SSLParameters( + new String[] { "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA" }))); + success &= checkProtocol(handler.getSSLSession(), "TLSv1.2"); + success &= checkCipherSuite(handler.getSSLSession(), + "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"); + + // set TLS_RSA_WITH_AES_128_CBC_SHA cipher suite + // which has less priority in default cipher suite list + // also set TLSv11 protocol + success &= expectSuccess( + "Test #4: SSL parameters with " + + "TLS_RSA_WITH_AES_128_CBC_SHA cipher suite," + + " expect successful connection", + () -> connect(uriString, new SSLParameters( + new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA" }, + new String[] { "TLSv1.1" }))); + success &= checkProtocol(handler.getSSLSession(), "TLSv1.1"); + success &= checkCipherSuite(handler.getSSLSession(), + "TLS_RSA_WITH_AES_128_CBC_SHA"); + + if (success) { + System.out.println("Test passed"); + } else { + throw new RuntimeException("At least one test case failed"); + } + } + } + + private static interface Test { + + public void run() throws Exception; + } + + private static class Handler implements Http2Handler { + + private static final byte[] BODY = "Test response".getBytes(); + + private volatile SSLSession sslSession; + + @Override + public void handle(Http2TestExchange t) throws IOException { + System.out.println("Handler: received request to " + + t.getRequestURI()); + + try (InputStream is = t.getRequestBody()) { + byte[] body = is.readAllBytes(); + System.out.println("Handler: read " + body.length + + " bytes of body: "); + System.out.println(new String(body)); + } + + try (OutputStream os = t.getResponseBody()) { + t.sendResponseHeaders(200, BODY.length); + os.write(BODY); + } + + sslSession = t.getSSLSession(); + } + + SSLSession getSSLSession() { + return sslSession; + } + } + + private static void connect(String uriString, SSLParameters sslParameters) + throws URISyntaxException, IOException, InterruptedException { + + String body = HttpClient.create() + .sslParameters(sslParameters) + .version(HttpClient.Version.HTTP_2) + .build() + .request(new URI(uriString)) + .body(HttpRequest.fromString("body")) + .GET() + .response() + .body(HttpResponse.asString()); + + System.out.println("Response: " + body); + } + + private static boolean checkProtocol(SSLSession session, String protocol) { + if (session == null) { + System.out.println("Check protocol: no session provided"); + return false; + } + + System.out.println("Check protocol: negotiated protocol: " + + session.getProtocol()); + System.out.println("Check protocol: expected protocol: " + + protocol); + if (!protocol.equals(session.getProtocol())) { + System.out.println("Check protocol: unexpected negotiated protocol"); + return false; + } + + return true; + } + + private static boolean checkCipherSuite(SSLSession session, String ciphersuite) { + if (session == null) { + System.out.println("Check protocol: no session provided"); + return false; + } + + System.out.println("Check protocol: negotiated ciphersuite: " + + session.getCipherSuite()); + System.out.println("Check protocol: expected ciphersuite: " + + ciphersuite); + if (!ciphersuite.equals(session.getCipherSuite())) { + System.out.println("Check protocol: unexpected negotiated ciphersuite"); + return false; + } + + return true; + } + + private static boolean expectSuccess(String message, Test test) { + System.out.println(message); + try { + test.run(); + System.out.println("Passed"); + return true; + } catch (Exception e) { + System.out.println("Failed: unexpected exception:"); + e.printStackTrace(System.out); + return false; + } + } + + private static boolean expectFailure(String message, Test test, + Class expectedException) { + + System.out.println(message); + try { + test.run(); + System.out.println("Failed: unexpected successful connection"); + return false; + } catch (Exception e) { + System.out.println("Got an exception:"); + e.printStackTrace(System.out); + if (expectedException != null + && !expectedException.isAssignableFrom(e.getClass())) { + System.out.printf("Failed: expected %s, but got %s%n", + expectedException.getName(), + e.getClass().getName()); + return false; + } + System.out.println("Passed: expected exception"); + return true; + } + } + +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java index 667a1d6ec55..3baefe142bb 100644 --- a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java @@ -42,7 +42,7 @@ import javax.net.ssl.SSLServerSocketFactory; * Http2Handler on additional threads. All threads * obtained from the supplied ExecutorService. */ -public class Http2TestServer { +public class Http2TestServer implements AutoCloseable { final ServerSocket server; boolean secure; SettingsFrame serverSettings, clientSettings; @@ -156,4 +156,9 @@ public class Http2TestServer { }); } + @Override + public void close() throws Exception { + stop(); + } + } diff --git a/jdk/test/java/nio/Buffer/Order-X.java.template b/jdk/test/java/nio/Buffer/Order-X.java.template index a8753a5f8a9..97313a841f6 100644 --- a/jdk/test/java/nio/Buffer/Order-X.java.template +++ b/jdk/test/java/nio/Buffer/Order-X.java.template @@ -52,8 +52,5 @@ public class Order$Type$ extends Order { buf = $Type$Buffer.allocate(LENGTH); ck(buf.order(), nord); ck$Type$Buffer(buf, nord); - - ck$Type$Buffer(ByteBuffer.allocate(LENGTH).as$Type$Buffer(), be); - ck$Type$Buffer(ByteBuffer.allocateDirect(LENGTH).as$Type$Buffer(), be); } } diff --git a/jdk/test/java/nio/Buffer/Order.java b/jdk/test/java/nio/Buffer/Order.java index 0232992525b..33ae418bb56 100644 --- a/jdk/test/java/nio/Buffer/Order.java +++ b/jdk/test/java/nio/Buffer/Order.java @@ -51,25 +51,31 @@ public class Order { ck(bb.asDoubleBuffer().order(), bb.order()); } + private static void ckCopyViews(ByteBuffer bb) { + ck(bb.asReadOnlyBuffer().order(), be); + ck(bb.duplicate().order(), be); + ck(bb.slice().order(), be); + } + private static void ckByteBuffer(ByteBuffer bb) { ckViews(bb); + ckCopyViews(bb); bb.order(be); ckViews(bb); + ckCopyViews(bb); bb.order(le); ckViews(bb); - - if (bb.hasArray()) { - byte[] array = bb.array(); - ck(ByteBuffer.wrap(array, LENGTH/2, LENGTH/2).order(), be); - ck(ByteBuffer.wrap(array).order(), be); - ck(bb.asReadOnlyBuffer().order(), be); - ck(bb.duplicate().order(), be); - ck(bb.slice().order(), be); - } + ckCopyViews(bb); } public static void main(String args[]) throws Exception { + ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(), be); + ck(ByteBuffer.wrap(new byte[LENGTH]).order(), be); + ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(be).order(), be); + ck(ByteBuffer.wrap(new byte[LENGTH]).order(be).order(), be); + ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(le).order(), le); + ck(ByteBuffer.wrap(new byte[LENGTH]).order(le).order(), le); ck(ByteBuffer.allocate(LENGTH).order(), be); ck(ByteBuffer.allocateDirect(LENGTH).order(), be); ck(ByteBuffer.allocate(LENGTH).order(be).order(), be); diff --git a/jdk/test/java/nio/Buffer/OrderChar.java b/jdk/test/java/nio/Buffer/OrderChar.java index ebf9faad79c..f72828bd0de 100644 --- a/jdk/test/java/nio/Buffer/OrderChar.java +++ b/jdk/test/java/nio/Buffer/OrderChar.java @@ -52,8 +52,5 @@ public class OrderChar extends Order { buf = CharBuffer.allocate(LENGTH); ck(buf.order(), nord); ckCharBuffer(buf, nord); - - ckCharBuffer(ByteBuffer.allocate(LENGTH).asCharBuffer(), be); - ckCharBuffer(ByteBuffer.allocateDirect(LENGTH).asCharBuffer(), be); } } diff --git a/jdk/test/java/nio/Buffer/OrderDouble.java b/jdk/test/java/nio/Buffer/OrderDouble.java index deaa6a3eb27..4100695cab5 100644 --- a/jdk/test/java/nio/Buffer/OrderDouble.java +++ b/jdk/test/java/nio/Buffer/OrderDouble.java @@ -52,8 +52,5 @@ public class OrderDouble extends Order { buf = DoubleBuffer.allocate(LENGTH); ck(buf.order(), nord); ckDoubleBuffer(buf, nord); - - ckDoubleBuffer(ByteBuffer.allocate(LENGTH).asDoubleBuffer(), be); - ckDoubleBuffer(ByteBuffer.allocateDirect(LENGTH).asDoubleBuffer(), be); } } diff --git a/jdk/test/java/nio/Buffer/OrderFloat.java b/jdk/test/java/nio/Buffer/OrderFloat.java index 6a65eaa8e4f..905d531d434 100644 --- a/jdk/test/java/nio/Buffer/OrderFloat.java +++ b/jdk/test/java/nio/Buffer/OrderFloat.java @@ -52,8 +52,5 @@ public class OrderFloat extends Order { buf = FloatBuffer.allocate(LENGTH); ck(buf.order(), nord); ckFloatBuffer(buf, nord); - - ckFloatBuffer(ByteBuffer.allocate(LENGTH).asFloatBuffer(), be); - ckFloatBuffer(ByteBuffer.allocateDirect(LENGTH).asFloatBuffer(), be); } } diff --git a/jdk/test/java/nio/Buffer/OrderInt.java b/jdk/test/java/nio/Buffer/OrderInt.java index 5d3843ffec7..700fc07110a 100644 --- a/jdk/test/java/nio/Buffer/OrderInt.java +++ b/jdk/test/java/nio/Buffer/OrderInt.java @@ -52,8 +52,5 @@ public class OrderInt extends Order { buf = IntBuffer.allocate(LENGTH); ck(buf.order(), nord); ckIntBuffer(buf, nord); - - ckIntBuffer(ByteBuffer.allocate(LENGTH).asIntBuffer(), be); - ckIntBuffer(ByteBuffer.allocateDirect(LENGTH).asIntBuffer(), be); } } diff --git a/jdk/test/java/nio/Buffer/OrderLong.java b/jdk/test/java/nio/Buffer/OrderLong.java index abda8b22932..9e507ffc18e 100644 --- a/jdk/test/java/nio/Buffer/OrderLong.java +++ b/jdk/test/java/nio/Buffer/OrderLong.java @@ -52,8 +52,5 @@ public class OrderLong extends Order { buf = LongBuffer.allocate(LENGTH); ck(buf.order(), nord); ckLongBuffer(buf, nord); - - ckLongBuffer(ByteBuffer.allocate(LENGTH).asLongBuffer(), be); - ckLongBuffer(ByteBuffer.allocateDirect(LENGTH).asLongBuffer(), be); } } diff --git a/jdk/test/java/nio/Buffer/OrderShort.java b/jdk/test/java/nio/Buffer/OrderShort.java index d19b43a1b60..f385b62d6dd 100644 --- a/jdk/test/java/nio/Buffer/OrderShort.java +++ b/jdk/test/java/nio/Buffer/OrderShort.java @@ -52,8 +52,5 @@ public class OrderShort extends Order { buf = ShortBuffer.allocate(LENGTH); ck(buf.order(), nord); ckShortBuffer(buf, nord); - - ckShortBuffer(ByteBuffer.allocate(LENGTH).asShortBuffer(), be); - ckShortBuffer(ByteBuffer.allocateDirect(LENGTH).asShortBuffer(), be); } } diff --git a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java index 00281647f17..270efce9126 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java @@ -25,7 +25,7 @@ * @bug 4640544 8044773 * @summary Unit test for setOption/getOption/options methods * @run main SocketOptionTests - * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests + * @run main/othervm -limitmods java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java index a0b2b6a8e82..b8c7c327bcb 100644 --- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -26,7 +26,7 @@ * @summary Unit test for ServerSocketChannel setOption/getOption/options * methods. * @run main SocketOptionTests - * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests + * @run main/othervm -limitmods java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java index 74f87c71623..38a4e9c170e 100644 --- a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java @@ -26,7 +26,7 @@ * @summary Unit test to check SocketChannel setOption/getOption/options * methods. * @run main SocketOptionTests - * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests + * @run main/othervm -limitmods java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/java/rmi/module/ModuleTest.java b/jdk/test/java/rmi/module/ModuleTest.java new file mode 100644 index 00000000000..ad19a71b9f4 --- /dev/null +++ b/jdk/test/java/rmi/module/ModuleTest.java @@ -0,0 +1,159 @@ +/* + * 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 + * @library /lib/testlibrary + * @build jdk.testlibrary.ProcessTools + * ModuleTest CompilerUtils JarUtils + * @run testng ModuleTest + * @summary Basic tests for using rmi in module world + */ + +import static jdk.testlibrary.ProcessTools.executeTestJava; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.io.File; +import java.nio.file.Paths; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +public class ModuleTest { + + static String fileJoin(String... names) { + return String.join(File.separator, names); + } + + static String pathJoin(String... paths) { + return String.join(File.pathSeparator, paths); + } + + private static final String TEST_SRC = System.getProperty("test.src"); + private static final String CLIENT_EXP = fileJoin("exploded", "mclient"); + private static final String SERVER_EXP = fileJoin("exploded", "mserver"); + private static final String MTEST_EXP = fileJoin("exploded", "mtest"); + private static final String CLIENT_JAR = fileJoin("mods", "mclient.jar"); + private static final String SERVER_JAR = fileJoin("mods", "mserver.jar"); + private static final String MTEST_JAR = fileJoin("mods", "mtest.jar"); + + private static final String DUMMY_MAIN = "testpkg.DummyApp"; + + /** + * Compiles all sample classes + */ + @BeforeTest + public void compileAll() throws Exception { + assertTrue(CompilerUtils.compile( + Paths.get(TEST_SRC, "src", "mserver"), + Paths.get(SERVER_EXP))); + + JarUtils.createJarFile( + Paths.get(SERVER_JAR), + Paths.get(SERVER_EXP)); + + assertTrue(CompilerUtils.compile( + Paths.get(TEST_SRC, "src", "mclient"), + Paths.get(CLIENT_EXP), + "-cp", SERVER_JAR)); + + JarUtils.createJarFile( + Paths.get(CLIENT_JAR), + Paths.get(CLIENT_EXP)); + + assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "mtest"), + Paths.get(MTEST_EXP), + "-cp", pathJoin(CLIENT_JAR, SERVER_JAR))); + + JarUtils.createJarFile( + Paths.get(MTEST_JAR), + Paths.get(MTEST_EXP)); + } + + /** + * Test the client, server and dummy application in different modules + * @throws Exception + */ + @Test + public void testAllInModule() throws Exception { + assertEquals(executeTestJava("-mp", pathJoin(MTEST_JAR, CLIENT_JAR, SERVER_JAR), + "-addmods", "mclient,mserver", + "-m", "mtest/" + DUMMY_MAIN) + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(), + 0); + } + + /** + * Test the client and server in unnamed modules, + * while the dummy application is in automatic module + * @throws Exception + */ + @Test + public void testAppInModule() throws Exception { + assertEquals(executeTestJava("-mp", MTEST_JAR, + "-cp", pathJoin(CLIENT_JAR, SERVER_JAR), + "-m", "mtest/" + DUMMY_MAIN) + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(), + 0); + } + + /** + * Test the client and server in automatic modules, + * while the dummy application is in unnamed module + * @throws Exception + */ + @Test + public void testAppInUnnamedModule() throws Exception { + assertEquals(executeTestJava("-mp", pathJoin(CLIENT_JAR, SERVER_JAR), + "-addmods", "mclient,mserver", + "-cp", MTEST_JAR, + DUMMY_MAIN) + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(), + 0); + } + + /** + * Test the server and test application in automatic modules, + * with client in unnamed module + * @throws Exception + */ + @Test + public void testClientInUnamedModule() throws Exception { + assertEquals(executeTestJava("-mp", pathJoin(MTEST_JAR, SERVER_JAR), + "-addmods", "mserver", + "-cp", CLIENT_JAR, + "-m", "mtest/" + DUMMY_MAIN) + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(), + 0); + } +} + diff --git a/jdk/test/java/rmi/module/src/mclient/clientpkg/Client.java b/jdk/test/java/rmi/module/src/mclient/clientpkg/Client.java new file mode 100644 index 00000000000..0907748c1e9 --- /dev/null +++ b/jdk/test/java/rmi/module/src/mclient/clientpkg/Client.java @@ -0,0 +1,47 @@ +/* + * 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 clientpkg; + +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; + +import serverpkg.Hello; + +public class Client { + int port; + Hello stub; + + public Client(Hello stub) { + this.stub = stub; + } + + public String testStub() throws Exception { + try { + return stub.sayHello(); + } catch (Exception e) { + System.err.println("Client exception: " + e.toString()); + throw e; + } + } +} diff --git a/jdk/test/java/rmi/module/src/mserver/serverpkg/Hello.java b/jdk/test/java/rmi/module/src/mserver/serverpkg/Hello.java new file mode 100644 index 00000000000..4525c09746c --- /dev/null +++ b/jdk/test/java/rmi/module/src/mserver/serverpkg/Hello.java @@ -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 serverpkg; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface Hello extends Remote { + + String sayHello() throws RemoteException; +} diff --git a/jdk/test/java/rmi/module/src/mserver/serverpkg/Server.java b/jdk/test/java/rmi/module/src/mserver/serverpkg/Server.java new file mode 100644 index 00000000000..0ba07492b9e --- /dev/null +++ b/jdk/test/java/rmi/module/src/mserver/serverpkg/Server.java @@ -0,0 +1,37 @@ +/* + * 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 serverpkg; + +public class Server implements Hello { + + private final String hello = "Hello world!"; + + public Server() { + } + + @Override + public String sayHello() { + return hello; + } +} diff --git a/jdk/test/java/rmi/module/src/mtest/testpkg/DummyApp.java b/jdk/test/java/rmi/module/src/mtest/testpkg/DummyApp.java new file mode 100644 index 00000000000..6fc88d01fab --- /dev/null +++ b/jdk/test/java/rmi/module/src/mtest/testpkg/DummyApp.java @@ -0,0 +1,55 @@ +/* + * 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 testpkg; + +import java.rmi.server.UnicastRemoteObject; + +import clientpkg.Client; +import serverpkg.Hello; +import serverpkg.Server; + +public class DummyApp { + + public static void main(String args[]) { + try { + Hello obj = new Server(); + Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0); + + Client client = new Client(stub); + String testStubReturn = client.testStub(); + System.out.println("Stub is: " + testStubReturn); + if (!testStubReturn.equals(obj.sayHello())) { + throw new RuntimeException("Unexpected string from stub call, expected \"" + + testStubReturn + "\", actual \"" + obj.sayHello() + "\""); + } else { + System.out.println("Test passed"); + } + + System.exit(0); + } catch (Throwable e) { + e.printStackTrace(); + System.exit(-1); + } + } +} diff --git a/jdk/test/java/security/Provider/DefaultProviderList.java b/jdk/test/java/security/Provider/DefaultProviderList.java index c2836642f42..ba63c76caf6 100644 --- a/jdk/test/java/security/Provider/DefaultProviderList.java +++ b/jdk/test/java/security/Provider/DefaultProviderList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,13 +23,16 @@ /** * @test - * @bug 7191662 + * @bug 7191662 8157469 * @summary Ensure non-java.base providers can be found by ServiceLoader * @author Valerie Peng */ -import java.util.*; -import java.security.*; +import java.security.Provider; +import java.security.Security; +import java.util.Arrays; +import java.util.Iterator; +import java.util.ServiceLoader; public class DefaultProviderList { @@ -44,7 +47,8 @@ public class DefaultProviderList { String pName = p.getName(); // only providers outside java.base are loaded by ServiceLoader if (pName.equals("SUN") || pName.equals("SunRsaSign") || - pName.equals("SunJCE") || pName.equals("SunJSSE")) { + pName.equals("SunJCE") || pName.equals("SunJSSE") || + pName.equals("Apple")) { System.out.println("Skip test for provider " + pName); continue; } diff --git a/jdk/test/java/security/SecureRandom/ApiTest.java b/jdk/test/java/security/SecureRandom/ApiTest.java new file mode 100644 index 00000000000..e48ee4a90de --- /dev/null +++ b/jdk/test/java/security/SecureRandom/ApiTest.java @@ -0,0 +1,366 @@ +/* + * 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 8141039 + * @library /lib/testlibrary + * @summary This test do API coverage for SecureRandom. It covers most of + * supported operations along with possible positive and negative + * parameters for DRBG mechanism. + * @run main/othervm ApiTest Hash_DRBG + * @run main/othervm ApiTest HMAC_DRBG + * @run main/othervm ApiTest CTR_DRBG + * @run main/othervm ApiTest SHA1PRNG + * @run main/othervm ApiTest NATIVE + */ +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.Security; +import java.security.SecureRandomParameters; +import java.security.DrbgParameters; +import java.security.DrbgParameters.Instantiation; +import java.security.DrbgParameters.Capability; +import javax.crypto.Cipher; + +public class ApiTest { + + private static final boolean SHOULD_PASS = true; + private static final long SEED = 1l; + private static final String INVALID_ALGO = "INVALID"; + private static final String DRBG_CONFIG = "securerandom.drbg.config"; + private static final String DRBG_CONFIG_VALUE + = Security.getProperty(DRBG_CONFIG); + + public static void main(String[] args) throws Exception { + System.setProperty("java.security.egd", "file:/dev/urandom"); + + if (args == null || args.length < 1) { + throw new RuntimeException("No mechanism available to run test."); + } + String mech + = "NATIVE".equals(args[0]) ? supportedNativeAlgo() : args[0]; + String[] algs = null; + boolean success = true; + + try { + if (!isDRBG(mech)) { + SecureRandom random = SecureRandom.getInstance(mech); + verifyAPI(random, mech); + return; + } else if (mech.equals("CTR_DRBG")) { + algs = new String[]{"AES-128", "AES-192", "AES-256", + INVALID_ALGO}; + } else if (mech.equals("Hash_DRBG") || mech.equals("HMAC_DRBG")) { + algs = new String[]{"SHA-224", "SHA-256", "SHA-512/224", + "SHA-512/256", "SHA-384", "SHA-512", INVALID_ALGO}; + } else { + throw new RuntimeException( + String.format("Not a valid mechanism '%s'", mech)); + } + runForEachMech(mech, algs); + } catch (Exception e) { + e.printStackTrace(System.out); + success = false; + } + + if (!success) { + throw new RuntimeException("At least one test failed."); + } + } + + /** + * Run the test for a DRBG mechanism with a possible set of parameter + * combination. + * @param mech DRBG mechanism name + * @param algs Algorithm supported by each mechanism + * @throws Exception + */ + private static void runForEachMech(String mech, String[] algs) + throws Exception { + for (String alg : algs) { + runForEachAlg(mech, alg); + } + } + + private static void runForEachAlg(String mech, String alg) + throws Exception { + for (int strength : new int[]{Integer.MIN_VALUE, -1, 0, 1, 223, 224, + 192, 255, 256}) { + for (Capability cp : Capability.values()) { + for (byte[] pr : new byte[][]{null, new byte[]{}, + "personal".getBytes()}) { + SecureRandomParameters param + = DrbgParameters.instantiation(strength, cp, pr); + runForEachParam(mech, alg, param); + } + } + } + } + + private static void runForEachParam(String mech, String alg, + SecureRandomParameters param) throws Exception { + + for (boolean df : new Boolean[]{true, false}) { + try { + Security.setProperty(DRBG_CONFIG, mech + "," + alg + "," + + (df ? "use_df" : "no_df")); + System.out.printf("%nParameter for SecureRandom " + + "mechanism: %s is (param:%s, algo:%s, df:%s)", + mech, param, alg, df); + SecureRandom sr = SecureRandom.getInstance("DRBG", param); + verifyAPI(sr, mech); + } catch (NoSuchAlgorithmException e) { + // Verify exception status for current test. + checkException(getDefaultAlg(mech, alg), param, e); + } finally { + Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); + } + } + } + + /** + * Returns the algorithm supported for input mechanism. + * @param mech Mechanism name + * @param alg Algorithm name + * @return Algorithm name + */ + private static String getDefaultAlg(String mech, String alg) + throws NoSuchAlgorithmException { + if (alg == null) { + switch (mech) { + case "Hash_DRBG": + case "HMAC_DRBG": + return "SHA-256"; + case "CTR_DRBG": + return (Cipher.getMaxAllowedKeyLength("AES") < 256) + ? "AES-128" : "AES-256"; + default: + throw new RuntimeException("Mechanism not supported"); + } + } + return alg; + } + + /** + * Verify the exception type either it is expected to occur or not. + * @param alg Algorithm name + * @param param DRBG parameter + * @param e Exception to verify + * @throws NoSuchAlgorithmException + */ + private static void checkException(String alg, SecureRandomParameters param, + NoSuchAlgorithmException e) throws NoSuchAlgorithmException { + + int strength = ((Instantiation) param).getStrength(); + boolean error = true; + switch (alg) { + case INVALID_ALGO: + error = false; + break; + case "SHA-224": + case "SHA-512/224": + if (strength > 192) { + error = false; + } + break; + case "SHA-256": + case "SHA-512/256": + case "SHA-384": + case "SHA-512": + if (strength > 256) { + error = false; + } + break; + case "AES-128": + case "AES-192": + case "AES-256": + int algoStrength = Integer.parseInt(alg.replaceAll("AES-", "")); + int maxStrengthSupported = Cipher.getMaxAllowedKeyLength("AES"); + if (strength > maxStrengthSupported + || algoStrength > maxStrengthSupported) { + error = false; + } + break; + } + if (error) { + throw new RuntimeException("Unknown :", e); + } + } + + /** + * Find if the mechanism is a DRBG mechanism. + * @param mech Mechanism name + * @return True for DRBG mechanism else False + */ + private static boolean isDRBG(String mech) { + return mech.contains("_DRBG"); + } + + /** + * Find the name of supported native mechanism name for current platform. + */ + private static String supportedNativeAlgo() { + String nativeSr = "Windows-PRNG"; + try { + SecureRandom.getInstance(nativeSr); + } catch (NoSuchAlgorithmException e) { + nativeSr = "NativePRNG"; + } + return nativeSr; + } + + /** + * Test a possible set of SecureRandom API for a SecureRandom instance. + * @param random SecureRandom instance + * @param mech Mechanism used to create SecureRandom instance + */ + private static void verifyAPI(SecureRandom random, String mech) + throws Exception { + + System.out.printf("%nTest SecureRandom mechanism: %s for provider: %s", + mech, random.getProvider().getName()); + byte[] output = new byte[2]; + + // Generate random number. + random.nextBytes(output); + + // Seed the SecureRandom with a generated seed value of lesser size. + byte[] seed = random.generateSeed(1); + random.setSeed(seed); + random.nextBytes(output); + + // Seed the SecureRandom with a fixed seed value. + random.setSeed(SEED); + random.nextBytes(output); + + // Seed the SecureRandom with a larger seed value. + seed = random.generateSeed(128); + random.setSeed(seed); + random.nextBytes(output); + + // Additional operation only supported for DRBG based SecureRandom. + // Execute the code block and expect to pass for DRBG. If it will fail + // then it should fail with specified exception type. Else the case + // will be considered as a test case failure. + matchExc(() -> { + random.reseed(); + random.nextBytes(output); + }, + isDRBG(mech), + UnsupportedOperationException.class, + String.format("PASS - Unsupported reseed() method for " + + "SecureRandom Algorithm %s ", mech)); + + matchExc(() -> { + random.reseed(DrbgParameters.reseed(false, new byte[]{})); + random.nextBytes(output); + }, + isDRBG(mech), + UnsupportedOperationException.class, + String.format("PASS - Unsupported reseed(param) method for " + + "SecureRandom Algorithm %s ", mech)); + + matchExc(() -> { + random.reseed(DrbgParameters.reseed(true, new byte[]{})); + random.nextBytes(output); + }, + isDRBG(mech), + !isSupportPR(mech, random) ? IllegalArgumentException.class + : UnsupportedOperationException.class, + String.format("PASS - Unsupported or illegal reseed(param) " + + "method for SecureRandom Algorithm %s ", mech)); + + matchExc(() -> random.nextBytes(output, + DrbgParameters.nextBytes(-1, false, new byte[]{})), + isDRBG(mech), + UnsupportedOperationException.class, + String.format("PASS - Unsupported nextBytes(out, nextByteParam)" + + " method for SecureRandom Algorithm %s ", mech)); + + matchExc(() -> random.nextBytes(output, + DrbgParameters.nextBytes(-1, true, new byte[]{})), + isDRBG(mech), + !isSupportPR(mech, random) ? IllegalArgumentException.class + : UnsupportedOperationException.class, + String.format("PASS - Unsupported or illegal " + + "nextBytes(out, nextByteParam) method for " + + "SecureRandom Algorithm %s ", mech)); + + matchExc(() -> { + random.reseed(null); + random.nextBytes(output); + }, + !SHOULD_PASS, + IllegalArgumentException.class, + "PASS - Test is expected to fail when parameter for reseed() " + + "is null"); + + matchExc(() -> random.nextBytes(output, null), + !SHOULD_PASS, + IllegalArgumentException.class, + "PASS - Test is expected to fail when parameter for nextBytes()" + + " is null"); + + } + + private static boolean isSupportPR(String mech, SecureRandom random) { + return (isDRBG(mech) && ((Instantiation) random.getParameters()) + .getCapability() + .supportsPredictionResistance()); + } + + private interface RunnableCode { + + void run() throws Exception; + } + + /** + * Execute a given code block and verify, if the exception type is expected. + * @param r Code block to run + * @param ex Expected exception type + * @param shouldPass If the code execution expected to pass without failure + * @param msg Message to log in case of expected failure + */ + private static void matchExc(RunnableCode r, boolean shouldPass, Class ex, + String msg) { + try { + r.run(); + if (!shouldPass) { + throw new RuntimeException("Excecution should fail here."); + } + } catch (Exception e) { + System.out.printf("%nOccured exception: %s - Expected exception: " + + "%s : ", e.getClass(), ex.getCanonicalName()); + if (ex.isAssignableFrom(e.getClass())) { + System.out.printf("%n%s : Expected Exception occured: %s : ", + e.getClass(), msg); + } else if (shouldPass) { + throw new RuntimeException(e); + } else { + System.out.printf("Ignore the following exception: %s%n", + e.getMessage()); + } + } + } +} diff --git a/jdk/test/java/security/SecureRandom/EnoughSeedTest.java b/jdk/test/java/security/SecureRandom/EnoughSeedTest.java new file mode 100644 index 00000000000..a42807d0530 --- /dev/null +++ b/jdk/test/java/security/SecureRandom/EnoughSeedTest.java @@ -0,0 +1,101 @@ +/* + * 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 8141039 + * @library /lib/testlibrary + * @summary Check SecureRandom generate expected seed counts what the caller + * asked for. + * @run main/othervm EnoughSeedTest + */ +import java.security.SecureRandom; +import java.security.Security; +import static java.lang.Math.*; + +public class EnoughSeedTest { + + private static final String DRBG_CONFIG = "securerandom.drbg.config"; + private static final String DRBG_CONFIG_VALUE + = Security.getProperty(DRBG_CONFIG); + + public static void main(String[] args) { + System.setProperty("java.security.egd", "file:/dev/urandom"); + + boolean success = true; + for (String mech : new String[]{ + "SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) { + System.out.printf("%nTest for SecureRandom algorithm: '%s'", mech); + try { + SecureRandom sr = null; + if (!mech.contains("_DRBG")) { + sr = SecureRandom.getInstance(mech); + } else { + Security.setProperty(DRBG_CONFIG, mech); + sr = SecureRandom.getInstance("DRBG"); + } + + success &= forEachSeedBytes(sr); + System.out.printf("%nCompleted test for SecureRandom " + + "mechanism: '%s'", mech); + } catch (Exception e) { + success &= false; + e.printStackTrace(System.out); + } finally { + Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); + } + } + if (!success) { + throw new RuntimeException("At least one test failed."); + } + } + + /** + * Generates fixed number of seed bytes through a SecureRandom instance + * to verify it's seed generation status. + * @param sr SecureRandom instance + * @return The test success indicator + */ + private static boolean forEachSeedBytes(SecureRandom sr) { + boolean success = true; + sr.setSeed(1l); + for (int seedByte : new int[]{Integer.MIN_VALUE, -1, 0, 1, 256, 1024, + Short.MAX_VALUE, (int) pow(2, 20)}) { + try { + byte[] seed = sr.generateSeed(seedByte); + if (seed.length != seedByte) { + throw new RuntimeException("Not able to produce expected " + + "seed size."); + } + } catch (IllegalArgumentException e) { + if (seedByte >= 0) { + throw new RuntimeException("Unknown Exception occured.", e); + } + System.out.printf("%nPASS - Exception expected when required " + + "seed size requested is negative: %s", seedByte); + } + } + return success; + } + +} diff --git a/jdk/test/java/security/SecureRandom/GetAlgorithm.java b/jdk/test/java/security/SecureRandom/GetAlgorithm.java index b1947ef1db8..1ec3fd25ce2 100644 --- a/jdk/test/java/security/SecureRandom/GetAlgorithm.java +++ b/jdk/test/java/security/SecureRandom/GetAlgorithm.java @@ -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,49 +23,54 @@ /** * @test - * @bug 4915392 + * @bug 4915392 8141039 * @summary test that the getAlgorithm() method works correctly * @author Andreas Sterbenz + * @run main GetAlgorithm */ - import java.io.*; - import java.security.*; +import java.util.Arrays; +import java.util.List; public class GetAlgorithm { - private final static String BASE = System.getProperty("test.src", "."); + private static final String BASE = System.getProperty("test.src", "."); + private static final String DRBG_CONFIG = "securerandom.drbg.config"; + private static final String DRBG_CONFIG_VALUE + = Security.getProperty(DRBG_CONFIG); public static void main(String[] args) throws Exception { - SecureRandom sr; - - sr = new SecureRandom(); + SecureRandom sr = new SecureRandom(); if (sr.getAlgorithm().equals("unknown")) { throw new Exception("Unknown: " + sr.getAlgorithm()); } - sr = SecureRandom.getInstance("SHA1PRNG"); - check("SHA1PRNG", sr); + for (String mech : new String[]{supportedNativeAlgo(), "SHA1PRNG", + "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) { + if (!mech.contains("_DRBG")) { + check(mech, SecureRandom.getInstance(mech)); + } else { + try { + Security.setProperty(DRBG_CONFIG, mech); + check("DRBG", SecureRandom.getInstance("DRBG")); + } finally { + Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); + } + } + } + check("unknown", new MySecureRandom()); -// OutputStream out = new FileOutputStream("sha1prng.bin"); -// ObjectOutputStream oout = new ObjectOutputStream(out); -// sr.nextInt(); -// oout.writeObject(sr); -// oout.flush(); -// oout.close(); - - sr = new MySecureRandom(); - check("unknown", sr); - - InputStream in = new FileInputStream(new File(BASE, "sha1prng-old.bin")); + InputStream in = new FileInputStream( + new File(BASE, "sha1prng-old.bin")); ObjectInputStream oin = new ObjectInputStream(in); - sr = (SecureRandom)oin.readObject(); + sr = (SecureRandom) oin.readObject(); oin.close(); check("unknown", sr); in = new FileInputStream(new File(BASE, "sha1prng-new.bin")); oin = new ObjectInputStream(in); - sr = (SecureRandom)oin.readObject(); + sr = (SecureRandom) oin.readObject(); oin.close(); check("SHA1PRNG", sr); @@ -83,4 +88,17 @@ public class GetAlgorithm { } + /** + * Find the name of supported native mechanism name for current platform. + */ + private static String supportedNativeAlgo() { + String nativeSr = "Windows-PRNG"; + try { + SecureRandom.getInstance(nativeSr); + } catch (NoSuchAlgorithmException e) { + nativeSr = "NativePRNG"; + } + return nativeSr; + } + } diff --git a/jdk/test/java/security/SecureRandom/GetInstanceTest.java b/jdk/test/java/security/SecureRandom/GetInstanceTest.java new file mode 100644 index 00000000000..08477da847e --- /dev/null +++ b/jdk/test/java/security/SecureRandom/GetInstanceTest.java @@ -0,0 +1,312 @@ +/* + * 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 8141039 + * @library /lib/testlibrary + * @summary SecureRandom supports multiple getInstance method including + * getInstanceStrong() method. This test verifies a set of possible + * cases for getInstance with different SecureRandom mechanism + * supported in Java. + * @run main GetInstanceTest + */ +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.SecureRandomParameters; +import java.security.DrbgParameters; +import static java.security.DrbgParameters.Capability.*; +import java.security.Security; +import java.util.Arrays; +import jdk.testlibrary.Asserts; + +public class GetInstanceTest { + + private static final boolean PASS = true; + private static final String INVALID_ALGO = "INVALID"; + private static final String SUN_PROVIDER = "SUN"; + private static final String INVALID_PROVIDER = "INVALID"; + private static final String STRONG_ALG_SEC_PROP + = "securerandom.strongAlgorithms"; + private static final String DRBG_CONFIG = "securerandom.drbg.config"; + private static final String DRBG_CONFIG_VALUE + = Security.getProperty(DRBG_CONFIG); + + public static void main(String[] args) throws Exception { + + boolean success = true; + // Only accepted failure is NoSuchAlgorithmException. + // For any other failure the test case will fail here. + SecureRandom sr = matchExc(() -> SecureRandom.getInstanceStrong(), + PASS, NoSuchAlgorithmException.class, + "PASS - Undefined security Property " + + "'securerandom.strongAlgorithms'"); + System.out.format("Current platform supports mechanism: '%s' through " + + "provider: '%s' for the method getInstanceStrong().", + sr.getAlgorithm(), sr.getProvider().getName()); + + // DRBG name should appear with "securerandom.strongAlgorithms" + // security property. + String origDRBGConfig = Security.getProperty(STRONG_ALG_SEC_PROP); + if (!origDRBGConfig.contains("DRBG")) { + throw new RuntimeException("DRBG is not associated with default " + + "strong algorithm through security Property: " + + "'securerandom.strongAlgorithms'."); + } + try { + Security.setProperty(STRONG_ALG_SEC_PROP, "DRBG:SUN"); + sr = matchExc(() -> SecureRandom.getInstanceStrong(), + PASS, NoSuchAlgorithmException.class, + "PASS - Undefined security Property " + + "'securerandom.strongAlgorithms'"); + checkAttributes(sr, "DRBG"); + } finally { + Security.setProperty(STRONG_ALG_SEC_PROP, origDRBGConfig); + } + + for (String mech : new String[]{ + "SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG", INVALID_ALGO,}) { + System.out.printf("%nTest SecureRandom mechanism: '%s'", mech); + try { + if (isDRBG(mech)) { + Security.setProperty(DRBG_CONFIG, mech); + } + verifyInstance(mech); + } catch (Exception e) { + e.printStackTrace(System.out); + success = false; + } finally { + Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); + } + } + if (!success) { + throw new RuntimeException("At least one test failed."); + } + } + + private static void verifyInstance(String mech) throws Exception { + + String srAlgo = isDRBG(mech) ? "DRBG" : mech; + + // Test for getInstance(algorithm) method. + // It should pass for all case other than invalid algorithm name. + // If it fails then the expected exception type should be + // NoSuchAlgorithmException. Any other Exception type occured will be + // treated as failure. + checkAttributes( + matchExc(() -> SecureRandom.getInstance(srAlgo), !(nsa(mech)), + NoSuchAlgorithmException.class, + String.format("PASS - It is expected to fail for" + + " getInstance(algorithm) when algorithm: '%s'" + + " is null or invalid.", mech)), mech); + // Test for getInstance(algorithm, provider) method. + checkAttributes( + matchExc(() -> SecureRandom.getInstance(srAlgo, + Security.getProvider(SUN_PROVIDER)), + !(nsa(mech)), + NoSuchAlgorithmException.class, + String.format("PASS - It is expected to fail for" + + " getInstance(algorithm, provider) when" + + " algorithm:'%s' is null or invalid.", mech)), + mech); + // Test for getInstance(algorithm, providerName) method. + checkAttributes( + matchExc(() -> SecureRandom.getInstance(srAlgo, SUN_PROVIDER), + !(nsa(mech)), NoSuchAlgorithmException.class, + String.format("PASS - It is expected to fail for " + + "getInstance(algorithm, providerName) when " + + "algorithm: '%s' is null or invalid.", mech)), + mech); + // Test for getInstance(algorithm, providerName) method. + checkAttributes( + matchExc(() -> SecureRandom.getInstance( + srAlgo, INVALID_PROVIDER), + !PASS, NoSuchProviderException.class, + String.format("PASS - It is expected to fail for " + + "getInstance(algorithm, providerName) when " + + "provider name: '%s' is invalid and " + + "algorithm: '%s'", INVALID_PROVIDER, mech)), + mech); + + // Run the test for a set of SecureRandomParameters + for (SecureRandomParameters param : Arrays.asList(null, + DrbgParameters.instantiation(-1, NONE, null))) { + + System.out.printf("%nRunning DRBG param getInstance() methods " + + "for algorithm: %s and DRBG param type: %s", mech, + (param != null) ? param.getClass().getName() : param); + + // Following Test are applicable for new DRBG methods only. + // Test for getInstance(algorithm, params) method. + // Tests are expected to pass for DRBG type with valid parameter + // If it fails the expected exception type is derived from + // getExcType(mech, param) method. If exception type is not + // expected then the test will be considered as failure. + checkAttributes( + matchExc(() -> SecureRandom.getInstance(srAlgo, param), + (isDRBG(mech)) && (isValidDRBGParam(param)), + getExcType(mech, param), + String.format("PASS - It is expected to fail " + + "for getInstance(algorithm, params) " + + "for algorithm: %s and parameter: %s", + mech, param)), + mech); + // Test for getInstance(algorithm, params, provider) method. + checkAttributes( + matchExc(() -> SecureRandom.getInstance(srAlgo, param, + Security.getProvider(SUN_PROVIDER)), + (isDRBG(mech)) && (isValidDRBGParam(param)), + getExcType(mech, param), + String.format("PASS - It is expected to fail " + + "for getInstance(algorithm, params, " + + "provider) for algorithm: %s and " + + "parameter: %s", mech, param)), + mech); + // Test for getInstance(algorithm, params, providerName) method. + checkAttributes( + matchExc(() -> SecureRandom.getInstance(srAlgo, param, + SUN_PROVIDER), + (isDRBG(mech)) && (isValidDRBGParam(param)), + getExcType(mech, param), + String.format("PASS - It is expected to fail " + + "for getInstance(algorithm, params, " + + "providerName) for algorithm: %s and " + + "parameter: %s", mech, param)), mech); + // getInstance(algorithm, params, providerName) when + // providerName is invalid + checkAttributes( + matchExc(() -> SecureRandom.getInstance(srAlgo, param, + INVALID_PROVIDER), + !PASS, ((param == null) + ? IllegalArgumentException.class + : NoSuchProviderException.class), + String.format("PASS - It is expected to fail " + + "for getInstance(algorithm, params, " + + "providerName) when param is null or" + + " provider: %s is invalid for " + + "algorithm: '%s'", INVALID_PROVIDER, + mech)), mech); + // getInstance(algorithm, params, provider) when provider=null + checkAttributes( + matchExc(() -> SecureRandom.getInstance(srAlgo, param, + (String) null), + !PASS, IllegalArgumentException.class, + String.format("PASS - It is expected to fail " + + "for getInstance(algorithm, params, " + + "providerName) when provider name " + + "is null")), mech); + // getInstance(algorithm, params, providerName) when + // providerName is empty. + checkAttributes( + matchExc(() -> SecureRandom.getInstance( + srAlgo, param, ""), + !PASS, IllegalArgumentException.class, + String.format("PASS - It is expected to fail " + + "for getInstance(algorithm, params, " + + "providerName) when provider name " + + "is empty")), mech); + } + } + + private static boolean isValidDRBGParam(SecureRandomParameters param) { + return (param instanceof DrbgParameters.Instantiation); + } + + /** + * If the mechanism should occur NoSuchAlgorithmException. + */ + private static boolean nsa(String mech) { + return mech.equals(INVALID_ALGO); + } + + /** + * Verify if the mechanism is DRBG type. + * @param mech Mechanism name + * @return True if the mechanism name is DRBG type else False. + */ + private static boolean isDRBG(String mech) { + return mech.contains("_DRBG"); + } + + /** + * Type of exception expected for a SecureRandom instance when exception + * occurred while calling getInstance method with a fixed set of parameter. + * @param mech Mechanism used to create a SecureRandom instance + * @param param Parameter to getInstance() method + * @return Exception type expected + */ + private static Class getExcType(String mech, SecureRandomParameters param) { + return ((isDRBG(mech) && !isValidDRBGParam(param)) || param == null) + ? IllegalArgumentException.class + : NoSuchAlgorithmException.class; + } + + private interface RunnableCode { + + SecureRandom run() throws Exception; + } + + /** + * Execute a given code block and verify, if the exception type is expected. + * @param r Code block to run + * @param ex Expected exception type + * @param shouldPass If the code execution expected to pass without failure + * @param msg Message to log in case of expected failure + */ + private static SecureRandom matchExc(RunnableCode r, boolean shouldPass, + Class ex, String msg) { + SecureRandom sr = null; + try { + sr = r.run(); + if (!shouldPass) { + throw new RuntimeException("Excecution should fail here."); + } + } catch (Exception e) { + System.out.printf("%nOccured exception: %s - Expected exception: %s" + + " : ", e.getClass(), ex.getCanonicalName()); + if (ex.isAssignableFrom(e.getClass())) { + System.out.printf("%n%s : Expected Exception: %s : ", + e.getClass(), msg); + } else if (shouldPass) { + throw new RuntimeException(e); + } else { + System.out.printf("%nIgnore the following exception: %s%n", + e.getMessage()); + } + } + return sr; + } + + /** + * Check specific attributes of a SecureRandom instance. + */ + private static void checkAttributes(SecureRandom sr, String mech) { + if (sr == null) { + return; + } + Asserts.assertEquals(sr.getAlgorithm(), (isDRBG(mech) ? "DRBG" : mech)); + Asserts.assertEquals(sr.getProvider().getName(), SUN_PROVIDER); + } + +} diff --git a/jdk/test/java/security/SecureRandom/MultiThreadTest.java b/jdk/test/java/security/SecureRandom/MultiThreadTest.java new file mode 100644 index 00000000000..82c6d68dd94 --- /dev/null +++ b/jdk/test/java/security/SecureRandom/MultiThreadTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.math.BigInteger; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.Security; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import static java.lang.Math.*; + +/* + * @test + * @bug 8141039 + * @library /lib/testlibrary + * @summary Test behavior of a shared SecureRandom object when it is operated + * by multiple threads concurrently. + * @run main/othervm -Djava.security.egd=file:/dev/urandom MultiThreadTest + */ +public class MultiThreadTest { + + private static final byte[] GEN_RND_BYTES = {1}; + private static final String DRBG_CONFIG = "securerandom.drbg.config"; + private static final String DRBG_CONFIG_VALUE + = Security.getProperty(DRBG_CONFIG); + + private enum SEED { + + NONE, RESEED, SETSEED + } + + public static void main(String[] args) { + + boolean success = true; + for (int byteLen : GEN_RND_BYTES) { + for (SEED reSeed : SEED.values()) { + for (String mech : new String[]{ + "SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) { + try { + forEachMech(mech, byteLen, reSeed); + } catch (Exception e) { + success = false; + e.printStackTrace(System.out); + } finally { + Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); + } + } + } + } + + if (!success) { + throw new RuntimeException("At least one test failed."); + } + } + + /** + * Generate a number of threads to fetch random numbers of certain bits + * generated through a shared SecureRandom instance. + * @param mech Mechanism name + * @param byteLen Number of bytes of random number to produce + * @param reSeed Call reseed() before generating random numbers + * @throws NoSuchAlgorithmException + * @throws InterruptedException + * @throws ExecutionException + */ + private static void forEachMech(String mech, int byteLen, SEED reSeed) + throws NoSuchAlgorithmException, InterruptedException, + ExecutionException { + + if ("SHA1PRNG".equals(mech) && SEED.RESEED.equals(reSeed)) { + System.out.printf( + "%nreseed() api is not supported for '%s'", mech); + return; + } + System.out.printf("%nTest SecureRandom mechanism: '%s' with support of" + + " reseed: '%s'", mech, reSeed); + int threadCount = (int) pow(2, 8 * byteLen); + System.out.printf("%nCreating %s number of threads to generate secure " + + "random numbers concurrently.", threadCount); + + ExecutorService executor + = Executors.newCachedThreadPool(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = Executors.defaultThreadFactory() + .newThread(r); + t.setDaemon(true); + return t; + } + }); + CompletionService completionService + = new ExecutorCompletionService(executor); + + CountDownLatch latch = new CountDownLatch(1); + SecureRandom rnd = null; + if (!mech.contains("_DRBG")) { + rnd = SecureRandom.getInstance(mech); + } else { + Security.setProperty(DRBG_CONFIG, mech); + rnd = SecureRandom.getInstance("DRBG"); + } + try { + for (int i = 0; i < threadCount; i++) { + completionService.submit(new Task(rnd, latch, byteLen, reSeed)); + } + latch.countDown(); + + for (int i = 0; i < threadCount; i++) { + completionService.take(); + } + } finally { + executor.shutdown(); + } + System.out.printf("%nCompleted Test for algorithm '%s' with thread " + + "counts to '%s' using reseeding '%s'", + mech, threadCount, reSeed); + + } + + /** + * Define a Task to be executed by multiple thread to produce random numbers + * from a shared SecureRandom instance. + */ + private static class Task implements Callable { + + private final SecureRandom random; + private final CountDownLatch latch; + private final SEED reSeed; + private final int byteSize; + + public Task(SecureRandom random, CountDownLatch latch, int byteSize, + SEED reSeed) { + this.random = random; + this.latch = latch; + this.byteSize = byteSize; + this.reSeed = reSeed; + } + + @Override + public Integer call() throws Exception { + latch.await(); + switch (this.reSeed) { + case RESEED: + this.random.reseed(); + break; + case SETSEED: + this.random.setSeed(1l); + break; + } + byte[] bytes = new byte[byteSize]; + random.nextBytes(bytes); + return new BigInteger(bytes).intValue(); + } + } + +} diff --git a/jdk/test/java/security/SecureRandom/Serialize.java b/jdk/test/java/security/SecureRandom/Serialize.java index 799f1bfa428..2e364878c80 100644 --- a/jdk/test/java/security/SecureRandom/Serialize.java +++ b/jdk/test/java/security/SecureRandom/Serialize.java @@ -24,6 +24,7 @@ /* @test * @bug 4102896 * @summary Make sure that a SecureRandom object can be serialized + * @run main/othervm Serialize */ import java.security.*; @@ -32,6 +33,8 @@ import java.io.*; public class Serialize { public static void main(String args[]) throws Exception { + System.setProperty("java.security.egd", "file:/dev/urandom"); + for (String alg: new String[]{ "SHA1PRNG", "DRBG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG", "Hash_DRBG,SHA-512,192,pr_and_reseed"}) { diff --git a/jdk/test/java/security/SecureRandom/SerializedSeedTest.java b/jdk/test/java/security/SecureRandom/SerializedSeedTest.java new file mode 100644 index 00000000000..9af7296c4ab --- /dev/null +++ b/jdk/test/java/security/SecureRandom/SerializedSeedTest.java @@ -0,0 +1,214 @@ +/* + * 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 8141039 + * @library /lib/testlibrary + * @summary When random number is generated through the a SecureRandom instance + * as well from it's serialized instance in the same time then the + * generated random numbers should be different when one or both are + * reseeded. + * @run main/othervm -Djava.security.egd=file:/dev/urandom SerializedSeedTest + */ +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ByteArrayInputStream; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.Security; +import jdk.testlibrary.Asserts; + +public class SerializedSeedTest { + + private static final byte[] SEED = "seed".getBytes(); + private static final String DRBG_CONFIG = "securerandom.drbg.config"; + private static final String DRBG_CONFIG_VALUE + = Security.getProperty(DRBG_CONFIG); + + public static void main(String[] args) { + boolean success = true; + + for (String mech : new String[]{ + "SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) { + System.out.printf( + "%nRunning test for SecureRandom mechanism: '%s'", mech); + try { + // Serialize without seed and compare generated random numbers + // produced through original and serialized instances. + SecureRandom orig = getSRInstance(mech); + SecureRandom copy = deserializedCopy(orig); + System.out.printf("%nSerialize without seed. Generated random" + + " numbers should be different."); + check(orig, copy, false, mech); + + // Serialize after default seed and compare generated random + // numbers produced through original and serialized instances. + orig = getSRInstance(mech); + orig.nextInt(); // Default seeded + copy = deserializedCopy(orig); + System.out.printf("%nSerialize after default seed. Generated" + + " random numbers should be same till 20-bytes."); + check(orig, copy, !isDRBG(mech), mech); + + // Serialize after explicit seed and compare generated random + // numbers produced through original and serialized instances. + orig = getSRInstance(mech); + orig.setSeed(SEED); // Explicitly seeded + copy = deserializedCopy(orig); + System.out.printf("%nSerialize after explicit seed. Generated " + + "random numbers should be same till 20-bytes."); + check(orig, copy, !isDRBG(mech), mech); + + // Serialize without seed but original is explicitly seeded + // before generating any random number. Then compare generated + // random numbers produced through original and serialized + // instances. + orig = getSRInstance(mech); + copy = deserializedCopy(orig); + orig.setSeed(SEED); // Explicitly seeded + System.out.printf("%nSerialize without seed. When original is " + + "explicitly seeded before generating random numbers," + + " Generated random numbers should be different."); + check(orig, copy, false, mech); + + // Serialize after default seed but original is explicitly + // seeded before generating any random number. Then compare + // generated random numbers produced through original and + // serialized instances. + orig = getSRInstance(mech); + orig.nextInt(); // Default seeded + copy = deserializedCopy(orig); + orig.setSeed(SEED); // Explicitly seeded + System.out.printf("%nSerialize after default seed but original " + + "is explicitly seeded before generating random number" + + ". Generated random numbers should be different."); + check(orig, copy, false, mech); + + // Serialize after explicit seed but original is explicitly + // seeded again before generating random number. Then compare + // generated random numbers produced through original and + // serialized instances. + orig = getSRInstance(mech); + orig.setSeed(SEED); // Explicitly seeded + copy = deserializedCopy(orig); + orig.setSeed(SEED); // Explicitly seeded + System.out.printf("%nSerialize after explicit seed but " + + "original is explicitly seeded again before " + + "generating random number. Generated random " + + "numbers should be different."); + check(orig, copy, false, mech); + + } catch (Exception e) { + e.printStackTrace(System.out); + success = false; + } finally { + Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); + } + System.out.printf("%n------Completed Test for %s------", mech); + } + + if (!success) { + throw new RuntimeException("At least one test failed."); + } + } + + /** + * Find if the mechanism is a DRBG mechanism. + * @param mech Mechanism name + * @return True for DRBG mechanism else False + */ + private static boolean isDRBG(String mech) { + return mech.contains("_DRBG"); + } + + /** + * Verify the similarity of random numbers generated though both original + * as well as deserialized instance. + */ + private static void check(SecureRandom orig, SecureRandom copy, + boolean equal, String mech) { + int o = orig.nextInt(); + int c = copy.nextInt(); + System.out.printf("%nRandom number generated for mechanism: '%s' " + + "from original instance as: '%s' and from serialized " + + "instance as: '%s'", mech, o, c); + if (equal) { + Asserts.assertEquals(o, c, mech); + } else { + Asserts.assertNotEquals(o, c, mech); + } + } + + /** + * Get a copy of SecureRandom instance through deserialization. + * @param orig Original SecureRandom instance + * @return Deserialized SecureRandom instance + * @throws IOException + * @throws ClassNotFoundException + */ + private static SecureRandom deserializedCopy(SecureRandom orig) + throws IOException, ClassNotFoundException { + return deserialize(serialize(orig)); + } + + /** + * Deserialize the SecureRandom object. + */ + private static SecureRandom deserialize(byte[] serialized) + throws IOException, ClassNotFoundException { + SecureRandom sr = null; + try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized); + ObjectInputStream ois = new ObjectInputStream(bis)) { + sr = (SecureRandom) ois.readObject(); + } + return sr; + } + + /** + * Serialize the given SecureRandom object. + */ + private static byte[] serialize(SecureRandom sr) throws IOException { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos)) { + oos.writeObject(sr); + return bos.toByteArray(); + } + } + + /** + * Create a SecureRandom instance for a given mechanism. + */ + private static SecureRandom getSRInstance(String mech) + throws NoSuchAlgorithmException { + if (!isDRBG(mech)) { + return SecureRandom.getInstance(mech); + } else { + Security.setProperty(DRBG_CONFIG, mech); + return SecureRandom.getInstance("DRBG"); + } + } + +} diff --git a/jdk/test/java/sql/TEST.properties b/jdk/test/java/sql/TEST.properties new file mode 100644 index 00000000000..878b05fc591 --- /dev/null +++ b/jdk/test/java/sql/TEST.properties @@ -0,0 +1,2 @@ +modules = java.sql + diff --git a/jdk/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java b/jdk/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java new file mode 100644 index 00000000000..9417ddbec4d --- /dev/null +++ b/jdk/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4136620 4144590 + @summary Make sure that Attribute & subclasses are serialized and deserialized correctly + @modules java.desktop + */ + +import java.text.AttributedCharacterIterator.Attribute; +import java.awt.font.TextAttribute; +import java.io.*; + +public class ReadResolve { + + public static void main(String[] args) throws Exception { + testSerializationCycle(Attribute.LANGUAGE); + testSerializationCycle(TextAttribute.INPUT_METHOD_HIGHLIGHT); + + boolean gotException = false; + Attribute result = null; + try { + result = doSerializationCycle(FakeAttribute.LANGUAGE); + } catch (Throwable e) { + gotException = true; + } + if (!gotException) { + throw new RuntimeException("Attribute should throw an exception when given a fake \"language\" attribute. Deserialized object: " + result); + } + } + + static Attribute doSerializationCycle(Attribute attribute) throws Exception { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(attribute); + oos.flush(); + + byte[] data = baos.toByteArray(); + + ByteArrayInputStream bais = new ByteArrayInputStream(data); + ObjectInputStream ois = new ObjectInputStream(bais); + Attribute result = (Attribute) ois.readObject(); + + return result; + } + + static void testSerializationCycle(Attribute attribute) throws Exception { + Attribute result = doSerializationCycle(attribute); + if (result != attribute) { + throw new RuntimeException("attribute changed identity during serialization/deserialization"); + } + } + + private static class FakeAttribute extends Attribute { + + // This LANGUAGE attribute should never be confused with the + // Attribute.LANGUAGE attribute. However, we don't override + // readResolve here, so that deserialization goes + // to Attribute. Attribute has to catch this problem and reject + // the fake attribute. + static final FakeAttribute LANGUAGE = new FakeAttribute("language"); + + FakeAttribute(String name) { + super(name); + } + } +} diff --git a/jdk/test/java/text/AttributedString/AttributedStringTest.java b/jdk/test/java/text/AttributedString/AttributedStringTest.java new file mode 100644 index 00000000000..bab39962359 --- /dev/null +++ b/jdk/test/java/text/AttributedString/AttributedStringTest.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4139771 + * @summary test all aspects of AttributedString class + */ + +import java.text.Annotation; +import java.text.AttributedCharacterIterator; +import java.text.AttributedCharacterIterator.Attribute; +import java.text.AttributedString; +import java.text.CharacterIterator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + + +public class AttributedStringTest { + + private static final String text = "Hello, world!"; + private static final Annotation hi = new Annotation("hi"); + private static final int[] array5_13 = {5, 13}; + private static final int[] array3_9_13 = {3, 9, 13}; + private static final int[] array5_9_13 = {5, 9, 13}; + private static final int[] array3_5_9_13 = {3, 5, 9, 13}; + private static final Attribute[] arrayLanguage = {Attribute.LANGUAGE}; + private static final Attribute[] arrayLanguageReading = {Attribute.LANGUAGE, Attribute.READING}; + private static final Set setLanguageReading = new HashSet(); + static { + setLanguageReading.add(Attribute.LANGUAGE); + setLanguageReading.add(Attribute.READING); + } + + + public static final void main(String argv[]) throws Exception { + + + AttributedString string; + AttributedCharacterIterator iterator; + + // create a string with text, but no attributes + string = new AttributedString(text); + iterator = string.getIterator(); + + // make sure the text is there and attributes aren't + checkIteratorText(iterator, text); + if (!iterator.getAllAttributeKeys().isEmpty()) { + throwException(iterator, "iterator provides attributes where none are defined"); + } + + // add an attribute to a subrange + string.addAttribute(Attribute.LANGUAGE, Locale.ENGLISH, 3, 9); + iterator = string.getIterator(); + + // make sure the attribute is defined, and it's on the correct subrange + checkIteratorAttributeKeys(iterator, arrayLanguage); + checkIteratorSubranges(iterator, array3_9_13); + checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null); + checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH); + checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); + + // add an attribute to a subrange + string.addAttribute(Attribute.READING, hi, 0, 5); + iterator = string.getIterator(); + + // make sure the attribute is defined, and it's on the correct subrange + checkIteratorAttributeKeys(iterator, arrayLanguageReading); + checkIteratorSubranges(iterator, array3_5_9_13); + checkIteratorAttribute(iterator, 0, Attribute.READING, hi); + checkIteratorAttribute(iterator, 3, Attribute.READING, hi); + checkIteratorAttribute(iterator, 5, Attribute.READING, null); + checkIteratorAttribute(iterator, 9, Attribute.READING, null); + + // make sure the first attribute wasn't adversely affected + // in particular, we shouldn't see separate subranges (3,5) and (5,9). + checkIteratorSubranges(iterator, Attribute.LANGUAGE, array3_9_13); + checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null); + checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH); + checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH); + checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); + + // for the entire set of attributes, we expect four subranges + checkIteratorSubranges(iterator, setLanguageReading, array3_5_9_13); + + // redefine the language attribute so that both language and reading are continuous from 0 to 5 + string.addAttribute(Attribute.LANGUAGE, Locale.US, 0, 5); + iterator = string.getIterator(); + + // make sure attributes got changed and merged correctly + checkIteratorAttributeKeys(iterator, arrayLanguageReading); + checkIteratorSubranges(iterator, array3_5_9_13); + checkIteratorSubranges(iterator, Attribute.LANGUAGE, array5_9_13); + checkIteratorSubranges(iterator, Attribute.READING, array5_13); + checkIteratorSubranges(iterator, setLanguageReading, array5_9_13); + checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, Locale.US); + checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.US); + checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH); + checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); + + // make sure an annotation is only returned if its range is contained in the iterator's range + iterator = string.getIterator(null, 3, 5); + checkIteratorAttribute(iterator, 3, Attribute.READING, null); + checkIteratorAttribute(iterator, 5, Attribute.READING, null); + iterator = string.getIterator(null, 0, 4); + checkIteratorAttribute(iterator, 0, Attribute.READING, null); + checkIteratorAttribute(iterator, 3, Attribute.READING, null); + iterator = string.getIterator(null, 0, 5); + checkIteratorAttribute(iterator, 0, Attribute.READING, hi); + checkIteratorAttribute(iterator, 4, Attribute.READING, hi); + checkIteratorAttribute(iterator, 5, Attribute.READING, null); + + } + + private static final void checkIteratorText(AttributedCharacterIterator iterator, String expectedText) throws Exception { + if (iterator.getEndIndex() - iterator.getBeginIndex() != expectedText.length()) { + throwException(iterator, "text length doesn't match between original text and iterator"); + } + + char c = iterator.first(); + for (int i = 0; i < expectedText.length(); i++) { + if (c != expectedText.charAt(i)) { + throwException(iterator, "text content doesn't match between original text and iterator"); + } + c = iterator.next(); + } + if (c != CharacterIterator.DONE) { + throwException(iterator, "iterator text doesn't end with DONE"); + } + } + + private static final void checkIteratorAttributeKeys(AttributedCharacterIterator iterator, Attribute[] expectedKeys) throws Exception { + Set iteratorKeys = iterator.getAllAttributeKeys(); + if (iteratorKeys.size() != expectedKeys.length) { + throwException(iterator, "number of keys returned by iterator doesn't match expectation"); + } + for (int i = 0; i < expectedKeys.length; i++) { + if (!iteratorKeys.contains(expectedKeys[i])) { + throwException(iterator, "expected key wasn't found in iterator's key set"); + } + } + } + + private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, int[] expectedLimits) throws Exception { + int previous = 0; + char c = iterator.first(); + for (int i = 0; i < expectedLimits.length; i++) { + if (iterator.getRunStart() != previous || iterator.getRunLimit() != expectedLimits[i]) { + throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart() + ", " + iterator.getRunLimit()); + } + previous = expectedLimits[i]; + c = iterator.setIndex(previous); + } + if (c != CharacterIterator.DONE) { + throwException(iterator, "iterator's run sequence doesn't end with DONE"); + } + } + + private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Attribute key, int[] expectedLimits) throws Exception { + int previous = 0; + char c = iterator.first(); + for (int i = 0; i < expectedLimits.length; i++) { + if (iterator.getRunStart(key) != previous || iterator.getRunLimit(key) != expectedLimits[i]) { + throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(key) + ", " + iterator.getRunLimit(key) + " for key " + key); + } + previous = expectedLimits[i]; + c = iterator.setIndex(previous); + } + if (c != CharacterIterator.DONE) { + throwException(iterator, "iterator's run sequence doesn't end with DONE"); + } + } + + private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Set keys, int[] expectedLimits) throws Exception { + int previous = 0; + char c = iterator.first(); + for (int i = 0; i < expectedLimits.length; i++) { + if (iterator.getRunStart(keys) != previous || iterator.getRunLimit(keys) != expectedLimits[i]) { + throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(keys) + ", " + iterator.getRunLimit(keys) + " for keys " + keys); + } + previous = expectedLimits[i]; + c = iterator.setIndex(previous); + } + if (c != CharacterIterator.DONE) { + throwException(iterator, "iterator's run sequence doesn't end with DONE"); + } + } + + private static final void checkIteratorAttribute(AttributedCharacterIterator iterator, int index, Attribute key, Object expectedValue) throws Exception { + iterator.setIndex(index); + Object value = iterator.getAttribute(key); + if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) { + throwException(iterator, "iterator returns wrong attribute value - " + value + " instead of " + expectedValue); + } + value = iterator.getAttributes().get(key); + if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) { + throwException(iterator, "iterator's map returns wrong attribute value - " + value + " instead of " + expectedValue); + } + } + + private static final void throwException(AttributedCharacterIterator iterator, String details) throws Exception { + dumpIterator(iterator); + throw new Exception(details); + } + + private static final void dumpIterator(AttributedCharacterIterator iterator) { + Set attributeKeys = iterator.getAllAttributeKeys(); + System.out.print("All attributes: "); + Iterator keyIterator = attributeKeys.iterator(); + while (keyIterator.hasNext()) { + Attribute key = (Attribute) keyIterator.next(); + System.out.print(key); + } + for(char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) { + if (iterator.getIndex() == iterator.getBeginIndex() || + iterator.getIndex() == iterator.getRunStart()) { + System.out.println(); + Map attributes = iterator.getAttributes(); + Set entries = attributes.entrySet(); + Iterator attributeIterator = entries.iterator(); + while (attributeIterator.hasNext()) { + Map.Entry entry = (Map.Entry) attributeIterator.next(); + System.out.print("<" + entry.getKey() + ": " + + entry.getValue() + ">"); + } + } + System.out.print(" "); + System.out.print(c); + } + System.out.println(); + System.out.println("done"); + System.out.println(); + } + +} diff --git a/jdk/test/java/text/AttributedString/TestAttributedStringCtor.java b/jdk/test/java/text/AttributedString/TestAttributedStringCtor.java new file mode 100644 index 00000000000..0f9ed615ef9 --- /dev/null +++ b/jdk/test/java/text/AttributedString/TestAttributedStringCtor.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4146853 + * @summary Make sure we can construct an AttributedString from + * an AttributedCharacterIterator covering only a subrange + * @modules java.desktop + */ + +import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.Hashtable; + +public class TestAttributedStringCtor { + + public static void main(String[] args) { + + // Create a new AttributedString with one attribute. + Hashtable attributes = new Hashtable(); + attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); + AttributedString origString = new AttributedString("Hello world.", attributes); + + // Create an iterator over part of the AttributedString. + AttributedCharacterIterator iter = origString.getIterator(null, 4, 6); + + // Attempt to create a new AttributedString from the iterator. + // This will throw IllegalArgumentException. + AttributedString newString = new AttributedString(iter); + + // Without the exception this would get executed. + System.out.println("DONE"); + } +} diff --git a/jdk/test/java/text/AttributedString/getRunStartLimitTest.java b/jdk/test/java/text/AttributedString/getRunStartLimitTest.java new file mode 100644 index 00000000000..c0acfcfb507 --- /dev/null +++ b/jdk/test/java/text/AttributedString/getRunStartLimitTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4151160 + * @summary Make sure to return correct run start and limit values + * when the iterator has been created with begin and end index values. + * @modules java.desktop + */ + +import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.text.Annotation; + +public class getRunStartLimitTest { + + public static void main(String[] args) throws Exception { + + String text = "Hello world"; + AttributedString as = new AttributedString(text); + + // add non-Annotation attributes + as.addAttribute(TextAttribute.WEIGHT, + TextAttribute.WEIGHT_LIGHT, + 0, + 3); + as.addAttribute(TextAttribute.WEIGHT, + TextAttribute.WEIGHT_BOLD, + 3, + 5); + as.addAttribute(TextAttribute.WEIGHT, + TextAttribute.WEIGHT_EXTRABOLD, + 5, + text.length()); + + // add Annotation attributes + as.addAttribute(TextAttribute.WIDTH, + new Annotation(TextAttribute.WIDTH_EXTENDED), + 0, + 3); + as.addAttribute(TextAttribute.WIDTH, + new Annotation(TextAttribute.WIDTH_CONDENSED), + 3, + 4); + + AttributedCharacterIterator aci = as.getIterator(null, 2, 4); + + aci.first(); + int runStart = aci.getRunStart(); + if (runStart != 2) { + throw new Exception("1st run start is wrong. ("+runStart+" should be 2.)"); + } + + int runLimit = aci.getRunLimit(); + if (runLimit != 3) { + throw new Exception("1st run limit is wrong. ("+runLimit+" should be 3.)"); + } + + Object value = aci.getAttribute(TextAttribute.WEIGHT); + if (value != TextAttribute.WEIGHT_LIGHT) { + throw new Exception("1st run attribute is wrong. (" + +value+" should be "+TextAttribute.WEIGHT_LIGHT+".)"); + } + + value = aci.getAttribute(TextAttribute.WIDTH); + if (value != null) { + throw new Exception("1st run annotation is wrong. (" + +value+" should be null.)"); + } + + aci.setIndex(runLimit); + runStart = aci.getRunStart(); + if (runStart != 3) { + throw new Exception("2nd run start is wrong. ("+runStart+" should be 3.)"); + } + + runLimit = aci.getRunLimit(); + if (runLimit != 4) { + throw new Exception("2nd run limit is wrong. ("+runLimit+" should be 4.)"); + } + value = aci.getAttribute(TextAttribute.WEIGHT); + if (value != TextAttribute.WEIGHT_BOLD) { + throw new Exception("2nd run attribute is wrong. (" + +value+" should be "+TextAttribute.WEIGHT_BOLD+".)"); + } + + value = aci.getAttribute(TextAttribute.WIDTH); + if (!(value instanceof Annotation) + || (((Annotation)value).getValue() != TextAttribute.WIDTH_CONDENSED)) { + throw new Exception("2nd run annotation is wrong. (" + value + " should be " + + new Annotation(TextAttribute.WIDTH_CONDENSED)+".)"); + } + } +} diff --git a/jdk/test/java/text/BreakIterator/BreakIteratorTest.java b/jdk/test/java/text/BreakIterator/BreakIteratorTest.java new file mode 100644 index 00000000000..3c2498de48e --- /dev/null +++ b/jdk/test/java/text/BreakIterator/BreakIteratorTest.java @@ -0,0 +1,1438 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4035266 4052418 4068133 4068137 4068139 4086052 4095322 4097779 + * 4097920 4098467 4111338 4113835 4117554 4143071 4146175 4152117 + * 4152416 4153072 4158381 4214367 4217703 4638433 + * @library /java/text/testlib + * @run main/timeout=2000 BreakIteratorTest + * @summary test BreakIterator + */ + +/* + * + * + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved + * + * Portions copyright (c) 2007 Sun Microsystems, Inc. + * All Rights Reserved. + * + * The original version of this source code and documentation + * is copyrighted and owned by Taligent, Inc., a wholly-owned + * subsidiary of IBM. These materials are provided under terms + * of a License Agreement between Taligent and Sun. This technology + * is protected by multiple US and International patents. + * + * This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + */ + +import java.text.BreakIterator; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Locale; +import java.util.Vector; +import java.util.Enumeration; +import java.io.*; + +public class BreakIteratorTest extends IntlTest +{ + private BreakIterator characterBreak; + private BreakIterator wordBreak; + private BreakIterator lineBreak; + private BreakIterator sentenceBreak; + + public static void main(String[] args) throws Exception { + new BreakIteratorTest().run(args); + } + + public BreakIteratorTest() + { + characterBreak = BreakIterator.getCharacterInstance(); + wordBreak = BreakIterator.getWordInstance(); + lineBreak = BreakIterator.getLineInstance(); + sentenceBreak = BreakIterator.getSentenceInstance(); + } + + //========================================================================= + // general test subroutines + //========================================================================= + + private void generalIteratorTest(BreakIterator bi, Vector expectedResult) { + StringBuffer buffer = new StringBuffer(); + String text; + for (int i = 0; i < expectedResult.size(); i++) { + text = (String)expectedResult.elementAt(i); + buffer.append(text); + } + text = buffer.toString(); + + bi.setText(text); + + Vector nextResults = testFirstAndNext(bi, text); + Vector previousResults = testLastAndPrevious(bi, text); + + logln("comparing forward and backward..."); + int errs = getErrorCount(); + compareFragmentLists("forward iteration", "backward iteration", nextResults, + previousResults); + if (getErrorCount() == errs) { + logln("comparing expected and actual..."); + compareFragmentLists("expected result", "actual result", expectedResult, + nextResults); + } + + int[] boundaries = new int[expectedResult.size() + 3]; + boundaries[0] = BreakIterator.DONE; + boundaries[1] = 0; + for (int i = 0; i < expectedResult.size(); i++) + boundaries[i + 2] = boundaries[i + 1] + ((String)expectedResult.elementAt(i)). + length(); + boundaries[boundaries.length - 1] = BreakIterator.DONE; + + testFollowing(bi, text, boundaries); + testPreceding(bi, text, boundaries); + testIsBoundary(bi, text, boundaries); + + doMultipleSelectionTest(bi, text); + } + + private Vector testFirstAndNext(BreakIterator bi, String text) { + int p = bi.first(); + int lastP = p; + Vector result = new Vector(); + + if (p != 0) + errln("first() returned " + p + " instead of 0"); + while (p != BreakIterator.DONE) { + p = bi.next(); + if (p != BreakIterator.DONE) { + if (p <= lastP) + errln("next() failed to move forward: next() on position " + + lastP + " yielded " + p); + + result.addElement(text.substring(lastP, p)); + } + else { + if (lastP != text.length()) + errln("next() returned DONE prematurely: offset was " + + lastP + " instead of " + text.length()); + } + lastP = p; + } + return result; + } + + private Vector testLastAndPrevious(BreakIterator bi, String text) { + int p = bi.last(); + int lastP = p; + Vector result = new Vector(); + + if (p != text.length()) + errln("last() returned " + p + " instead of " + text.length()); + while (p != BreakIterator.DONE) { + p = bi.previous(); + if (p != BreakIterator.DONE) { + if (p >= lastP) + errln("previous() failed to move backward: previous() on position " + + lastP + " yielded " + p); + + result.insertElementAt(text.substring(p, lastP), 0); + } + else { + if (lastP != 0) + errln("previous() returned DONE prematurely: offset was " + + lastP + " instead of 0"); + } + lastP = p; + } + return result; + } + + private void compareFragmentLists(String f1Name, String f2Name, Vector f1, Vector f2) { + int p1 = 0; + int p2 = 0; + String s1; + String s2; + int t1 = 0; + int t2 = 0; + + while (p1 < f1.size() && p2 < f2.size()) { + s1 = (String)f1.elementAt(p1); + s2 = (String)f2.elementAt(p2); + t1 += s1.length(); + t2 += s2.length(); + + if (s1.equals(s2)) { + debugLogln(" >" + s1 + "<"); + ++p1; + ++p2; + } + else { + int tempT1 = t1; + int tempT2 = t2; + int tempP1 = p1; + int tempP2 = p2; + + while (tempT1 != tempT2 && tempP1 < f1.size() && tempP2 < f2.size()) { + while (tempT1 < tempT2 && tempP1 < f1.size()) { + tempT1 += ((String)f1.elementAt(tempP1)).length(); + ++tempP1; + } + while (tempT2 < tempT1 && tempP2 < f2.size()) { + tempT2 += ((String)f2.elementAt(tempP2)).length(); + ++tempP2; + } + } + logln("*** " + f1Name + " has:"); + while (p1 <= tempP1 && p1 < f1.size()) { + s1 = (String)f1.elementAt(p1); + t1 += s1.length(); + debugLogln(" *** >" + s1 + "<"); + ++p1; + } + logln("***** " + f2Name + " has:"); + while (p2 <= tempP2 && p2 < f2.size()) { + s2 = (String)f2.elementAt(p2); + t2 += s2.length(); + debugLogln(" ***** >" + s2 + "<"); + ++p2; + } + errln("Discrepancy between " + f1Name + " and " + f2Name + "\n---\n" + f1 +"\n---\n" + f2); + } + } + } + + private void testFollowing(BreakIterator bi, String text, int[] boundaries) { + logln("testFollowing():"); + int p = 2; + int i = 0; + try { + for (i = 0; i <= text.length(); i++) { // change to <= when new BI code goes in + if (i == boundaries[p]) + ++p; + + int b = bi.following(i); + logln("bi.following(" + i + ") -> " + b); + if (b != boundaries[p]) + errln("Wrong result from following() for " + i + ": expected " + boundaries[p] + + ", got " + b); + } + } catch (IllegalArgumentException illargExp) { + errln("IllegalArgumentException caught from following() for offset: " + i); + } + } + + private void testPreceding(BreakIterator bi, String text, int[] boundaries) { + logln("testPreceding():"); + int p = 0; + int i = 0; + try { + for (i = 0; i <= text.length(); i++) { // change to <= when new BI code goes in + int b = bi.preceding(i); + logln("bi.preceding(" + i + ") -> " + b); + if (b != boundaries[p]) + errln("Wrong result from preceding() for " + i + ": expected " + boundaries[p] + + ", got " + b); + + if (i == boundaries[p + 1]) + ++p; + } + } catch (IllegalArgumentException illargExp) { + errln("IllegalArgumentException caught from preceding() for offset: " + i); + } + } + + private void testIsBoundary(BreakIterator bi, String text, int[] boundaries) { + logln("testIsBoundary():"); + int p = 1; + boolean isB; + for (int i = 0; i <= text.length(); i++) { // change to <= when new BI code goes in + isB = bi.isBoundary(i); + logln("bi.isBoundary(" + i + ") -> " + isB); + + if (i == boundaries[p]) { + if (!isB) + errln("Wrong result from isBoundary() for " + i + ": expected true, got false"); + ++p; + } + else { + if (isB) + errln("Wrong result from isBoundary() for " + i + ": expected false, got true"); + } + } + } + + private void doMultipleSelectionTest(BreakIterator iterator, String testText) + { + logln("Multiple selection test..."); + BreakIterator testIterator = (BreakIterator)iterator.clone(); + int offset = iterator.first(); + int testOffset; + int count = 0; + + do { + testOffset = testIterator.first(); + testOffset = testIterator.next(count); + logln("next(" + count + ") -> " + testOffset); + if (offset != testOffset) + errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset); + + if (offset != BreakIterator.DONE) { + count++; + offset = iterator.next(); + } + } while (offset != BreakIterator.DONE); + + // now do it backwards... + offset = iterator.last(); + count = 0; + + do { + testOffset = testIterator.last(); + testOffset = testIterator.next(count); + logln("next(" + count + ") -> " + testOffset); + if (offset != testOffset) + errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset); + + if (offset != BreakIterator.DONE) { + count--; + offset = iterator.previous(); + } + } while (offset != BreakIterator.DONE); + } + + private void doBreakInvariantTest(BreakIterator tb, String testChars) + { + StringBuffer work = new StringBuffer("aaa"); + int errorCount = 0; + + // a break should always occur after CR (unless followed by LF), LF, PS, and LS + String breaks = /*"\r\n\u2029\u2028"*/"\n\u2029\u2028"; + // change this back when new BI code is added + + for (int i = 0; i < breaks.length(); i++) { + work.setCharAt(1, breaks.charAt(i)); + for (int j = 0; j < testChars.length(); j++) { + work.setCharAt(0, testChars.charAt(j)); + for (int k = 0; k < testChars.length(); k++) { + char c = testChars.charAt(k); + + // if a cr is followed by lf, don't do the check (they stay together) + if (work.charAt(1) == '\r' && (c == '\n')) + continue; + + // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored + // for breaking purposes as per UTR14 + int type1 = Character.getType(work.charAt(1)); + int type2 = Character.getType(c); + if (type1 == Character.CONTROL || type1 == Character.FORMAT || + type2 == Character.CONTROL || type2 == Character.FORMAT) { + continue; + } + + work.setCharAt(2, c); + tb.setText(work.toString()); + boolean seen2 = false; + for (int l = tb.first(); l != BreakIterator.DONE; l = tb.next()) { + if (l == 2) + seen2 = true; + } + if (!seen2) { + errln("No break between U+" + Integer.toHexString((int)(work.charAt(1))) + + " and U+" + Integer.toHexString((int)(work.charAt(2)))); + errorCount++; + if (errorCount >= 75) + return; + } + } + } + } + } + + private void doOtherInvariantTest(BreakIterator tb, String testChars) + { + StringBuffer work = new StringBuffer("a\r\na"); + int errorCount = 0; + + // a break should never occur between CR and LF + for (int i = 0; i < testChars.length(); i++) { + work.setCharAt(0, testChars.charAt(i)); + for (int j = 0; j < testChars.length(); j++) { + work.setCharAt(3, testChars.charAt(j)); + tb.setText(work.toString()); + for (int k = tb.first(); k != BreakIterator.DONE; k = tb.next()) + if (k == 2) { + errln("Break between CR and LF in string U+" + Integer.toHexString( + (int)(work.charAt(0))) + ", U+d U+a U+" + Integer.toHexString( + (int)(work.charAt(3)))); + errorCount++; + if (errorCount >= 75) + return; + } + } + } + + // a break should never occur before a non-spacing mark, unless it's preceded + // by a line terminator + work.setLength(0); + work.append("aaaa"); + for (int i = 0; i < testChars.length(); i++) { + char c = testChars.charAt(i); + if (c == '\n' || c == '\r' || c == '\u2029' || c == '\u2028' || c == '\u0003') + continue; + work.setCharAt(1, c); + for (int j = 0; j < testChars.length(); j++) { + c = testChars.charAt(j); + if (Character.getType(c) != Character.NON_SPACING_MARK && Character.getType(c) + != Character.ENCLOSING_MARK) + continue; + work.setCharAt(2, c); + + // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored + // for breaking purposes as per UTR14 + int type1 = Character.getType(work.charAt(1)); + int type2 = Character.getType(work.charAt(2)); + if (type1 == Character.CONTROL || type1 == Character.FORMAT || + type2 == Character.CONTROL || type2 == Character.FORMAT) { + continue; + } + + tb.setText(work.toString()); + for (int k = tb.first(); k != BreakIterator.DONE; k = tb.next()) + if (k == 2) { + errln("Break between U+" + Integer.toHexString((int)(work.charAt(1))) + + " and U+" + Integer.toHexString((int)(work.charAt(2)))); + errorCount++; + if (errorCount >= 75) + return; + } + } + } + } + + public void debugLogln(String s) { + final String zeros = "0000"; + String temp; + StringBuffer out = new StringBuffer(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c >= ' ' && c < '\u007f') + out.append(c); + else { + out.append("\\u"); + temp = Integer.toHexString((int)c); + out.append(zeros.substring(0, 4 - temp.length())); + out.append(temp); + } + } + logln(out.toString()); + } + + //========================================================================= + // tests + //========================================================================= + + public void TestWordBreak() { + + Vector wordSelectionData = new Vector(); + + wordSelectionData.addElement("12,34"); + + wordSelectionData.addElement(" "); + wordSelectionData.addElement("\u00A2"); //cent sign + wordSelectionData.addElement("\u00A3"); //pound sign + wordSelectionData.addElement("\u00A4"); //currency sign + wordSelectionData.addElement("\u00A5"); //yen sign + wordSelectionData.addElement("alpha-beta-gamma"); + wordSelectionData.addElement("."); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("Badges"); + wordSelectionData.addElement("?"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("BADGES"); + wordSelectionData.addElement("!"); + wordSelectionData.addElement("?"); + wordSelectionData.addElement("!"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("We"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("don't"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("need"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("no"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("STINKING"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("BADGES"); + wordSelectionData.addElement("!"); + wordSelectionData.addElement("!"); + wordSelectionData.addElement("!"); + + wordSelectionData.addElement("012.566,5"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("123.3434,900"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("1000,233,456.000"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("1,23.322%"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("123.1222"); + + wordSelectionData.addElement(" "); + wordSelectionData.addElement("\u0024123,000.20"); + + wordSelectionData.addElement(" "); + wordSelectionData.addElement("179.01\u0025"); + + wordSelectionData.addElement("Hello"); + wordSelectionData.addElement(","); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("how"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("are"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("you"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("X"); + wordSelectionData.addElement(" "); + + wordSelectionData.addElement("Now"); + wordSelectionData.addElement("\r"); + wordSelectionData.addElement("is"); + wordSelectionData.addElement("\n"); + wordSelectionData.addElement("the"); + wordSelectionData.addElement("\r\n"); + wordSelectionData.addElement("time"); + wordSelectionData.addElement("\n"); + wordSelectionData.addElement("\r"); + wordSelectionData.addElement("for"); + wordSelectionData.addElement("\r"); + wordSelectionData.addElement("\r"); + wordSelectionData.addElement("all"); + wordSelectionData.addElement(" "); + + generalIteratorTest(wordBreak, wordSelectionData); + } + + public void TestBug4097779() { + Vector wordSelectionData = new Vector(); + + wordSelectionData.addElement("aa\u0300a"); + wordSelectionData.addElement(" "); + + generalIteratorTest(wordBreak, wordSelectionData); + } + + public void TestBug4098467Words() { + Vector wordSelectionData = new Vector(); + + // What follows is a string of Korean characters (I found it in the Yellow Pages + // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed + // it correctly), first as precomposed syllables, and then as conjoining jamo. + // Both sequences should be semantically identical and break the same way. + // precomposed syllables... + wordSelectionData.addElement("\uc0c1\ud56d"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("\ud55c\uc778"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("\uc5f0\ud569"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("\uc7a5\ub85c\uad50\ud68c"); + wordSelectionData.addElement(" "); + // conjoining jamo... + wordSelectionData.addElement("\u1109\u1161\u11bc\u1112\u1161\u11bc"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("\u1112\u1161\u11ab\u110b\u1175\u11ab"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("\u110b\u1167\u11ab\u1112\u1161\u11b8"); + wordSelectionData.addElement(" "); + wordSelectionData.addElement("\u110c\u1161\u11bc\u1105\u1169\u1100\u116d\u1112\u116c"); + wordSelectionData.addElement(" "); + + generalIteratorTest(wordBreak, wordSelectionData); + } + + public void TestBug4117554Words() { + Vector wordSelectionData = new Vector(); + + // this is a test for bug #4117554: the ideographic iteration mark (U+3005) should + // count as a Kanji character for the purposes of word breaking + wordSelectionData.addElement("abc"); + wordSelectionData.addElement("\u4e01\u4e02\u3005\u4e03\u4e03"); + wordSelectionData.addElement("abc"); + + generalIteratorTest(wordBreak, wordSelectionData); + } + + public void TestSentenceBreak() { + Vector sentenceSelectionData = new Vector(); + + sentenceSelectionData.addElement("This is a simple sample sentence. "); + sentenceSelectionData.addElement("(This is it.) "); + sentenceSelectionData.addElement("This is a simple sample sentence. "); + sentenceSelectionData.addElement("\"This isn\'t it.\" "); + sentenceSelectionData.addElement("Hi! "); + sentenceSelectionData.addElement("This is a simple sample sentence. "); + sentenceSelectionData.addElement("It does not have to make any sense as you can see. "); + sentenceSelectionData.addElement("Nel mezzo del cammin di nostra vita, mi ritrovai in una selva oscura. "); + sentenceSelectionData.addElement("Che la dritta via aveo smarrita. "); + sentenceSelectionData.addElement("He said, that I said, that you said!! "); + + sentenceSelectionData.addElement("Don't rock the boat.\u2029"); + + sentenceSelectionData.addElement("Because I am the daddy, that is why. "); + sentenceSelectionData.addElement("Not on my time (el timo.)! "); + + sentenceSelectionData.addElement("So what!!\u2029"); + + sentenceSelectionData.addElement("\"But now,\" he said, \"I know!\" "); + sentenceSelectionData.addElement("Harris thumbed down several, including \"Away We Go\" (which became the huge success Oklahoma!). "); + sentenceSelectionData.addElement("One species, B. anthracis, is highly virulent.\n"); + sentenceSelectionData.addElement("Wolf said about Sounder:\"Beautifully thought-out and directed.\" "); + sentenceSelectionData.addElement("Have you ever said, \"This is where \tI shall live\"? "); + sentenceSelectionData.addElement("He answered, \"You may not!\" "); + sentenceSelectionData.addElement("Another popular saying is: \"How do you do?\". "); + sentenceSelectionData.addElement("Yet another popular saying is: \'I\'m fine thanks.\' "); + sentenceSelectionData.addElement("What is the proper use of the abbreviation pp.? "); + sentenceSelectionData.addElement("Yes, I am definatelly 12\" tall!!"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestBug4113835() { + Vector sentenceSelectionData = new Vector(); + + // test for bug #4113835: \n and \r count as spaces, not as paragraph breaks + sentenceSelectionData.addElement("Now\ris\nthe\r\ntime\n\rfor\r\rall\u2029"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestBug4111338() { + Vector sentenceSelectionData = new Vector(); + + // test for bug #4111338: Don't break sentences at the boundary between CJK + // and other letters + sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165:\"JAVA\u821c" + + "\u8165\u7fc8\u51ce\u306d,\u2494\u56d8\u4ec0\u60b1\u8560\u51ba" + + "\u611d\u57b6\u2510\u5d46\".\u2029"); + sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8" + + "\u97e4JAVA\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8\u4ec0" + + "\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029"); + sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8\u97e4" + + "\u6470\u8790JAVA\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8" + + "\u4ec0\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029"); + sentenceSelectionData.addElement("He said, \"I can go there.\"\u2029"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestBug4117554Sentences() { + Vector sentenceSelectionData = new Vector(); + + // Treat fullwidth variants of .!? the same as their + // normal counterparts + sentenceSelectionData.addElement("I know I'm right\uff0e "); + sentenceSelectionData.addElement("Right\uff1f "); + sentenceSelectionData.addElement("Right\uff01 "); + + // Don't break sentences at boundary between CJK and digits + sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8" + + "\u97e48888\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8\u4ec0" + + "\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029"); + + // Break sentence between a sentence terminator and + // opening punctuation + sentenceSelectionData.addElement("no?"); + sentenceSelectionData.addElement("(yes)"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestBug4158381() { + Vector sentenceSelectionData = new Vector(); + + // Don't break sentence after period if it isn't followed by a space + sentenceSelectionData.addElement("Test Flags.Flag class. "); + sentenceSelectionData.addElement("Another test.\u2029"); + + // No breaks when there are no terminators around + sentenceSelectionData.addElement("

    Provides a set of " + + ""lightweight" (all-javaTM" + + " language) components that, " + + "to the maximum degree possible, work the same on all platforms. "); + sentenceSelectionData.addElement("Another test.\u2029"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestBug4143071() { + Vector sentenceSelectionData = new Vector(); + + // Make sure sentences that end with digits work right + sentenceSelectionData.addElement("Today is the 27th of May, 1998. "); + sentenceSelectionData.addElement("Tomorrow with be 28 May 1998. "); + sentenceSelectionData.addElement("The day after will be the 30th.\u2029"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestBug4152416() { + Vector sentenceSelectionData = new Vector(); + + // Make sure sentences ending with a capital letter are treated correctly + sentenceSelectionData.addElement("The type of all primitive " + + "boolean values accessed in the target VM. "); + sentenceSelectionData.addElement("Calls to xxx will return an " + + "implementor of this interface.\u2029"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestBug4152117() { + Vector sentenceSelectionData = new Vector(); + + // Make sure sentence breaking is handling punctuation correctly + // [COULD NOT REPRODUCE THIS BUG, BUT TEST IS HERE TO MAKE SURE + // IT DOESN'T CROP UP] + sentenceSelectionData.addElement("Constructs a randomly generated " + + "BigInteger, uniformly distributed over the range 0 " + + "to (2numBits - 1), inclusive. "); + sentenceSelectionData.addElement("The uniformity of the distribution " + + "assumes that a fair source of random bits is provided in " + + "rnd. "); + sentenceSelectionData.addElement("Note that this constructor always " + + "constructs a non-negative BigInteger.\u2029"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestLineBreak() { + Vector lineSelectionData = new Vector(); + + lineSelectionData.addElement("Multi-"); + lineSelectionData.addElement("Level "); + lineSelectionData.addElement("example "); + lineSelectionData.addElement("of "); + lineSelectionData.addElement("a "); + lineSelectionData.addElement("semi-"); + lineSelectionData.addElement("idiotic "); + lineSelectionData.addElement("non-"); + lineSelectionData.addElement("sensical "); + lineSelectionData.addElement("(non-"); + lineSelectionData.addElement("important) "); + lineSelectionData.addElement("sentence. "); + + lineSelectionData.addElement("Hi "); + lineSelectionData.addElement("Hello "); + lineSelectionData.addElement("How\n"); + lineSelectionData.addElement("are\r"); + lineSelectionData.addElement("you\u2028"); + lineSelectionData.addElement("fine.\t"); + lineSelectionData.addElement("good. "); + + lineSelectionData.addElement("Now\r"); + lineSelectionData.addElement("is\n"); + lineSelectionData.addElement("the\r\n"); + lineSelectionData.addElement("time\n"); + lineSelectionData.addElement("\r"); + lineSelectionData.addElement("for\r"); + lineSelectionData.addElement("\r"); + lineSelectionData.addElement("all"); + + generalIteratorTest(lineBreak, lineSelectionData); + } + + public void TestBug4068133() { + Vector lineSelectionData = new Vector(); + + lineSelectionData.addElement("\u96f6"); + lineSelectionData.addElement("\u4e00\u3002"); + lineSelectionData.addElement("\u4e8c\u3001"); + lineSelectionData.addElement("\u4e09\u3002\u3001"); + lineSelectionData.addElement("\u56db\u3001\u3002\u3001"); + lineSelectionData.addElement("\u4e94,"); + lineSelectionData.addElement("\u516d."); + lineSelectionData.addElement("\u4e03.\u3001,\u3002"); + lineSelectionData.addElement("\u516b"); + + generalIteratorTest(lineBreak, lineSelectionData); + } + + public void TestBug4086052() { + Vector lineSelectionData = new Vector(); + + lineSelectionData.addElement("foo\u00a0bar "); +// lineSelectionData.addElement("foo\ufeffbar"); + + generalIteratorTest(lineBreak, lineSelectionData); + } + + public void TestBug4097920() { + Vector lineSelectionData = new Vector(); + + lineSelectionData.addElement("dog,"); + lineSelectionData.addElement("cat,"); + lineSelectionData.addElement("mouse "); + lineSelectionData.addElement("(one)"); + lineSelectionData.addElement("(two)\n"); + + generalIteratorTest(lineBreak, lineSelectionData); + } + /* + public void TestBug4035266() { + Vector lineSelectionData = new Vector(); + + lineSelectionData.addElement("The "); + lineSelectionData.addElement("balance "); + lineSelectionData.addElement("is "); + lineSelectionData.addElement("$-23,456.78, "); + lineSelectionData.addElement("not "); + lineSelectionData.addElement("-$32,456.78!\n"); + + generalIteratorTest(lineBreak, lineSelectionData); + } + */ + public void TestBug4098467Lines() { + Vector lineSelectionData = new Vector(); + + // What follows is a string of Korean characters (I found it in the Yellow Pages + // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed + // it correctly), first as precomposed syllables, and then as conjoining jamo. + // Both sequences should be semantically identical and break the same way. + // precomposed syllables... + lineSelectionData.addElement("\uc0c1"); + lineSelectionData.addElement("\ud56d "); + lineSelectionData.addElement("\ud55c"); + lineSelectionData.addElement("\uc778 "); + lineSelectionData.addElement("\uc5f0"); + lineSelectionData.addElement("\ud569 "); + lineSelectionData.addElement("\uc7a5"); + lineSelectionData.addElement("\ub85c"); + lineSelectionData.addElement("\uad50"); + lineSelectionData.addElement("\ud68c "); + // conjoining jamo... + lineSelectionData.addElement("\u1109\u1161\u11bc\u1112\u1161\u11bc "); + lineSelectionData.addElement("\u1112\u1161\u11ab\u110b\u1175\u11ab "); + lineSelectionData.addElement("\u110b\u1167\u11ab\u1112\u1161\u11b8 "); + lineSelectionData.addElement("\u110c\u1161\u11bc\u1105\u1169\u1100\u116d\u1112\u116c"); + + if (Locale.getDefault().getLanguage().equals("th")) { + logln("This test is skipped in th locale."); + return; + } + + generalIteratorTest(lineBreak, lineSelectionData); + } + + public void TestBug4117554Lines() { + Vector lineSelectionData = new Vector(); + + // Fullwidth .!? should be treated as postJwrd + lineSelectionData.addElement("\u4e01\uff0e"); + lineSelectionData.addElement("\u4e02\uff01"); + lineSelectionData.addElement("\u4e03\uff1f"); + + generalIteratorTest(lineBreak, lineSelectionData); + } + + public void TestBug4217703() { + if (Locale.getDefault().getLanguage().equals("th")) { + logln("This test is skipped in th locale."); + return; + } + + Vector lineSelectionData = new Vector(); + + // There shouldn't be a line break between sentence-ending punctuation + // and a closing quote + lineSelectionData.addElement("He "); + lineSelectionData.addElement("said "); + lineSelectionData.addElement("\"Go!\" "); + lineSelectionData.addElement("I "); + lineSelectionData.addElement("went. "); + + lineSelectionData.addElement("Hashtable$Enumeration "); + lineSelectionData.addElement("getText()."); + lineSelectionData.addElement("getIndex()"); + + generalIteratorTest(lineBreak, lineSelectionData); + } + + private static final String graveS = "S\u0300"; + private static final String acuteBelowI = "i\u0317"; + private static final String acuteE = "e\u0301"; + private static final String circumflexA = "a\u0302"; + private static final String tildeE = "e\u0303"; + + public void TestCharacterBreak() { + Vector characterSelectionData = new Vector(); + + characterSelectionData.addElement(graveS); + characterSelectionData.addElement(acuteBelowI); + characterSelectionData.addElement("m"); + characterSelectionData.addElement("p"); + characterSelectionData.addElement("l"); + characterSelectionData.addElement(acuteE); + characterSelectionData.addElement(" "); + characterSelectionData.addElement("s"); + characterSelectionData.addElement(circumflexA); + characterSelectionData.addElement("m"); + characterSelectionData.addElement("p"); + characterSelectionData.addElement("l"); + characterSelectionData.addElement(tildeE); + characterSelectionData.addElement("."); + characterSelectionData.addElement("w"); + characterSelectionData.addElement(circumflexA); + characterSelectionData.addElement("w"); + characterSelectionData.addElement("a"); + characterSelectionData.addElement("f"); + characterSelectionData.addElement("q"); + characterSelectionData.addElement("\n"); + characterSelectionData.addElement("\r"); + characterSelectionData.addElement("\r\n"); + characterSelectionData.addElement("\n"); + + generalIteratorTest(characterBreak, characterSelectionData); + } + + public void TestBug4098467Characters() { + Vector characterSelectionData = new Vector(); + + // What follows is a string of Korean characters (I found it in the Yellow Pages + // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed + // it correctly), first as precomposed syllables, and then as conjoining jamo. + // Both sequences should be semantically identical and break the same way. + // precomposed syllables... + characterSelectionData.addElement("\uc0c1"); + characterSelectionData.addElement("\ud56d"); + characterSelectionData.addElement(" "); + characterSelectionData.addElement("\ud55c"); + characterSelectionData.addElement("\uc778"); + characterSelectionData.addElement(" "); + characterSelectionData.addElement("\uc5f0"); + characterSelectionData.addElement("\ud569"); + characterSelectionData.addElement(" "); + characterSelectionData.addElement("\uc7a5"); + characterSelectionData.addElement("\ub85c"); + characterSelectionData.addElement("\uad50"); + characterSelectionData.addElement("\ud68c"); + characterSelectionData.addElement(" "); + // conjoining jamo... + characterSelectionData.addElement("\u1109\u1161\u11bc"); + characterSelectionData.addElement("\u1112\u1161\u11bc"); + characterSelectionData.addElement(" "); + characterSelectionData.addElement("\u1112\u1161\u11ab"); + characterSelectionData.addElement("\u110b\u1175\u11ab"); + characterSelectionData.addElement(" "); + characterSelectionData.addElement("\u110b\u1167\u11ab"); + characterSelectionData.addElement("\u1112\u1161\u11b8"); + characterSelectionData.addElement(" "); + characterSelectionData.addElement("\u110c\u1161\u11bc"); + characterSelectionData.addElement("\u1105\u1169"); + characterSelectionData.addElement("\u1100\u116d"); + characterSelectionData.addElement("\u1112\u116c"); + + generalIteratorTest(characterBreak, characterSelectionData); + } + + public void TestBug4153072() { + BreakIterator iter = BreakIterator.getWordInstance(); + String str = "...Hello, World!..."; + int begin = 3; + int end = str.length() - 3; + boolean gotException = false; + boolean dummy; + + iter.setText(new StringCharacterIterator(str, begin, end, begin)); + for (int index = -1; index < begin + 1; ++index) { + try { + dummy = iter.isBoundary(index); + if (index < begin) + errln("Didn't get exception with offset = " + index + + " and begin index = " + begin); + } + catch (IllegalArgumentException e) { + if (index >= begin) + errln("Got exception with offset = " + index + + " and begin index = " + begin); + } + } + } + + public void TestBug4146175Sentences() { + Vector sentenceSelectionData = new Vector(); + + // break between periods and opening punctuation even when there's no + // intervening space + sentenceSelectionData.addElement("end."); + sentenceSelectionData.addElement("(This is\u2029"); + + // treat the fullwidth period as an unambiguous sentence terminator + sentenceSelectionData.addElement("\u7d42\u308f\u308a\uff0e"); + sentenceSelectionData.addElement("\u300c\u3053\u308c\u306f"); + + generalIteratorTest(sentenceBreak, sentenceSelectionData); + } + + public void TestBug4146175Lines() { + if (Locale.getDefault().getLanguage().equals("th")) { + logln("This test is skipped in th locale."); + return; + } + + Vector lineSelectionData = new Vector(); + + // the fullwidth comma should stick to the preceding Japanese character + lineSelectionData.addElement("\u7d42\uff0c"); + lineSelectionData.addElement("\u308f"); + + generalIteratorTest(lineBreak, lineSelectionData); + } + + public void TestBug4214367() { + if (Locale.getDefault().getLanguage().equals("th")) { + logln("This test is skipped in th locale."); + return; + } + + Vector wordSelectionData = new Vector(); + + // the hiragana and katakana iteration marks and the long vowel mark + // are not being treated correctly by the word-break iterator + wordSelectionData.addElement("\u3042\u3044\u309d\u3042\u309e\u3042\u30fc\u3042"); + wordSelectionData.addElement("\u30a2\u30a4\u30fd\u30a2\u30fe\u30a2\u30fc\u30a2"); + + generalIteratorTest(wordBreak, wordSelectionData); + } + + private static final String cannedTestChars // characters fo the class Cc are ignorable for breaking + = /*"\u0000\u0001\u0002\u0003\u0004*/" !\"#$%&()+-01234<=>ABCDE[]^_`abcde{}|\u00a0\u00a2" + + "\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00ab\u00ad\u00ae\u00af\u00b0\u00b2\u00b3" + + "\u00b4\u00b9\u00bb\u00bc\u00bd\u02b0\u02b1\u02b2\u02b3\u02b4\u0300\u0301\u0302\u0303" + + "\u0304\u05d0\u05d1\u05d2\u05d3\u05d4\u0903\u093e\u093f\u0940\u0949\u0f3a\u0f3b\u2000" + + "\u2001\u2002\u200c\u200d\u200e\u200f\u2010\u2011\u2012\u2028\u2029\u202a\u203e\u203f" + + "\u2040\u20dd\u20de\u20df\u20e0\u2160\u2161\u2162\u2163\u2164"; + + public void TestSentenceInvariants() + { + BreakIterator e = BreakIterator.getSentenceInstance(); + doOtherInvariantTest(e, cannedTestChars + ".,\u3001\u3002\u3041\u3042\u3043\ufeff"); + } + + public void TestWordInvariants() + { + if (Locale.getDefault().getLanguage().equals("th")) { + logln("This test is skipped in th locale."); + return; + } + + BreakIterator e = BreakIterator.getWordInstance(); + doBreakInvariantTest(e, cannedTestChars + "\',.\u3041\u3042\u3043\u309b\u309c\u30a1\u30a2" + + "\u30a3\u4e00\u4e01\u4e02"); + doOtherInvariantTest(e, cannedTestChars + "\',.\u3041\u3042\u3043\u309b\u309c\u30a1\u30a2" + + "\u30a3\u4e00\u4e01\u4e02"); + } + + public void TestLineInvariants() + { + if (Locale.getDefault().getLanguage().equals("th")) { + logln("This test is skipped in th locale."); + return; + } + + BreakIterator e = BreakIterator.getLineInstance(); + String testChars = cannedTestChars + ".,;:\u3001\u3002\u3041\u3042\u3043\u3044\u3045" + + "\u30a3\u4e00\u4e01\u4e02"; + doBreakInvariantTest(e, testChars); + doOtherInvariantTest(e, testChars); + + int errorCount = 0; + + // in addition to the other invariants, a line-break iterator should make sure that: + // it doesn't break around the non-breaking characters + String noBreak = "\u00a0\u2007\u2011\ufeff"; + StringBuffer work = new StringBuffer("aaa"); + for (int i = 0; i < testChars.length(); i++) { + char c = testChars.charAt(i); + if (c == '\r' || c == '\n' || c == '\u2029' || c == '\u2028' || c == '\u0003') + continue; + work.setCharAt(0, c); + for (int j = 0; j < noBreak.length(); j++) { + work.setCharAt(1, noBreak.charAt(j)); + for (int k = 0; k < testChars.length(); k++) { + work.setCharAt(2, testChars.charAt(k)); + // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored + // for breaking purposes as per UTR14 + int type1 = Character.getType(work.charAt(1)); + int type2 = Character.getType(work.charAt(2)); + if (type1 == Character.CONTROL || type1 == Character.FORMAT || + type2 == Character.CONTROL || type2 == Character.FORMAT) { + continue; + } + e.setText(work.toString()); + for (int l = e.first(); l != BreakIterator.DONE; l = e.next()) { + if (l == 1 || l == 2) { + //errln("Got break between U+" + Integer.toHexString((int) + // (work.charAt(l - 1))) + " and U+" + Integer.toHexString( + // (int)(work.charAt(l))) + "\ntype1 = " + type1 + "\ntype2 = " + type2); + // as per UTR14 spaces followed by a GLUE character should allow + // line breaking + if (work.charAt(l-1) == '\u0020' && (work.charAt(l) == '\u00a0' || + work.charAt(l) == '\u0f0c' || + work.charAt(l) == '\u2007' || + work.charAt(l) == '\u2011' || + work.charAt(l) == '\u202f' || + work.charAt(l) == '\ufeff')) { + continue; + } + errln("Got break between U+" + Integer.toHexString((int) + (work.charAt(l - 1))) + " and U+" + Integer.toHexString( + (int)(work.charAt(l)))); + errorCount++; + if (errorCount >= 75) + return; + } + } + } + } + } + + // The following test has so many exceptions that it would be better to write a new set of data + // that tested exactly what should be tested + // Until that point it will be commented out + /* + + // it does break after dashes (unless they're followed by a digit, a non-spacing mark, + // a currency symbol, a space, a format-control character, a regular control character, + // a line or paragraph separator, or another dash) + String dashes = "-\u00ad\u2010\u2012\u2013\u2014"; + for (int i = 0; i < testChars.length(); i++) { + work.setCharAt(0, testChars.charAt(i)); + for (int j = 0; j < dashes.length(); j++) { + work.setCharAt(1, dashes.charAt(j)); + for (int k = 0; k < testChars.length(); k++) { + char c = testChars.charAt(k); + if (Character.getType(c) == Character.DECIMAL_DIGIT_NUMBER || + Character.getType(c) == Character.OTHER_NUMBER || + Character.getType(c) == Character.NON_SPACING_MARK || + Character.getType(c) == Character.ENCLOSING_MARK || + Character.getType(c) == Character.CURRENCY_SYMBOL || + Character.getType(c) == Character.DASH_PUNCTUATION || + Character.getType(c) == Character.SPACE_SEPARATOR || + Character.getType(c) == Character.FORMAT || + Character.getType(c) == Character.CONTROL || + Character.getType(c) == Character.END_PUNCTUATION || + Character.getType(c) == Character.FINAL_QUOTE_PUNCTUATION || + Character.getType(c) == Character.OTHER_PUNCTUATION || + c == '\'' || c == '\"' || + // category EX as per UTR14 + c == '!' || c == '?' || c == '\ufe56' || c == '\ufe57' || c == '\uff01' || c == '\uff1f' || + c == '\n' || c == '\r' || c == '\u2028' || c == '\u2029' || + c == '\u0003' || c == '\u2007' || c == '\u2011' || + c == '\ufeff') + continue; + work.setCharAt(2, c); + e.setText(work.toString()); + boolean saw2 = false; + for (int l = e.first(); l != BreakIterator.DONE; l = e.next()) + if (l == 2) + saw2 = true; + if (!saw2) { + errln("Didn't get break between U+" + Integer.toHexString((int) + (work.charAt(1))) + " and U+" + Integer.toHexString( + (int)(work.charAt(2)))); + errorCount++; + if (errorCount >= 75) + return; + } + } + } + } + */ + } + + public void TestCharacterInvariants() + { + BreakIterator e = BreakIterator.getCharacterInstance(); + doBreakInvariantTest(e, cannedTestChars + "\u1100\u1101\u1102\u1160\u1161\u1162\u11a8" + + "\u11a9\u11aa"); + doOtherInvariantTest(e, cannedTestChars + "\u1100\u1101\u1102\u1160\u1161\u1162\u11a8" + + "\u11a9\u11aa"); + } + + public void TestEmptyString() + { + String text = ""; + Vector x = new Vector(); + x.addElement(text); + + generalIteratorTest(lineBreak, x); + } + + public void TestGetAvailableLocales() + { + Locale[] locList = BreakIterator.getAvailableLocales(); + + if (locList.length == 0) + errln("getAvailableLocales() returned an empty list!"); + // I have no idea how to test this function... + } + + + /** + * Bug 4095322 + */ + public void TestJapaneseLineBreak() + { + StringBuffer testString = new StringBuffer("\u4e00x\u4e8c"); + // Breaking on $ is inconsistent + + /* Characters in precedingChars and followingChars have been updated + * from Unicode 2.0.14-based to 3.0.0-based when 4638433 was fixed. + * In concrete terms, + * 0x301F : Its category was changed from Ps to Pe since Unicode 2.1. + * 0x169B & 0x169C : added since Unicode 3.0.0. + */ + String precedingChars = + /* Puctuation, Open */ + "([{\u201a\u201e\u2045\u207d\u208d\u2329\u3008\u300a\u300c\u300e\u3010\u3014\u3016\u3018\u301a\u301d\ufe35\ufe37\ufe39\ufe3b\ufe3d\ufe3f\ufe41\ufe43\ufe59\ufe5b\ufe5d\uff08\uff3b\uff5b\uff62\u169b" + /* Punctuation, Initial quote */ + + "\u00ab\u2018\u201b\u201c\u201f\u2039" + /* Symbol, Currency */ + + "\u00a5\u00a3\u00a4\u20a0"; + + String followingChars = + /* Puctuation, Close */ + ")]}\u2046\u207e\u208e\u232a\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\u301e\u301f\ufd3e\ufe36\ufe38\ufe3a\ufe3c\ufe3e\ufe40\ufe42\ufe44\ufe5a\ufe5c\ufe5e\uff09\uff3d\uff5d\uff63\u169c" + /* Punctuation, Final quote */ + + "\u00bb\u2019\u201d\u203a" + /* Punctuation, Other */ + + "!%,.:;\u3001\u3002\u2030\u2031\u2032\u2033\u2034" + /* Punctuation, Dash */ + + "\u2103\u2109" + /* Symbol, Currency */ + + "\u00a2" + /* Letter, Modifier */ + + "\u3005\u309d\u309e" + /* Letter, Other */ + + "\u3063\u3083\u3085\u3087\u30c3\u30e3\u30e5\u30e7\u30fc\u30fd\u30fe" + /* Mark, Non-Spacing */ + + "\u0300\u0301\u0302" + /* Symbol, Modifier */ + + "\u309b\u309c" + /* Symbol, Other */ + + "\u00b0"; + + BreakIterator iter = BreakIterator.getLineInstance(Locale.JAPAN); + + for (int i = 0; i < precedingChars.length(); i++) { + testString.setCharAt(1, precedingChars.charAt(i)); + iter.setText(testString.toString()); + int j = iter.first(); + if (j != 0) { + errln("ja line break failure: failed to start at 0 and bounced at " + j); + } + j = iter.next(); + if (j != 1) { + errln("ja line break failure: failed to stop before '" + + precedingChars.charAt(i) + "' (\\u" + + Integer.toString(precedingChars.charAt(i), 16) + + ") at 1 and bounded at " + j); + } + j = iter.next(); + if (j != 3) { + errln("ja line break failure: failed to skip position after '" + + precedingChars.charAt(i) + "' (\\u" + + Integer.toString(precedingChars.charAt(i), 16) + + ") at 3 and bounded at " + j); + } + } + + for (int i = 0; i < followingChars.length(); i++) { + testString.setCharAt(1, followingChars.charAt(i)); + iter.setText(testString.toString()); + int j = iter.first(); + if (j != 0) { + errln("ja line break failure: failed to start at 0 and bounded at " + j); + } + j = iter.next(); + if (j != 2) { + errln("ja line break failure: failed to skip position before '" + + followingChars.charAt(i) + "' (\\u" + + Integer.toString(followingChars.charAt(i), 16) + + ") at 2 and bounded at " + j); + } + j = iter.next(); + if (j != 3) { + errln("ja line break failure: failed to stop after '" + + followingChars.charAt(i) + "' (\\u" + + Integer.toString(followingChars.charAt(i), 16) + + ") at 3 and bounded at " + j); + } + } + } + + /** + * Bug 4638433 + */ + public void TestLineBreakBasedOnUnicode3_0_0() + { + BreakIterator iter; + int i; + + /* Latin Extend-B characters + * 0x0218-0x0233 which have been added since Unicode 3.0.0. + */ + iter = BreakIterator.getWordInstance(Locale.US); + iter.setText("\u0216\u0217\u0218\u0219\u021A"); + i = iter.first(); + i = iter.next(); + if (i != 5) { + errln("Word break failure: failed to stop at 5 and bounded at " + i); + } + + + iter = BreakIterator.getLineInstance(Locale.US); + + /* + * \u301f has changed its category from Ps to Pe since Unicode 2.1. + */ + iter.setText("32\u301f1"); + i = iter.first(); + i = iter.next(); + if (i != 3) { + errln("Line break failure: failed to skip before \\u301F(Pe) at 3 and bounded at " + i); + } + + /* Mongolian + * which have been added since Unicode 3.0.0. + */ + iter.setText("\u1820\u1806\u1821"); + i = iter.first(); + i = iter.next(); + if (i != 2) { + errln("Mongolian line break failure: failed to skip position before \\u1806(Pd) at 2 and bounded at " + i); + } + + /* Khmer which have + * been added since Unicode 3.0.0. + */ + iter.setText("\u17E0\u17DB\u17E1"); + i = iter.first(); + i = iter.next(); + if (i != 1) { + errln("Khmer line break failure: failed to stop before \\u17DB(Sc) at 1 and bounded at " + i); + } + i = iter.next(); + if (i != 3) { + errln("Khmer line break failure: failed to skip position after \\u17DB(Sc) at 3 and bounded at " + i); + } + + /* Ogham which have + * been added since Unicode 3.0.0. + */ + iter.setText("\u1692\u1680\u1696"); + i = iter.first(); + i = iter.next(); + if (i != 2) { + errln("Ogham line break failure: failed to skip postion before \\u1680(Zs) at 2 and bounded at " + i); + } + + + // Confirm changes in BreakIteratorRules_th.java have been reflected. + iter = BreakIterator.getLineInstance(new Locale("th", "")); + + /* Thai + * + * + * + * + */ + iter.setText("\u0E57\u201C\u0E55\u201D\u0E53"); + i = iter.first(); + i = iter.next(); + if (i != 1) { + errln("Thai line break failure: failed to stop before \\u201C(Pi) at 1 and bounded at " + i); + } + i = iter.next(); + if (i != 4) { + errln("Thai line break failure: failed to stop after \\u201D(Pf) at 4 and bounded at " + i); + } + } + + /** + * Bug 4068137 + */ + public void TestEndBehavior() + { + String testString = "boo."; + BreakIterator wb = BreakIterator.getWordInstance(); + wb.setText(testString); + + if (wb.first() != 0) + errln("Didn't get break at beginning of string."); + if (wb.next() != 3) + errln("Didn't get break before period in \"boo.\""); + if (wb.current() != 4 && wb.next() != 4) + errln("Didn't get break at end of string."); + } + + // [serialization test has been removed pursuant to bug #4152965] + + /** + * Bug 4450804 + */ + public void TestLineBreakContractions() { + Vector expected = new Vector(); + + expected.add("These "); + expected.add("are "); + expected.add("'foobles'. "); + expected.add("Don't "); + expected.add("you "); + expected.add("like "); + expected.add("them?"); + generalIteratorTest(lineBreak, expected); + } + +} diff --git a/jdk/test/java/text/BreakIterator/Bug4533872.java b/jdk/test/java/text/BreakIterator/Bug4533872.java new file mode 100644 index 00000000000..64a4ccf569e --- /dev/null +++ b/jdk/test/java/text/BreakIterator/Bug4533872.java @@ -0,0 +1,261 @@ +/* + * 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. + */ + +/** + * @test + * @bug 4533872 4640853 + * @library /java/text/testlib + * @summary Unit tests for supplementary character support (JSR-204) and Unicode 4.0 support + */ + +import java.text.BreakIterator; +import java.util.Locale; + +public class Bug4533872 extends IntlTest { + + public static void main(String[] args) throws Exception { + new Bug4533872().run(args); + } + + static final String[] given = { + /* Lu Nd Lu Ll */ + "XYZ12345 ABCDE abcde", + /* Nd Lo Nd Lu Po Lu Ll */ + "123\uD800\uDC00345 ABC\uFF61XYZ abc", + /* Nd Lo Nd Lu Po Lu Ll */ + "123\uD800\uDC00345 ABC\uD800\uDD00XYZ abc", + /* Lu Ll Cs Ll Cs Lu Lo Lu */ + "ABCabc\uDC00xyz\uD800ABC\uD800\uDC00XYZ", + }; + + // Golden data for TestNext(), TestBoundar() and TestPrintEach*ward() + static final String[][] expected = { + {"XYZ12345", " ", "ABCDE", " ", "abcde"}, + {"123\uD800\uDC00345", " ", "ABC", "\uFF61", "XYZ", " ", "abc"}, + {"123\uD800\uDC00345", " ", "ABC", "\uD800\uDD00", "XYZ", " ", "abc"}, + {"ABCabc", "\uDC00", "xyz", "\uD800", "ABC\uD800\uDC00XYZ"}, + }; + + BreakIterator iter; + int start, end, current; + + /* + * Test for next(int n) + */ + void TestNext() { + iter = BreakIterator.getWordInstance(Locale.US); + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + start = iter.first(); + int j = expected[i].length - 1; + start = iter.next(j); + end = iter.next(); + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printEachForward() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + } + + /* + * Test for isBoundary(int n) + */ + void TestIsBoundary() { + iter = BreakIterator.getWordInstance(Locale.US); + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + + start = iter.first(); + end = iter.next(); + + while (end < given[i].length()) { + if (!iter.isBoundary(end)) { + errln("Word break failure: isBoundary() This should be a boundary. Index=" + + end + " for " + given[i]); + } + end = iter.next(); + } + } + } + + + /* + * The followig test cases were made based on examples in BreakIterator's + * API Doc. + */ + + /* + * Test mainly for next() and current() + */ + void TestPrintEachForward() { + iter = BreakIterator.getWordInstance(Locale.US); + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + start = iter.first(); + + // Check current()'s return value - should be same as first()'s. + current = iter.current(); + if (start != current) { + errln("Word break failure: printEachForward() Unexpected current value: current()=" + + current + ", expected(=first())=" + start); + } + + int j = 0; + for (end = iter.next(); + end != BreakIterator.DONE; + start = end, end = iter.next(), j++) { + + // Check current()'s return value - should be same as next()'s. + current = iter.current(); + if (end != current) { + errln("Word break failure: printEachForward() Unexpected current value: current()=" + + current + ", expected(=next())=" + end); + } + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printEachForward() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + } + } + + /* + * Test mainly for previous() and current() + */ + void TestPrintEachBackward() { + iter = BreakIterator.getWordInstance(Locale.US); + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + end = iter.last(); + + // Check current()'s return value - should be same as last()'s. + current = iter.current(); + if (end != current) { + errln("Word break failure: printEachBackward() Unexpected current value: current()=" + + current + ", expected(=last())=" + end); + } + + int j; + for (start = iter.previous(), j = expected[i].length-1; + start != BreakIterator.DONE; + end = start, start = iter.previous(), j--) { + + // Check current()'s return value - should be same as previous()'s. + current = iter.current(); + if (start != current) { + errln("Word break failure: printEachBackward() Unexpected current value: current()=" + + current + ", expected(=previous())=" + start); + } + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printEachBackward() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + } + } + + /* + * Test mainly for following() and previous() + */ + void TestPrintAt_1() { + iter = BreakIterator.getWordInstance(Locale.US); + + int[][] index = { + {2, 8, 10, 15, 17}, + {1, 8, 10, 12, 15, 17, 20}, + {3, 8, 10, 13, 16, 18, 20}, + {4, 6, 9, 10, 16}, + }; + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + for (int j = index[i].length-1; j >= 0; j--) { + end = iter.following(index[i][j]); + start = iter.previous(); + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printAt_1() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + } + } + + /* + * Test mainly for preceding() and next() + */ + void TestPrintAt_2() { + iter = BreakIterator.getWordInstance(Locale.US); + + int[][] index = { + {2, 9, 10, 15, 17}, + {1, 9, 10, 13, 16, 18, 20}, + {4, 9, 10, 13, 16, 18, 20}, + {6, 7, 10, 11, 15}, + }; + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + + // Check preceding(0)'s return value - should equals BreakIterator.DONE. + if (iter.preceding(0) != BreakIterator.DONE) { + errln("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" + + iter.preceding(0)); + } + + for (int j = 0; j < index[i].length; j++) { + start = iter.preceding(index[i][j]); + end = iter.next(); + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printAt_2() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + + // Check next()'s return value - should equals BreakIterator.DONE. + end = iter.last(); + start = iter.next(); + if (start != BreakIterator.DONE) { + errln("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" + start); + } + } + } +} diff --git a/jdk/test/java/text/BreakIterator/Bug4740757.java b/jdk/test/java/text/BreakIterator/Bug4740757.java new file mode 100644 index 00000000000..b60e70d0e8b --- /dev/null +++ b/jdk/test/java/text/BreakIterator/Bug4740757.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4740757 + * @summary Confirm line-breaking behavior of Hangul + */ + +import java.text.*; +import java.util.*; + +public class Bug4740757 { + + private static boolean err = false; + + public static void main(String[] args) { + Locale defaultLocale = Locale.getDefault(); + if (defaultLocale.getLanguage().equals("th")) { + Locale.setDefault(Locale.KOREA); + test4740757(); + Locale.setDefault(defaultLocale); + } else { + test4740757(); + } + + if (err) { + throw new RuntimeException("Incorrect Line-breaking"); + } + } + + private static void test4740757() { + String source = "\uc548\ub155\ud558\uc138\uc694? \uc88b\uc740 \uc544\uce68, \uc5ec\ubcf4\uc138\uc694! \uc548\ub155. End."; + String expected = "\uc548/\ub155/\ud558/\uc138/\uc694? /\uc88b/\uc740 /\uc544/\uce68, /\uc5ec/\ubcf4/\uc138/\uc694! /\uc548/\ub155. /End./"; + + BreakIterator bi = BreakIterator.getLineInstance(Locale.KOREAN); + bi.setText(source); + int start = bi.first(); + int end = bi.next(); + StringBuilder sb = new StringBuilder(); + + for (; end != BreakIterator.DONE; start = end, end = bi.next()) { + sb.append(source.substring(start,end)); + sb.append('/'); + } + + if (!expected.equals(sb.toString())) { + System.err.println("Failed: Hangul line-breaking failed." + + "\n\tExpected: " + expected + + "\n\tGot: " + sb + + "\nin " + Locale.getDefault() + " locale."); + err = true; + } + } + +} diff --git a/jdk/test/java/text/BreakIterator/Bug4912404.java b/jdk/test/java/text/BreakIterator/Bug4912404.java new file mode 100644 index 00000000000..07a2d0cb3c7 --- /dev/null +++ b/jdk/test/java/text/BreakIterator/Bug4912404.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/** + * @test + * @bug 4912404 + * @summary Confirm that BreakIterator.equals(null) return false. + */ + +import java.text.BreakIterator; + +public class Bug4912404 { + + public static void main(String[] args) { + BreakIterator b = BreakIterator.getWordInstance(); + b.setText("abc"); + if (b.equals(null)) { + throw new RuntimeException("BreakIterator.equals(null) should return false."); + } + } +} diff --git a/jdk/test/java/text/BreakIterator/Bug4932583.java b/jdk/test/java/text/BreakIterator/Bug4932583.java new file mode 100644 index 00000000000..a9d62d44396 --- /dev/null +++ b/jdk/test/java/text/BreakIterator/Bug4932583.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/* + * @test + * @run main/timeout=60 Bug4932583 + * @bug 4932583 + * @summary Confirm that BreakIterator doesn't get caught in an infinite loop. + */ + +import java.text.*; +import java.util.*; +import java.io.*; + +public class Bug4932583 { + public static void main(String[] args) { + BreakIterator iterator = BreakIterator.getCharacterInstance(); + iterator.setText("\uDB40\uDFFF"); + int boundary = iterator.next(); + } +} diff --git a/jdk/test/java/text/BreakIterator/Bug6513074.java b/jdk/test/java/text/BreakIterator/Bug6513074.java new file mode 100644 index 00000000000..736cde17685 --- /dev/null +++ b/jdk/test/java/text/BreakIterator/Bug6513074.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6513074 + * @summary Confirm that JIS X 0213 characters are processed in line-breaking properly. + */ + +import java.text.*; +import java.util.*; + +public class Bug6513074 { + + private static final String[][] source = { + {"\ufa30\ufa31 \ufa69\ufa6a", + "JIS X 0213 compatibility additions (\\uFA30-\\uFA6A)"}, + }; + + private static final String[] expected_line = { + "\ufa30/\ufa31 /\ufa69/\ufa6a/", + }; + + private static final String[] expected_word = { + "\ufa30\ufa31/ /\ufa69\ufa6a/", + }; + + private static final String[] expected_char = { + "\ufa30/\ufa31/ /\ufa69/\ufa6a/", + }; + + + private static boolean err = false; + + public static void main(String[] args) { + Locale defaultLocale = Locale.getDefault(); + if (defaultLocale.getLanguage().equals("th")) { + Locale.setDefault(Locale.JAPAN); + test6513074(); + Locale.setDefault(defaultLocale); + } else { + test6513074(); + } + + if (err) { + throw new RuntimeException("Failed: Incorrect Text-breaking."); + } + } + + + private static void test6513074() { + BreakIterator bi = BreakIterator.getLineInstance(Locale.JAPAN); + for (int i = 0; i < source.length; i++) { + testBreakIterator(bi, "Line", source[i][0], expected_line[i], source[i][1]); + } + + bi = BreakIterator.getWordInstance(Locale.JAPAN); + for (int i = 0; i < source.length; i++) { + testBreakIterator(bi, "Word", source[i][0], expected_word[i], source[i][1]); + } + + bi = BreakIterator.getCharacterInstance(Locale.JAPAN); + for (int i = 0; i < source.length; i++) { + testBreakIterator(bi, "Character", source[i][0], expected_char[i], source[i][1]); + } + } + + private static void testBreakIterator(BreakIterator bi, + String type, + String source, + String expected, + String description) { + bi.setText(source); + int start = bi.first(); + int end = bi.next(); + StringBuilder sb = new StringBuilder(); + + for (; end != BreakIterator.DONE; start = end, end = bi.next()) { + sb.append(source.substring(start,end)); + sb.append('/'); + } + + if (!expected.equals(sb.toString())) { + System.err.println("Failed: Incorrect " + type + "-breaking for " + + description + + "\n\tExpected: " + toString(expected) + + "\n\tGot: " + toString(sb.toString())); + err = true; + } + } + + private static String toString(String s) { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < s.length(); i++) { + sb.append(" 0x" + Integer.toHexString(s.charAt(i))); + } + + return sb.toString(); + } + +} diff --git a/jdk/test/java/text/BreakIterator/NewVSOld_th_TH.java b/jdk/test/java/text/BreakIterator/NewVSOld_th_TH.java new file mode 100644 index 00000000000..467cbc574c3 --- /dev/null +++ b/jdk/test/java/text/BreakIterator/NewVSOld_th_TH.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +/* + @test + @summary test Comparison of New Collators against Old Collators in the en_US locale +*/ + +import java.io.*; +import java.util.Enumeration; +import java.util.Vector; +import java.util.Locale; +import java.text.BreakIterator; +import java.lang.Math; + +public class NewVSOld_th_TH { + public static void main(String args[]) throws FileNotFoundException, + UnsupportedEncodingException, + IOException { + final String ENCODING = "UTF-8"; + final Locale THAI_LOCALE = new Locale("th", "TH"); + + String rawFileName = "test_th_TH.txt"; + String oldFileName = "broken_th_TH.txt"; + StringBuilder rawText = new StringBuilder(); + StringBuilder oldText = new StringBuilder(); + StringBuilder cookedText = new StringBuilder(); + + File f; + f = new File(System.getProperty("test.src", "."), rawFileName); + + try (InputStreamReader rawReader = + new InputStreamReader(new FileInputStream(f), ENCODING)) { + int c; + while ((c = rawReader.read()) != -1) { + rawText.append((char) c); + } + } + + f = new File(System.getProperty("test.src", "."), oldFileName); + try (InputStreamReader oldReader = + new InputStreamReader(new FileInputStream(f), ENCODING)) { + int c; + while ((c = oldReader.read()) != -1) { + oldText.append((char) c); + } + } + + BreakIterator breakIterator = BreakIterator.getWordInstance(THAI_LOCALE); + breakIterator.setText(rawText.toString()); + + int start = breakIterator.first(); + for (int end = breakIterator.next(); + end != BreakIterator.DONE; + start = end, end = breakIterator.next()) { + cookedText.append(rawText.substring(start, end)); + cookedText.append("\n"); + } + + String cooked = cookedText.toString(); + String old = oldText.toString(); + if (cooked.compareTo(old) != 0) { + throw new RuntimeException("Text not broken the same as with the old BreakIterators"); + } + } +} diff --git a/jdk/test/java/text/BreakIterator/broken_th_TH.txt b/jdk/test/java/text/BreakIterator/broken_th_TH.txt new file mode 100644 index 00000000000..ca172c33339 --- /dev/null +++ b/jdk/test/java/text/BreakIterator/broken_th_TH.txt @@ -0,0 +1,13 @@ +การ +เก็บ +ภาษีประเทศ +ไทยและ +ประเทศ +เดนมาร์ค +อนุสัญญา +ระหว่าง +รัฐบาล +แห่ง +ประเทศ +ไทย +กับ diff --git a/jdk/test/java/text/BreakIterator/test_th_TH.txt b/jdk/test/java/text/BreakIterator/test_th_TH.txt new file mode 100644 index 00000000000..c423da033e7 --- /dev/null +++ b/jdk/test/java/text/BreakIterator/test_th_TH.txt @@ -0,0 +1 @@ +การเก็บภาษีประเทศไทยและประเทศเดนมาร์คอนุสัญญาระหว่างรัฐบาลแห่งประเทศไทยกับ \ No newline at end of file diff --git a/jdk/test/java/text/CharacterIterator/CharacterIteratorTest.java b/jdk/test/java/text/CharacterIterator/CharacterIteratorTest.java new file mode 100644 index 00000000000..9d2d94b4d01 --- /dev/null +++ b/jdk/test/java/text/CharacterIterator/CharacterIteratorTest.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test for Character Iterator + */ + +/* + * + * + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved + * + * Portions copyright (c) 2007 Sun Microsystems, Inc. + * All Rights Reserved. + * + * The original version of this source code and documentation + * is copyrighted and owned by Taligent, Inc., a wholly-owned + * subsidiary of IBM. These materials are provided under terms + * of a License Agreement between Taligent and Sun. This technology + * is protected by multiple US and International patents. + * + * This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + */ + +import java.text.*; + +public class CharacterIteratorTest extends IntlTest { + public static void main(String[] args) throws Exception { + new CharacterIteratorTest().run(args); + } + + public CharacterIteratorTest() { + } + + public void TestConstructionAndEquality() { + String testText = "Now is the time for all good men to come to the aid of their country."; + String testText2 = "Don't bother using this string."; + + CharacterIterator test1 = new StringCharacterIterator(testText); + CharacterIterator test2 = new StringCharacterIterator(testText, 5); + CharacterIterator test3 = new StringCharacterIterator(testText, 2, 20, 5); + CharacterIterator test4 = new StringCharacterIterator(testText2); + CharacterIterator test5 = (CharacterIterator)test1.clone(); + + if (test1.equals(test2) || test1.equals(test3) || test1.equals(test4)) + errln("Construation or equals() failed: Two unequal iterators tested equal"); + + if (!test1.equals(test5)) + errln("clone() or equals() failed: Two clones tested unequal"); + + if (test1.hashCode() == test2.hashCode() || test1.hashCode() == test3.hashCode() + || test1.hashCode() == test4.hashCode()) + errln("hash() failed: different objects have same hash code"); + + if (test1.hashCode() != test5.hashCode()) + errln("hash() failed: identical objects have different hash codes"); + + test1.setIndex(5); + if (!test1.equals(test2) || test1.equals(test5)) + errln("setIndex() failed"); + } + + public void TestIteration() { + String text = "Now is the time for all good men to come to the aid of their country."; + + CharacterIterator iter = new StringCharacterIterator(text, 5); + + if (iter.current() != text.charAt(5)) + errln("Iterator didn't start out in the right place."); + + char c = iter.first(); + int i = 0; + + if (iter.getBeginIndex() != 0 || iter.getEndIndex() != text.length()) + errln("getBeginIndex() or getEndIndex() failed"); + + logln("Testing forward iteration..."); + do { + if (c == CharacterIterator.DONE && i != text.length()) + errln("Iterator reached end prematurely"); + else if (c != text.charAt(i)) + errln("Character mismatch at position " + i + ", iterator has " + c + + ", string has " + text.charAt(c)); + + if (iter.current() != c) + errln("current() isn't working right"); + if (iter.getIndex() != i) + errln("getIndex() isn't working right"); + + if (c != CharacterIterator.DONE) { + c = iter.next(); + i++; + } + } while (c != CharacterIterator.DONE); + + c = iter.last(); + i = text.length() - 1; + + logln("Testing backward iteration..."); + do { + if (c == CharacterIterator.DONE && i >= 0) + errln("Iterator reached end prematurely"); + else if (c != text.charAt(i)) + errln("Character mismatch at position " + i + ", iterator has " + c + + ", string has " + text.charAt(c)); + + if (iter.current() != c) + errln("current() isn't working right"); + if (iter.getIndex() != i) + errln("getIndex() isn't working right"); + + if (c != CharacterIterator.DONE) { + c = iter.previous(); + i--; + } + } while (c != CharacterIterator.DONE); + + iter = new StringCharacterIterator(text, 5, 15, 10); + if (iter.getBeginIndex() != 5 || iter.getEndIndex() != 15) + errln("creation of a restricted-range iterator failed"); + + if (iter.getIndex() != 10 || iter.current() != text.charAt(10)) + errln("starting the iterator in the middle didn't work"); + + c = iter.first(); + i = 5; + + logln("Testing forward iteration over a range..."); + do { + if (c == CharacterIterator.DONE && i != 15) + errln("Iterator reached end prematurely"); + else if (c != text.charAt(i)) + errln("Character mismatch at position " + i + ", iterator has " + c + + ", string has " + text.charAt(c)); + + if (iter.current() != c) + errln("current() isn't working right"); + if (iter.getIndex() != i) + errln("getIndex() isn't working right"); + + if (c != CharacterIterator.DONE) { + c = iter.next(); + i++; + } + } while (c != CharacterIterator.DONE); + + c = iter.last(); + i = 14; + + logln("Testing backward iteration over a range..."); + do { + if (c == CharacterIterator.DONE && i >= 5) + errln("Iterator reached end prematurely"); + else if (c != text.charAt(i)) + errln("Character mismatch at position " + i + ", iterator has " + c + + ", string has " + text.charAt(c)); + + if (iter.current() != c) + errln("current() isn't working right"); + if (iter.getIndex() != i) + errln("getIndex() isn't working right"); + + if (c != CharacterIterator.DONE) { + c = iter.previous(); + i--; + } + } while (c != CharacterIterator.DONE); + } + + /** + * @bug 4082050 4078261 4078255 + */ + public void TestPathologicalCases() { + String text = "This is only a test."; + +/* +This test is commented out until API-change approval for bug #4082050 goes through. + // test for bug #4082050 (don't get an error if begin == end, even though all + // operations on the iterator will cause exceptions) + // [I actually fixed this so that you CAN create an iterator with begin == end, + // but all operations on it return DONE.] + CharacterIterator iter = new StringCharacterIterator(text, 5, 5, 5); + if (iter.first() != CharacterIterator.DONE + || iter.next() != CharacterIterator.DONE + || iter.last() != CharacterIterator.DONE + || iter.previous() != CharacterIterator.DONE + || iter.current() != CharacterIterator.DONE + || iter.getIndex() != 5) + errln("Got something other than DONE when performing operations on an empty StringCharacterIterator"); +*/ +CharacterIterator iter = null; + + // if we try to construct a StringCharacterIterator with an endIndex that's off + // the end of the String under iterator, we're supposed to get an + // IllegalArgumentException + boolean gotException = false; + try { + iter = new StringCharacterIterator(text, 5, 100, 5); + } + catch (IllegalArgumentException e) { + gotException = true; + } + if (!gotException) + errln("StringCharacterIterator didn't throw an exception when given an invalid substring range."); + + // test for bug #4078255 (getting wrong value from next() when we're at the end + // of the string) + iter = new StringCharacterIterator(text); + int expectedIndex = iter.getEndIndex(); + int actualIndex; + + iter.last(); + actualIndex = iter.getIndex(); + if (actualIndex != expectedIndex - 1) + errln("last() failed: expected " + (expectedIndex - 1) + ", got " + actualIndex); + + iter.next(); + actualIndex = iter.getIndex(); + if (actualIndex != expectedIndex) + errln("next() after last() failed: expected " + expectedIndex + ", got " + actualIndex); + + iter.next(); + actualIndex = iter.getIndex(); + if (actualIndex != expectedIndex) + errln("second next() after last() failed: expected " + expectedIndex + ", got " + actualIndex); + } + + /* + * @bug 4123771 4051073 + * #4123771 is actually a duplicate of bug #4051073, which was fixed some time ago, but + * no one ever added a regression test for it. + */ + public void TestBug4123771() { + String text = "Some string for testing"; + StringCharacterIterator iter = new StringCharacterIterator(text); + int index = iter.getEndIndex(); + try { + char c = iter.setIndex(index); + } + catch (Exception e) { + System.out.println("method setIndex(int position) throws unexpected exception " + e); + System.out.println(" position: " + index); + System.out.println(" getEndIndex(): " + iter.getEndIndex()); + System.out.println(" text.length(): " + text.length()); + errln(""); // re-throw the exception through our test framework + } + } +} diff --git a/jdk/test/java/text/Collator/APITest.java b/jdk/test/java/text/Collator/APITest.java new file mode 100644 index 00000000000..f2b0a019a29 --- /dev/null +++ b/jdk/test/java/text/Collator/APITest.java @@ -0,0 +1,318 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test Collation API + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.text.CollationKey; +import java.text.CollationElementIterator; + +public class APITest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new APITest().run(args); + } + + final void doAssert(boolean condition, String message) + { + if (!condition) { + err("ERROR: "); + errln(message); + } + } + + public final void TestProperty( ) + { + Collator col = null; + try { + col = Collator.getInstance(Locale.ROOT); + logln("The property tests begin : "); + logln("Test ctors : "); + doAssert(col.compare("ab", "abc") < 0, "ab < abc comparison failed"); + doAssert(col.compare("ab", "AB") < 0, "ab < AB comparison failed"); + doAssert(col.compare("black-bird", "blackbird") > 0, "black-bird > blackbird comparison failed"); + doAssert(col.compare("black bird", "black-bird") < 0, "black bird < black-bird comparison failed"); + doAssert(col.compare("Hello", "hello") > 0, "Hello > hello comparison failed"); + + logln("Test ctors ends."); + logln("testing Collator.getStrength() method ..."); + doAssert(col.getStrength() == Collator.TERTIARY, "collation object has the wrong strength"); + doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference"); + + logln("testing Collator.setStrength() method ..."); + col.setStrength(Collator.SECONDARY); + doAssert(col.getStrength() != Collator.TERTIARY, "collation object's strength is secondary difference"); + doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference"); + doAssert(col.getStrength() == Collator.SECONDARY, "collation object has the wrong strength"); + + logln("testing Collator.setDecomposition() method ..."); + col.setDecomposition(Collator.NO_DECOMPOSITION); + doAssert(col.getDecomposition() != Collator.FULL_DECOMPOSITION, "collation object's strength is secondary difference"); + doAssert(col.getDecomposition() != Collator.CANONICAL_DECOMPOSITION, "collation object's strength is primary difference"); + doAssert(col.getDecomposition() == Collator.NO_DECOMPOSITION, "collation object has the wrong strength"); + } catch (Exception foo) { + errln("Error : " + foo.getMessage()); + errln("Default Collator creation failed."); + } + logln("Default collation property test ended."); + logln("Collator.getRules() testing ..."); + doAssert(((RuleBasedCollator)col).getRules().length() != 0, "getRules() result incorrect" ); + logln("getRules tests end."); + try { + col = Collator.getInstance(Locale.FRENCH); + col.setStrength(Collator.PRIMARY); + logln("testing Collator.getStrength() method again ..."); + doAssert(col.getStrength() != Collator.TERTIARY, "collation object has the wrong strength"); + doAssert(col.getStrength() == Collator.PRIMARY, "collation object's strength is not primary difference"); + + logln("testing French Collator.setStrength() method ..."); + col.setStrength(Collator.TERTIARY); + doAssert(col.getStrength() == Collator.TERTIARY, "collation object's strength is not tertiary difference"); + doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference"); + doAssert(col.getStrength() != Collator.SECONDARY, "collation object's strength is secondary difference"); + + } catch (Exception bar) { + errln("Error : " + bar.getMessage()); + errln("Creating French collation failed."); + } + + logln("Create junk collation: "); + Locale abcd = new Locale("ab", "CD", ""); + Collator junk = null; + try { + junk = Collator.getInstance(abcd); + } catch (Exception err) { + errln("Error : " + err.getMessage()); + errln("Junk collation creation failed, should at least return the collator for the base bundle."); + } + try { + col = Collator.getInstance(Locale.ROOT); + doAssert(col.equals(junk), "The base bundle's collation should be returned."); + } catch (Exception exc) { + errln("Error : " + exc.getMessage()); + errln("Default collation comparison, caching not working."); + } + + logln("Collator property test ended."); + } + + public final void TestHashCode( ) + { + logln("hashCode tests begin."); + Collator col1 = null; + try { + col1 = Collator.getInstance(Locale.ROOT); + } catch (Exception foo) { + errln("Error : " + foo.getMessage()); + errln("Default collation creation failed."); + } + Collator col2 = null; + Locale dk = new Locale("da", "DK", ""); + try { + col2 = Collator.getInstance(dk); + } catch (Exception bar) { + errln("Error : " + bar.getMessage()); + errln("Danish collation creation failed."); + return; + } + Collator col3 = null; + try { + col3 = Collator.getInstance(Locale.ROOT); + } catch (Exception err) { + errln("Error : " + err.getMessage()); + errln("2nd default collation creation failed."); + } + logln("Collator.hashCode() testing ..."); + + if (col1 != null) { + doAssert(col1.hashCode() != col2.hashCode(), "Hash test1 result incorrect"); + if (col3 != null) { + doAssert(col1.hashCode() == col3.hashCode(), "Hash result not equal"); + } + } + + logln("hashCode tests end."); + } + + //---------------------------------------------------------------------------- + // ctor -- Tests the constructor methods + // + public final void TestCollationKey( ) + { + logln("testing CollationKey begins..."); + Collator col = null; + try { + col = Collator.getInstance(Locale.ROOT); + } catch (Exception foo) { + errln("Error : " + foo.getMessage()); + errln("Default collation creation failed."); + } + if (col == null) { + return; + } + + String test1 = "Abcda", test2 = "abcda"; + logln("Use tertiary comparison level testing ...."); + CollationKey sortk1 = col.getCollationKey(test1); + CollationKey sortk2 = col.getCollationKey(test2); + doAssert(sortk1.compareTo(sortk2) > 0, + "Result should be \"Abcda\" >>> \"abcda\""); + CollationKey sortk3 = sortk2; + CollationKey sortkNew = sortk1; + doAssert(sortk1 != sortk2, "The sort keys should be different"); + doAssert(sortk1.hashCode() != sortk2.hashCode(), "sort key hashCode() failed"); + doAssert(sortk2.compareTo(sortk3) == 0, "The sort keys should be the same"); + doAssert(sortk1 == sortkNew, "The sort keys assignment failed"); + doAssert(sortk1.hashCode() == sortkNew.hashCode(), "sort key hashCode() failed"); + doAssert(sortkNew != sortk3, "The sort keys should be different"); + doAssert(sortk1.compareTo(sortk3) > 0, "Result should be \"Abcda\" >>> \"abcda\""); + doAssert(sortk2.compareTo(sortk3) == 0, "Result should be \"abcda\" == \"abcda\""); + long cnt1, cnt2; + byte byteArray1[] = sortk1.toByteArray(); + byte byteArray2[] = sortk2.toByteArray(); + doAssert(byteArray1 != null && byteArray2 != null, "CollationKey.toByteArray failed."); + logln("testing sortkey ends..."); + } + //---------------------------------------------------------------------------- + // ctor -- Tests the constructor methods + // + public final void TestElemIter( ) + { + logln("testing sortkey begins..."); + Collator col = null; + try { + col = Collator.getInstance(); + } catch (Exception foo) { + errln("Error : " + foo.getMessage()); + errln("Default collation creation failed."); + } + RuleBasedCollator rbCol; + if (col instanceof RuleBasedCollator) { + rbCol = (RuleBasedCollator) col; + } else { + return; + } + String testString1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?"; + String testString2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?"; + logln("Constructors and comparison testing...."); + CollationElementIterator iterator1 = rbCol.getCollationElementIterator(testString1); + CollationElementIterator iterator2 = rbCol.getCollationElementIterator(testString1); + CollationElementIterator iterator3 = rbCol.getCollationElementIterator(testString2); + int order1, order2, order3; + order1 = iterator1.next(); + order2 = iterator2.next(); + doAssert(order1 == order2, "The order result should be the same"); + + order3 = iterator3.next(); + doAssert(CollationElementIterator.primaryOrder(order1) + == CollationElementIterator.primaryOrder(order3), + "The primary orders should be the same"); + doAssert(CollationElementIterator.secondaryOrder(order1) + == CollationElementIterator.secondaryOrder(order3), + "The secondary orders should be the same"); + doAssert(CollationElementIterator.tertiaryOrder(order1) + == CollationElementIterator.tertiaryOrder(order3), + "The tertiary orders should be the same"); + + order1 = iterator1.next(); + order3 = iterator3.next(); + doAssert(CollationElementIterator.primaryOrder(order1) + == CollationElementIterator.primaryOrder(order3), + "The primary orders should be identical"); + doAssert(CollationElementIterator.tertiaryOrder(order1) + != CollationElementIterator.tertiaryOrder(order3), + "The tertiary orders should be different"); + + order1 = iterator1.next(); + order3 = iterator3.next(); + doAssert(CollationElementIterator.secondaryOrder(order1) + != CollationElementIterator.secondaryOrder(order3), + "The secondary orders should be different"); + doAssert(order1 != CollationElementIterator.NULLORDER, + "Unexpected end of iterator reached"); + + iterator1.reset(); + iterator2.reset(); + iterator3.reset(); + order1 = iterator1.next(); + order2 = iterator2.next(); + doAssert(order1 == order2, "The order result should be the same"); + + order3 = iterator3.next(); + doAssert(CollationElementIterator.primaryOrder(order1) + == CollationElementIterator.primaryOrder(order3), + "The orders should be the same"); + doAssert(CollationElementIterator.secondaryOrder(order1) + == CollationElementIterator.secondaryOrder(order3), + "The orders should be the same"); + doAssert(CollationElementIterator.tertiaryOrder(order1) + == CollationElementIterator.tertiaryOrder(order3), + "The orders should be the same"); + + order1 = iterator1.next(); + order2 = iterator2.next(); + order3 = iterator3.next(); + doAssert(CollationElementIterator.primaryOrder(order1) + == CollationElementIterator.primaryOrder(order3), + "The primary orders should be identical"); + doAssert(CollationElementIterator.tertiaryOrder(order1) + != CollationElementIterator.tertiaryOrder(order3), + "The tertiary orders should be different"); + + order1 = iterator1.next(); + order3 = iterator3.next(); + doAssert(CollationElementIterator.secondaryOrder(order1) + != CollationElementIterator.secondaryOrder(order3), + "The secondary orders should be different"); + doAssert(order1 != CollationElementIterator.NULLORDER, "Unexpected end of iterator reached"); + logln("testing CollationElementIterator ends..."); + } + + public final void TestGetAll() + { + Locale[] list = Collator.getAvailableLocales(); + for (int i = 0; i < list.length; ++i) { + log("Locale name: "); + log(list[i].toString()); + log(" , the display name is : "); + logln(list[i].getDisplayName()); + } + } +} diff --git a/jdk/test/java/text/Collator/Bug6271411.java b/jdk/test/java/text/Collator/Bug6271411.java new file mode 100644 index 00000000000..16495d04bea --- /dev/null +++ b/jdk/test/java/text/Collator/Bug6271411.java @@ -0,0 +1,194 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6271411 + * @library /java/text/testlib + * @summary Confirm that three JCK testcases for CollationElementIterator pass. + */ + +import java.text.*; + +/* + * Based on JCK-runtime-15/tests/api/java_text/CollationElementIterator/ColltnElmtIterTests.java. + */ +public class Bug6271411 extends IntlTest { + + public static void main(String argv[]) throws Exception { + Bug6271411 test = new Bug6271411(); + test.run(argv); + } + + /* + * Rule for RuleBasedCollator + */ + static final String rule = "< c, C < d; D"; + + /* + * Textdata + */ + static final String[] values = { + "", "c", "cH522Yd", "Hi, high school", "abcchCHidD" + }; + + + /* + * Confirm that setOffset() throws IllegalArgumentException + * (not IndexOutOfBoundsException) if the given offset is invalid. + * Use CollationElementIterator.setText(String). + */ + public void Test_CollationElementIterator0007() throws Exception { + int[] offsets = { + Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -10000, -2, -1, + 100, 101, // These two are customized for every test data later. + 12345, Integer.MAX_VALUE - 1, Integer.MAX_VALUE + }; + boolean err = false; + + RuleBasedCollator rbc = new RuleBasedCollator(rule); + CollationElementIterator iterator = rbc.getCollationElementIterator(""); + + for (int i = 0; i < values.length; i++) { + String source = values[i]; + iterator.setText(source); + + int len = source.length(); + offsets[5] = len + 1; + offsets[6] = len + 2; + + for (int j = 0; j < offsets.length; j++) { + try { + iterator.setOffset(offsets[j]); + System.out.println("IllegalArgumentException should be thrown for setOffset(" + + offsets[j] + ") for <" + source + ">."); + err = true; + } + catch (IllegalArgumentException e) { + } + } + } + + if (err) { + errln("CollationElementIterator.setOffset() didn't throw an expected IllegalArguemntException."); + } + } + + /* + * Confirm that setText() doesn't throw an exception and setOffset() throws + * IllegalArgumentException if the given offset is invalid. + * Use CollationElementIterator.setText(CharacterIterator). + */ + public void Test_CollationElementIterator0010() throws Exception { + String prefix = "xyz abc"; + String suffix = "1234567890"; + int begin = prefix.length(); + int[] offsets = { + Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -10000, + -2, -1, 0, 1, begin - 2, begin - 1, 9, 10, 11, 12, 13, 14, + 15, 12345, Integer.MAX_VALUE - 1, Integer.MAX_VALUE + }; + boolean err = false; + + RuleBasedCollator rbc = new RuleBasedCollator(rule); + CollationElementIterator iterator = rbc.getCollationElementIterator(""); + + for (int i = 0; i < values.length; i++) { + String str = prefix + values[i] + suffix; + int len = str.length(); + int end = len - suffix.length(); + + CharacterIterator source = + new StringCharacterIterator(str, begin, end, begin); + iterator.setText(source); + + offsets[9] = end + 1; + offsets[10] = end + 2; + offsets[11] = (end + len) / 2; + offsets[12] = len - 1; + offsets[13] = len; + offsets[14] = len + 1; + offsets[15] = len + 2; + + for (int j = 0; j < offsets.length; j++) { + try { + iterator.setOffset(offsets[j]); + + System.out.println("IllegalArgumentException should be thrown for setOffset(" + + offsets[j] + ") for <" + str + ">."); + err = true; + } + catch (IllegalArgumentException e) { + } + } + } + + if (err) { + errln("CollationElementIterator.setOffset() didn't throw an expected IllegalArguemntException."); + } + } + + /* + * Confirm that setText() doesn't throw an exception and setOffset() sets + * an offset as expected. + * Use CollationElementIterator.setText(CharacterIterator). + */ + public void Test_CollationElementIterator0011() throws Exception { + String prefix = "xyz abc"; + String suffix = "1234567890"; + int begin = prefix.length(); + int[] offsets = { begin, begin + 1, 2, 3, 4 }; + + RuleBasedCollator rbc = new RuleBasedCollator(rule); + CollationElementIterator iterator = rbc.getCollationElementIterator(""); + + for (int i = 0; i < values.length; i++) { + String str = prefix + values[i] + suffix; + int len = str.length(); + int end = len - suffix.length(); + CharacterIterator source = + new StringCharacterIterator(str, begin, end, begin); + iterator.setText(source); + + offsets[2] = (end + len) / 2; + offsets[3] = len - 1; + offsets[4] = len; + + for (int j = 0; j < offsets.length; j++) { + int offset = offsets[j]; + + if (offset < begin || offset > end) { + break; + } + + iterator.setOffset(offset); + int newOffset = iterator.getOffset(); + + if (newOffset != offset) { + throw new RuntimeException("setOffset() didn't set a correct offset. Got: " + + newOffset + " Expected: " + offset + " for <" + str + ">."); + } + } + } + } +} diff --git a/jdk/test/java/text/Collator/CollationKeyTest.java b/jdk/test/java/text/Collator/CollationKeyTest.java new file mode 100644 index 00000000000..9146bf97e9a --- /dev/null +++ b/jdk/test/java/text/Collator/CollationKeyTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4106263 + * @summary Tests on the bug 4106263 - CollationKey became non-final extendable class. + * The implementation of CollationKey is moved to the new private class, + * RuleBasedCollationKey. This test basically tests on the two features: + * 1. Existing code using CollationKey works (backward compatiblility) + * 2. CollationKey can be extended by its subclass. + */ + + +public class CollationKeyTest { + + public static void main(String[] args) { + CollationKeyTestImpl ck = new CollationKeyTestImpl("Testing the CollationKey"); + ck.run(); + } +} diff --git a/jdk/test/java/text/Collator/CollationKeyTestImpl.java b/jdk/test/java/text/Collator/CollationKeyTestImpl.java new file mode 100644 index 00000000000..a017c817188 --- /dev/null +++ b/jdk/test/java/text/Collator/CollationKeyTestImpl.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * + * A part of tests on the bug 4106263. CollationKey became non-final extendable class. + * The implementation of CollationKey is moved to the new private class, + * RuleBasedCollationKey. This test basically tests on the two features: + * 1. Existing code using CollationKey works (backward compatiblility) + * 2. CollationKey can be extended by its subclass. + */ + +import java.util.Locale; +import java.text.Collator; +import java.text.CollationKey; +import java.io.*; + +import java.text.*; + + +public class CollationKeyTestImpl extends CollationKey { + + private static String[] sourceData_ja = { + "\u3042\u3044\u3046\u3048\u3048", + "\u3041\u3043\u3045\u3047\u3049", + "\u3052\u3054\u3056\u3058\u3058", + "\u3051\u3053\u3055\u3057\u3059", + "\u3062\u3064\u3066\u3068\u3068", + "\u3061\u3063\u3065\u3067\u3069", + "\u3072\u3074\u3075\u3078\u3078", + "\u3071\u3073\u3075\u3077\u3079", + "\u3082\u3084\u3085\u3088\u3088", + "\u3081\u3083\u3085\u3087\u3089", + "\u30a2\u30a4\u30a6\u30a8\u30aa", + "\u30a1\u30a3\u30a5\u30a7\u30a9", + "\u30c2\u30c4\u30c6\u30c8\u30ca", + "\u30c1\u30c3\u30c5\u30c7\u30c9", + "\u30b2\u30b4\u30b6\u30b8\u30ba", + "\u30b1\u30b3\u30b5\u30b7\u30b9", + "\u30d2\u30d4\u30d6\u30d8\u30da", + "\u30d1\u30d3\u30d5\u30d7\u30d9", + "\u30e2\u30e4\u30e6\u30e8\u30ea", + "\u30e1\u30e3\u30e5\u30e7\u30e9" + }; + private static final String[] targetData_ja = { + "\u3042\u3044\u3046\u3048\u3048", + "\u3041\u3043\u3045\u3047\u3049", + "\u30a2\u30a4\u30a6\u30a8\u30aa", + "\u30a1\u30a3\u30a5\u30a7\u30a9", + "\u3052\u3054\u3056\u3058\u3058", + "\u3051\u3053\u3055\u3057\u3059", + "\u30b1\u30b3\u30b5\u30b7\u30b9", + "\u30b2\u30b4\u30b6\u30b8\u30ba", + "\u3061\u3063\u3065\u3067\u3069", + "\u30c1\u30c3\u30c5\u30c7\u30c9", + "\u3062\u3064\u3066\u3068\u3068", + "\u30c2\u30c4\u30c6\u30c8\u30ca", + "\u3071\u3073\u3075\u3077\u3079", + "\u30d1\u30d3\u30d5\u30d7\u30d9", + "\u3072\u3074\u3075\u3078\u3078", + "\u30d2\u30d4\u30d6\u30d8\u30da", + "\u3081\u3083\u3085\u3087\u3089", + "\u30e1\u30e3\u30e5\u30e7\u30e9", + "\u3082\u3084\u3085\u3088\u3088", + "\u30e2\u30e4\u30e6\u30e8\u30ea" + }; + + public void run() { + /** debug: printout the test data + for (int i=0; i 0){ + continue; + } + tmp = keys[f]; + i = f-1; + while ( (i>=0) && (keys[i].compareTo(tmp) > 0) ) { + keys[i+1] = keys[i]; + i--; + } + keys[i+1]=tmp; + } + } + + + /* + * From here is the bogus methods to test the subclass of + * the CollationKey class. + */ + public CollationKeyTestImpl(String str){ + super (str); + // debug: System.out.println("CollationKeyTest extends CollationKey class: "+str); + } + /* abstract method: needs to be implemented */ + public byte[] toByteArray(){ + String foo= "Hello"; + return foo.getBytes(); + } + /* abstract method: needs to be implemented */ + public int compareTo(CollationKey target){ + return 0; + } + public boolean equals(Object target){ + return true; + } + public String getSourceString(){ + return "CollationKeyTestImpl"; + } + /* + * This method tests the collection of bugus methods from the extended + * subclass of CollationKey class. + */ + private void testSubclassMethods() { + CollationKeyTestImpl clt1 = new CollationKeyTestImpl("testSubclassMethods-1"); + CollationKeyTestImpl clt2 = new CollationKeyTestImpl("testSubclassMethods-2"); + // extended method, equals always returns true + if (!clt1.equals(clt2)){ + throw new RuntimeException("Failed: equals(CollationKeySubClass)"); + } + // extended method, compareTo always returns 0 + if (clt1.compareTo(clt2)!=0){ + throw new RuntimeException("Failed: compareTo(CollationKeySubClass)"); + } + // overriding extended method, getSourceString always returns "CollationKeyTestImpl" + if (! clt1.getSourceString().equals("CollationKeyTestImpl")){ + throw new RuntimeException("Failed: CollationKey subclass overriding getSourceString()"); + } + // extended method, toByteArray always returns bytes from "Hello" + String str2 = new String( clt2.toByteArray()); + if (! clt2.equals("Hello")){ + throw new RuntimeException("Failed: CollationKey subclass toByteArray()"); + } + } + + /* + * This method tests CollationKey constructor with null source string. + * It should throw NPE. + */ + private void testConstructor() { + boolean npe=false; + try{ + CollationKeyTestImpl cltNull = new CollationKeyTestImpl(null); + } catch (NullPointerException npException){ + npe=true; + // debug: System.out.println("--- NPE is thrown with NULL arguement: PASS ---"); + } + if(!npe){ + throw new RuntimeException("Failed: CollationKey Constructor with null source"+ + " didn't throw NPE!"); + } + } + +} diff --git a/jdk/test/java/text/Collator/CollatorTest.java b/jdk/test/java/text/Collator/CollatorTest.java new file mode 100644 index 00000000000..bb6785b888f --- /dev/null +++ b/jdk/test/java/text/Collator/CollatorTest.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.lang.reflect.*; +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Vector; +import java.io.*; +import java.text.*; + +/** + * CollatorTest is a base class for tests that can be run conveniently from + * the command line as well as under the Java test harness. + *

    + * Sub-classes implement a set of methods named Test. Each + * of these methods performs some test. Test methods should indicate + * errors by calling either err or errln. This will increment the + * errorCount field and may optionally print a message to the log. + * Debugging information may also be added to the log via the log + * and logln methods. These methods will add their arguments to the + * log only if the test is being run in verbose mode. + */ +public abstract class CollatorTest extends IntlTest { + + //------------------------------------------------------------------------ + // These methods are utilities specific to the Collation tests.. + //------------------------------------------------------------------------ + + protected void assertEqual(CollationElementIterator i1, CollationElementIterator i2) { + int c1, c2, count = 0; + do { + c1 = i1.next(); + c2 = i2.next(); + if (c1 != c2) { + errln(" " + count + ": " + c1 + " != " + c2); + break; + } + count++; + } while (c1 != CollationElementIterator.NULLORDER); + } + + // Replace nonprintable characters with unicode escapes + static protected String prettify(String str) { + StringBuffer result = new StringBuffer(); + + String zero = "0000"; + + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| (ch > 0x7E && ch < 0xA0) || ch > 0x100) { + String hex = Integer.toString((int)ch,16); + + result.append("\\u" + zero.substring(0, 4 - hex.length()) + hex); + } else { + result.append(ch); + } + } + return result.toString(); + } + + // Produce a printable representation of a CollationKey + static protected String prettify(CollationKey key) { + StringBuffer result = new StringBuffer(); + byte[] bytes = key.toByteArray(); + + for (int i = 0; i < bytes.length; i += 2) { + int val = (bytes[i] << 8) + bytes[i+1]; + result.append(Integer.toString(val, 16) + " "); + } + return result.toString(); + } + + //------------------------------------------------------------------------ + // Everything below here is boilerplate code that makes it possible + // to add a new test by simply adding a function to an existing class + //------------------------------------------------------------------------ + + protected void doTest(Collator col, int strength, + String[] source, String[] target, int[] result) { + if (source.length != target.length) { + errln("Data size mismatch: source = " + + source.length + ", target = " + target.length); + + return; // Return if "-nothrow" is specified. + } + if (source.length != result.length) { + errln("Data size mismatch: source & target = " + + source.length + ", result = " + result.length); + + return; // Return if "-nothrow" is specified. + } + + col.setStrength(strength); + for (int i = 0; i < source.length ; i++) { + doTest(col, source[i], target[i], result[i]); + } + } + + protected void doTest(Collator col, + String source, String target, int result) { + char relation = '='; + if (result <= -1) { + relation = '<'; + } else if (result >= 1) { + relation = '>'; + } + + int compareResult = col.compare(source, target); + CollationKey sortKey1 = col.getCollationKey(source); + CollationKey sortKey2 = col.getCollationKey(target); + int keyResult = sortKey1.compareTo(sortKey2); + if (compareResult != keyResult) { + errln("Compare and Collation Key results are different! Source = " + + source + " Target = " + target); + } + if (keyResult != result) { + errln("Collation Test failed! Source = " + source + " Target = " + + target + " result should be " + relation); + } + } +} diff --git a/jdk/test/java/text/Collator/CurrencyCollate.java b/jdk/test/java/text/Collator/CurrencyCollate.java new file mode 100644 index 00000000000..e8f50418598 --- /dev/null +++ b/jdk/test/java/text/Collator/CurrencyCollate.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4114080 4150807 + * @summary Test currency collation. For bug 4114080, make sure the collation + * of the euro sign behaves properly. For bug 4150807, make sure the collation + * order of ALL the current symbols is correct. This means they sort + * in English alphabetical order of their English names. This test can be + * easily extended to do simple spot checking. See other collation tests for + * more sophisticated testing. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.text.CollationKey; + +/* Author: Alan Liu + * (C) Copyright IBM Corp. 1998 - All Rights Reserved + */ +public class CurrencyCollate { + static Collator myCollation = Collator.getInstance(Locale.US); + + public static void main(String[] args) { + String[] DATA = { + "\u20AC", ">", "$", // euro > dollar + "\u20AC", "<", "\u00A3", // euro < pound + + // additional tests for general currency sort order (bug #4150807) + "\u00a4", "<", "\u0e3f", // generic currency < baht + "\u0e3f", "<", "\u00a2", // baht < cent + "\u00a2", "<", "\u20a1", // cent < colon + "\u20a1", "<", "\u20a2", // colon < cruzeiro + "\u20a2", "<", "\u0024", // cruzeiro < dollar + "\u0024", "<", "\u20ab", // dollar < dong + "\u20ab", "<", "\u20a3", // dong < franc + "\u20a3", "<", "\u20a4", // franc < lira + "\u20a4", "<", "\u20a5", // lira < mill + "\u20a5", "<", "\u20a6", // mill < naira + "\u20a6", "<", "\u20a7", // naira < peseta + "\u20a7", "<", "\u00a3", // peseta < pound + "\u00a3", "<", "\u20a8", // pound < rupee + "\u20a8", "<", "\u20aa", // rupee < shekel + "\u20aa", "<", "\u20a9", // shekel < won + "\u20a9", "<", "\u00a5" // won < yen + }; + for (int i=0; i") ? 1 : (DATA[i+1].equals("<") ? -1 : 0); + int actual = myCollation.compare(DATA[i], DATA[i+2]); + if (actual != expected) { + throw new RuntimeException("Collation of " + + DATA[i] + " vs. " + + DATA[i+2] + " yields " + actual + + "; expected " + expected); + } + } + System.out.println("Ok"); + } +} + +//eof diff --git a/jdk/test/java/text/Collator/DanishTest.java b/jdk/test/java/text/Collator/DanishTest.java new file mode 100644 index 00000000000..b5194a83c2a --- /dev/null +++ b/jdk/test/java/text/Collator/DanishTest.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4930708 4174436 5008498 + * @library /java/text/testlib + * @summary test Danish Collation + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class DanishTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new DanishTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "Lvi", + "L\u00E4vi", + "L\u00FCbeck", + "ANDR\u00C9", + "ANDRE", + "ANNONCERER" + }; + + private static final String[] primaryTargetData = { + "Lwi", + "L\u00F6wi", + "Lybeck", + "ANDR\u00E9", + "ANDR\u00C9", + "ANN\u00D3NCERER" + }; + + private static final int[] primaryResults = { + -1, -1, 0, 0, 0, 0 + }; + + /* + * Data for TestTertiary() + */ + private static final String[] tertiarySourceData = { + "Luc", + "luck", + "L\u00FCbeck", + "L\u00E4vi", + "L\u00F6ww" + }; + + private static final String[] tertiaryTargetData = { + "luck", + "L\u00FCbeck", + "lybeck", + "L\u00F6we", + "mast" + }; + + private static final int[] tertiaryResults = { + -1, -1, 1, -1, -1 + }; + + /* + * Data for TestExtra() + */ + private static final String[] testData = { + "A/S", + "ANDRE", + "ANDR\u00C9", // E-acute + "ANDR\u00C8", // E-grave + "ANDR\u00E9", // e-acute + "ANDR\u00EA", // e-circ + "Andre", + "Andr\u00E9", // e-acute + "\u00C1NDRE", // A-acute + "\u00C0NDRE", // A-grave + "andre", + "\u00E1ndre", // a-acute + "\u00E0ndre", // a-grave + "ANDREAS", + "ANNONCERER", + "ANN\u00D3NCERER", // O-acute + "annoncerer", + "ann\u00F3ncerer", // o-acute + "AS", + "A\u00e6RO", // ae-ligature + "CA", + "\u00C7A", // C-cedilla + "CB", + "\u00C7C", // C-cedilla + "D.S.B.", + "DA", + "DB", + "\u00D0ORA", // capital eth + "DSB", + "\u00D0SB", // capital eth + "DSC", + "EKSTRA_ARBEJDE", + "EKSTRABUD", + "H\u00D8ST", // could the 0x00D8 be 0x2205? + "HAAG", + "H\u00C5NDBOG", // A-ring + "HAANDV\u00C6RKSBANKEN", // AE-ligature + "INTERNETFORBINDELSE", + "Internetforbindelse", + "\u00CDNTERNETFORBINDELSE", // I-acute + "internetforbindelse", + "\u00EDnternetforbindelse", // i-acute + "Karl", + "karl", + "NIELSEN", + "NIELS J\u00D8RGEN", // O-slash + "NIELS-J\u00D8RGEN", // O-slash + "OERVAL", + "\u0152RVAL", // OE-ligature + "\u0153RVAL", // oe-ligature + "R\u00C9E, A", // E-acute + "REE, B", + "R\u00C9E, L", // E-acute + "REE, V", + "SCHYTT, B", + "SCHYTT, H", + "SCH\u00DCTT, H", // U-diaeresis + "SCHYTT, L", + "SCH\u00DCTT, M", // U-diaeresis + "SS", + "ss", + "\u00DF", // sharp S + "SSA", + "\u00DFA", // sharp S + "STOREK\u00C6R", // AE-ligature + "STORE VILDMOSE", + "STORMLY", + "STORM PETERSEN", + "THORVALD", + "THORVARDUR", + "\u00DEORVAR\u0110UR", // capital thorn, capital d-stroke(like eth) (sami) + "THYGESEN", + "VESTERG\u00C5RD, A", + "VESTERGAARD, A", + "VESTERG\u00C5RD, B", // 50 + "Westmalle", + "YALLE", + "Yderligere", + "\u00DDderligere", // Y-acute + "\u00DCderligere", // U-diaeresis + "\u00FDderligere", // y-acute + "\u00FCderligere", // u-diaeresis + "U\u0308ruk-hai", + "ZORO", + "\u00C6BLE", // AE-ligature + "\u00E6BLE", // ae-ligature + "\u00C4BLE", // A-diaeresis + "\u00E4BLE", // a-diaeresis + "\u00D8BERG", // O-stroke + "\u00F8BERG", // o-stroke + "\u00D6BERG", // O-diaeresis + "\u00F6BERG" // o-diaeresis + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + + for (int i = 0; i < testData.length-1; i++) { + for (int j = i+1; j < testData.length; j++) { + doTest(myCollation, testData[i], testData[j], -1); + } + } + } + + private final Collator myCollation = Collator.getInstance(new Locale("da", "", "")); +} diff --git a/jdk/test/java/text/Collator/DummyTest.java b/jdk/test/java/text/Collator/DummyTest.java new file mode 100644 index 00000000000..3e3124edb07 --- /dev/null +++ b/jdk/test/java/text/Collator/DummyTest.java @@ -0,0 +1,421 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test Dummy Collation + */ + +import java.text.Collator; +import java.text.RuleBasedCollator; + +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +public class DummyTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new DummyTest().run(args); + } + + private static final String DEFAULTRULES = + "='\u200B'=\u200C=\u200D=\u200E=\u200F" + // Control Characters + + "=\u0000 =\u0001 =\u0002 =\u0003 =\u0004" //null, .. eot + + "=\u0005 =\u0006 =\u0007 =\u0008 ='\u0009'" //enq, ... + + "='\u000b' =\u000e" //vt,, so + + "=\u000f ='\u0010' =\u0011 =\u0012 =\u0013" //si, dle, dc1, dc2, dc3 + + "=\u0014 =\u0015 =\u0016 =\u0017 =\u0018" //dc4, nak, syn, etb, can + + "=\u0019 =\u001a =\u001b =\u001c =\u001d" //em, sub, esc, fs, gs + + "=\u001e =\u001f =\u007f" //rs, us, del + //....then the C1 Latin 1 reserved control codes + + "=\u0080 =\u0081 =\u0082 =\u0083 =\u0084 =\u0085" + + "=\u0086 =\u0087 =\u0088 =\u0089 =\u008a =\u008b" + + "=\u008c =\u008d =\u008e =\u008f =\u0090 =\u0091" + + "=\u0092 =\u0093 =\u0094 =\u0095 =\u0096 =\u0097" + + "=\u0098 =\u0099 =\u009a =\u009b =\u009c =\u009d" + + "=\u009e =\u009f" + // IGNORE except for secondary, tertiary difference + // Spaces + + ";'\u0020';'\u00A0'" // spaces + + ";'\u2000';'\u2001';'\u2002';'\u2003';'\u2004'" // spaces + + ";'\u2005';'\u2006';'\u2007';'\u2008';'\u2009'" // spaces + + ";'\u200A';'\u3000';'\uFEFF'" // spaces + + ";'\r' ;'\t' ;'\n';'\f';'\u000b'" // whitespace + + // Non-spacing accents + + + ";\u0301" // non-spacing acute accent + + ";\u0300" // non-spacing grave accent + + ";\u0306" // non-spacing breve accent + + ";\u0302" // non-spacing circumflex accent + + ";\u030c" // non-spacing caron/hacek accent + + ";\u030a" // non-spacing ring above accent + + ";\u030d" // non-spacing vertical line above + + ";\u0308" // non-spacing diaeresis accent + + ";\u030b" // non-spacing double acute accent + + ";\u0303" // non-spacing tilde accent + + ";\u0307" // non-spacing dot above/overdot accent + + ";\u0304" // non-spacing macron accent + + ";\u0337" // non-spacing short slash overlay (overstruck diacritic) + + ";\u0327" // non-spacing cedilla accent + + ";\u0328" // non-spacing ogonek accent + + ";\u0323" // non-spacing dot-below/underdot accent + + ";\u0332" // non-spacing underscore/underline accent + // with the rest of the general diacritical marks in binary order + + ";\u0305" // non-spacing overscore/overline + + ";\u0309" // non-spacing hook above + + ";\u030e" // non-spacing double vertical line above + + ";\u030f" // non-spacing double grave + + ";\u0310" // non-spacing chandrabindu + + ";\u0311" // non-spacing inverted breve + + ";\u0312" // non-spacing turned comma above/cedilla above + + ";\u0313" // non-spacing comma above + + ";\u0314" // non-spacing reversed comma above + + ";\u0315" // non-spacing comma above right + + ";\u0316" // non-spacing grave below + + ";\u0317" // non-spacing acute below + + ";\u0318" // non-spacing left tack below + + ";\u0319" // non-spacing tack below + + ";\u031a" // non-spacing left angle above + + ";\u031b" // non-spacing horn + + ";\u031c" // non-spacing left half ring below + + ";\u031d" // non-spacing up tack below + + ";\u031e" // non-spacing down tack below + + ";\u031f" // non-spacing plus sign below + + ";\u0320" // non-spacing minus sign below + + ";\u0321" // non-spacing palatalized hook below + + ";\u0322" // non-spacing retroflex hook below + + ";\u0324" // non-spacing double dot below + + ";\u0325" // non-spacing ring below + + ";\u0326" // non-spacing comma below + + ";\u0329" // non-spacing vertical line below + + ";\u032a" // non-spacing bridge below + + ";\u032b" // non-spacing inverted double arch below + + ";\u032c" // non-spacing hacek below + + ";\u032d" // non-spacing circumflex below + + ";\u032e" // non-spacing breve below + + ";\u032f" // non-spacing inverted breve below + + ";\u0330" // non-spacing tilde below + + ";\u0331" // non-spacing macron below + + ";\u0333" // non-spacing double underscore + + ";\u0334" // non-spacing tilde overlay + + ";\u0335" // non-spacing short bar overlay + + ";\u0336" // non-spacing long bar overlay + + ";\u0338" // non-spacing long slash overlay + + ";\u0339" // non-spacing right half ring below + + ";\u033a" // non-spacing inverted bridge below + + ";\u033b" // non-spacing square below + + ";\u033c" // non-spacing seagull below + + ";\u033d" // non-spacing x above + + ";\u033e" // non-spacing vertical tilde + + ";\u033f" // non-spacing double overscore + + ";\u0340" // non-spacing grave tone mark + + ";\u0341" // non-spacing acute tone mark + + ";\u0342;\u0343;\u0344;\u0345;\u0360;\u0361" // newer + + ";\u0483;\u0484;\u0485;\u0486" // Cyrillic accents + + + ";\u20D0;\u20D1;\u20D2" // symbol accents + + ";\u20D3;\u20D4;\u20D5" // symbol accents + + ";\u20D6;\u20D7;\u20D8" // symbol accents + + ";\u20D9;\u20DA;\u20DB" // symbol accents + + ";\u20DC;\u20DD;\u20DE" // symbol accents + + ";\u20DF;\u20E0;\u20E1" // symbol accents + + + ",'\u002D';\u00AD" // dashes + + ";\u2010;\u2011;\u2012" // dashes + + ";\u2013;\u2014;\u2015" // dashes + + ";\u2212" // dashes + + // other punctuation + + + "<'\u005f'" // underline/underscore (spacing) + + "<\u00af" // overline or macron (spacing) +// + "<\u00ad" // syllable hyphen (SHY) or soft hyphen + + "<'\u002c'" // comma (spacing) + + "<'\u003b'" // semicolon + + "<'\u003a'" // colon + + "<'\u0021'" // exclamation point + + "<\u00a1" // inverted exclamation point + + "<'\u003f'" // question mark + + "<\u00bf" // inverted question mark + + "<'\u002f'" // slash + + "<'\u002e'" // period/full stop + + "<\u00b4" // acute accent (spacing) + + "<'\u0060'" // grave accent (spacing) + + "<'\u005e'" // circumflex accent (spacing) + + "<\u00a8" // diaresis/umlaut accent (spacing) + + "<'\u007e'" // tilde accent (spacing) + + "<\u00b7" // middle dot (spacing) + + "<\u00b8" // cedilla accent (spacing) + + "<'\u0027'" // apostrophe + + "<'\"'" // quotation marks + + "<\u00ab" // left angle quotes + + "<\u00bb" // right angle quotes + + "<'\u0028'" // left parenthesis + + "<'\u0029'" // right parenthesis + + "<'\u005b'" // left bracket + + "<'\u005d'" // right bracket + + "<'\u007b'" // left brace + + "<'\u007d'" // right brace + + "<\u00a7" // section symbol + + "<\u00b6" // paragraph symbol + + "<\u00a9" // copyright symbol + + "<\u00ae" // registered trademark symbol + + "<'\u0040'" // at sign + + "<\u00a4" // international currency symbol + + "<\u00a2" // cent sign + + "<'\u0024'" // dollar sign + + "<\u00a3" // pound-sterling sign + + "<\u00a5" // yen sign + + "<'\u002a'" // asterisk + + "<'\\u005c'" // backslash + + "<'\u0026'" // ampersand + + "<'\u0023'" // number sign + + "<'\u0025'" // percent sign + + "<'\u002b'" // plus sign +// + "<\u002d" // hyphen or minus sign + + "<\u00b1" // plus-or-minus sign + + "<\u00f7" // divide sign + + "<\u00d7" // multiply sign + + "<'\u003c'" // less-than sign + + "<'\u003d'" // equal sign + + "<'\u003e'" // greater-than sign + + "<\u00ac" // end of line symbol/logical NOT symbol + + "<'\u007c'" // vertical line/logical OR symbol + + "<\u00a6" // broken vertical line + + "<\u00b0" // degree symbol + + "<\u00b5" // micro symbol + + // NUMERICS + + + "<0<1<2<3<4<5<6<7<8<9" + + "<\u00bc<\u00bd<\u00be" // 1/4,1/2,3/4 fractions + + // NON-IGNORABLES + + " length, etc. + // + public static void main(String[] args) throws Exception { + new IteratorTest().run(args); + } + + /** + * Test for CollationElementIterator.previous() + * + * @bug 4108758 - Make sure it works with contracting characters + * + */ + public void TestPrevious() throws ParseException { + // A basic test to see if it's working at all + backAndForth(en_us.getCollationElementIterator(test1)); + + // Test with a contracting character sequence + RuleBasedCollator c1 = new RuleBasedCollator( + "< a,A < b,B < c,C, d,D < z,Z < ch,cH,Ch,CH" ); + + backAndForth(c1.getCollationElementIterator("abchdcba")); + + // Test with an expanding character sequence + RuleBasedCollator c2 = new RuleBasedCollator( + "< a < b < c/abd < d" ); + + backAndForth(c2.getCollationElementIterator("abcd")); + + // Now try both + RuleBasedCollator c3 = new RuleBasedCollator( + "< a < b < c/aba < d < z < ch" ); + + backAndForth(c3.getCollationElementIterator("abcdbchdc")); + } + + /** + * Test for getOffset() and setOffset() + */ + public void TestOffset() { + CollationElementIterator iter = en_us.getCollationElementIterator(test1); + + // Run all the way through the iterator, then get the offset + int orders[] = getOrders(iter); + + int offset = iter.getOffset(); + if (offset != test1.length()) { + System.out.println("offset at end != length: " + + offset + " vs " + test1.length()); + } + + // Now set the offset back to the beginning and see if it works + iter.setOffset(0); + assertEqual(iter, en_us.getCollationElementIterator(test1)); + + // TODO: try iterating halfway through a messy string. + } + + /** + * Test for setText() + */ + public void TestSetText() { + CollationElementIterator iter1 = en_us.getCollationElementIterator(test1); + CollationElementIterator iter2 = en_us.getCollationElementIterator(test2); + + // Run through the second iterator just to exercise it + int c = iter2.next(); + int i = 0; + while ( ++i < 10 && c != CollationElementIterator.NULLORDER) { + c = iter2.next(); + } + + // Now set it to point to the same string as the first iterator + iter2.setText(test1); + assertEqual(iter1, iter2); + } + + /** @bug 4108762 + * Test for getMaxExpansion() + */ + public void TestMaxExpansion() throws ParseException { + // Try a simple one first: + // The only expansion ends with 'e' and has length 2 + String[][] test1 = { + { "< a & ae = \u00e4 < b < e", "" }, + { "a", "1" }, + { "b", "1" }, + { "e", "2" }, + }; + verifyExpansion(test1); + + // Now a more complicated one: + // "a1" --> "ae" + // "z" --> "aeef" + // + String[][] test2 = { + { "< a & ae = a1 & aeef = z < b < e < f", "" }, + { "a", "1" }, + { "b", "1" }, + { "e", "2" }, + { "f", "4" }, + }; + verifyExpansion(test2); + } + + /* + * @bug 4157299 + */ + public void TestClearBuffers() throws ParseException { + RuleBasedCollator c = new RuleBasedCollator("< a < b < c & ab = d"); + CollationElementIterator i = c.getCollationElementIterator("abcd"); + int e0 = i.next(); // save the first collation element + i.setOffset(3); // go to the expanding character + i.next(); // but only use up half of it + i.setOffset(0); // go back to the beginning + int e = i.next(); // and get this one again + if (e != e0) { + errln("got " + Integer.toString(e, 16) + ", expected " + + Integer.toString(e0, 16)); + } + } + + //------------------------------------------------------------------------ + // Internal utilities + // + + private void backAndForth(CollationElementIterator iter) { + // Run through the iterator forwards and stick it into an array + int [] orders = getOrders(iter); + + // Now go through it backwards and make sure we get the same values + int index = orders.length; + int o; + + while ((o = iter.previous()) != CollationElementIterator.NULLORDER) { + if (o != orders[--index]) { + errln("Mismatch at index " + index + ": " + + orders[index] + " vs " + o); + break; + } + } + if (index != 0) { + errln("Didn't get back to beginning - index is " + index); + + iter.reset(); + err("next: "); + while ((o = iter.next()) != NULLORDER) { + err( Integer.toHexString(o) + " "); + } + errln(""); + + err("prev: "); + while ((o = iter.previous()) != NULLORDER) { + err( Integer.toHexString(o) + " "); + } + errln(""); + } + } + + /** + * Verify that getMaxExpansion works on a given set of collation rules + * + * The first row of the "tests" array contains the collation rules + * at index 0, and the string at index 1 is ignored. + * + * Subsequent rows of the array contain a character and a number, both + * represented as strings. The character's collation order is determined, + * and getMaxExpansion is called for that character. If its value is + * not equal to the specified number, an error results. + */ + private void verifyExpansion(String[][] tests) throws ParseException + { + RuleBasedCollator coll = new RuleBasedCollator(tests[0][0]); + CollationElementIterator iter = coll.getCollationElementIterator(""); + + for (int i = 1; i < tests.length; i++) { + // First get the collation key that the test string expands to + iter.setText(tests[i][0]); + + int order = iter.next(); + + if (order == NULLORDER || iter.next() != NULLORDER) { + iter.reset(); + errln("verifyExpansion: '" + tests[i][0] + + "' has multiple orders:" + orderString(iter)); + } + + int expansion = iter.getMaxExpansion(order); + int expect = new Integer(tests[i][1]).intValue(); + + if (expansion != expect) { + errln("expansion for '" + tests[i][0] + "' is wrong: " + + "expected " + expect + ", got " + expansion); + } + } + } + + /** + * Return an integer array containing all of the collation orders + * returned by calls to next on the specified iterator + */ + private int[] getOrders(CollationElementIterator iter) + { + int maxSize = 100; + int size = 0; + int[] orders = new int[maxSize]; + + int order; + while ((order = iter.next()) != NULLORDER) { + if (size == maxSize) { + maxSize *= 2; + int[] temp = new int[maxSize]; + System.arraycopy(orders, 0, temp, 0, size); + orders = temp; + } + orders[size++] = order; + } + + if (orders.length > size) { + int[] temp = new int[size]; + System.arraycopy(orders, 0, temp, 0, size); + orders = temp; + } + return orders; + }; + + /** + * Return a string containing all of the collation orders + * returned by calls to next on the specified iterator + */ + private String orderString(CollationElementIterator iter) { + StringBuffer buf = new StringBuffer(); + + int order; + while ((order = iter.next()) != NULLORDER) { + buf.append( Integer.toHexString(order) + " "); + } + return buf.toString(); + } + + static final private int NULLORDER = CollationElementIterator.NULLORDER; + RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US); + + String test1 = "What subset of all possible test cases?"; + String test2 = "has the highest probability of detecting"; +} diff --git a/jdk/test/java/text/Collator/JapaneseTest.java b/jdk/test/java/text/Collator/JapaneseTest.java new file mode 100644 index 00000000000..2bd5f6d0179 --- /dev/null +++ b/jdk/test/java/text/Collator/JapaneseTest.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 1.1 02/09/11 + * @bug 4176141 4655819 + * @summary Regression tests for Japanese Collation + */ + +import java.text.*; +import java.util.*; + +public class JapaneseTest { + + // NOTE: + // Golden data in this test case is locale data dependent and + // may need to be changed if the Japanese locale collation rules + // are changed. + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * SECONDARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results1 = { + { -1, -1, -1}, + { -1, -1, -1}, + { -1, -1, -1}, + }; + static final String[][] compData1 = { + /* + * Data to verify '<' relationship in LocaleElements_ja.java + */ + {"\u3084", "\u30E6", + "Hiragana \"YA\"(0x3084) <---> Katakana \"YU\"(0x30E6)"}, + {"\u30E6", "\u3088", + "Katakana \"YU\"(0x30E6) <---> Hiragana \"YO\"(0x3088)"}, + {"\u00B1", "\u2260", + "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"}, + {"\u3011", "\u2260", + "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"}, + {"\u2260", "\u2103", + "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"}, + {"\u2260", "\u2606", + "Not Equal To(0x2260) <---> White Star(0x2606)"}, + {"\u30FD", "\u309E", + "Katakana Iteration Mark(0x30FD) <---> Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u3059\u309D", "\u3059\u309E", + "Hiragana \"SU\"(0x3059)Hiragana Iteration Mark(0x309D) <---> Hiragana \"SU\"(0x3059)Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u821E", "\u798F", + "CJK Unified Ideograph(0x821E) <---> CJK Unified Ideograph(0x798F)"}, + + /* + * Data to verify normalization + */ + {"\u2260", "\u225F", + "Not Equal To(0x2260) <---> Questioned Equal To(0x225F)"}, + {"\u226E", "\u2260", + "Not Less-than(0x226E) <---> Not Equal To(0x2260)"}, + {"\u226E", "\u226D", + "Not Less-than(0x226E) <---> Not Equivalent To(0x226D)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results2 = { + { 0, 0, 0}, + { -1, -1, -1}, + { -1, -1, -1}, + }; + static final String[][] compData2 = { + /* + * Data to verify ';' relationship in LocaleElements_ja.java + */ + {"\u3099", "\u309A", + "Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A)"}, + {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3068\u3099\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUTO\"(0x3053 0x3046 0x3068)Combining Katakana-Hiragana Voiced Sound Mark(0X3099)\"U\"(0x3046)"}, + {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3069\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUDOU\"(0x3053 0x3046 0x3069 0x3046)"}, + {"\u3053\u3046\u3069\u3046", "\u3054\u3046\u3068\u3046", + "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3069 0x3046) <---> Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046)"}, + {"\u3054\u3046\u3068\u3046", "\u3054\u3046\u3069\u3046", + "Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046) <---> Hiragana \"GOUDOU\"(0x3054 0x3046 0x3069 0x3046)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1) + */ + static final int[][] results3 = { + { 0, 0, 0}, + { 0, 0, 0}, + { -1, -1, -1}, + }; + static final String[][] compData3 = { + /* + * Data to verify ',' relationship in LocaleElements_ja.java + */ + {"\u3042", "\u3041", + "Hiragana \"A\"(0x3042) <---> Hiragana \"a\"(0x3041)"}, + {"\u3041", "\u30A2", + "Hiragana \"a\"(0x3041) <---> Katakana \"A\"(0x30A2)"}, + {"\u30A2", "\u30A1", + "Katakana \"A\"(0x30A2) <---> Katakana \"a\"(0x30A1)"}, + {"\u3094", "\u30F4", + "Hiragana \"VU\"(0x3094) <---> Katakana \"VU\"(0x30F4)"}, + {"\u3094", "\u30A6\u3099", + "Hiragana \"VU\"(0x3094) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u3046\u3099", "\u30F4", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"}, + {"\u3046\u3099", "\u30A6\u3099", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u30AB\u30A2", "\u30AB\u30FC", + "Katakana \"KAA\"(0x30AB 0x30A2) <---> Katakana \"KA-\"(0x30AB 0x30FC)"}, + {"\u30CB\u30A1\u30A2", "\u30CB\u30A1\u30FC", + "Katakana \"NyaA\"(0x30CB 0x30A1 0x30A2) <---> Katakana \"Nya-\"(0x30CB 0x30A1 0x30FC)"}, + {"\u30B3\u30AA\u30D2\u30A4", "\u30B3\u30FC\u30D2\u30FC", + "Katakana \"KOOHII\"(0x30B3 0x30AA 0x30D2 0x30A4) <---> Katakana \"KO-HI-\"(0x30B3 0x30FC 0x30D2 0x30FC)"}, + {"\u308A\u3088\u3046", "\u308A\u3087\u3046", + "Hiragana \"RIYOU\"(0x308A 0x3088 0x3046) <---> Hiragana \"Ryou\"(0x308A 0x3087 0x3046)"}, + {"\u3081\u3064\u304D", "\u3081\u3063\u304D", + "Hiragana \"METSUKI\"(0x3081 0x3064 0x304D) <---> Hiragana \"MEKKI\"(0x3081 0x3063 0x304D)"}, + {"\u3075\u3042\u3093", "\u30D5\u30A1\u30F3", + "Hiragana \"FUAN\"(0x3075 0x3042 0x3093) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"}, + {"\u3075\u3041\u3093", "\u30D5\u30A2\u30F3", + "Hiragana \"FUaN\"(0x3075 0x3041 0x3093) <---> Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3)"}, + {"\u30D5\u30A2\u30F3", "\u30D5\u30A1\u30F3", + "Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0) + */ + static final int[][] results4 = { + { 0, 0, 0}, + { 0, 0, 0}, + { 0, 0, 0}, + }; + static final String[][] compData4 = { + /* + * Data to verify Japanese normalization + */ + {"\u309E", "\u309D\u3099", + "Hiragana Voiced Iteration Mark(0x309E) <---> Hiragana Iteration Mark(0x309D)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u30FE", "\u30FD\u3099", + "Katakana Voiced Iteration Mark(0x30FE) <---> Katakana iteration mark(0x30FD)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"}, + {"\u306F\u3099", "\u3070", + "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"BA\"(0x3070)"}, + {"\u306F\u309A", "\u3071", + "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A) <---> Hiragana \"PA\"(0x3071)"}, + {"\u30EF\u3099", "\u30F7", + "Katakana \"WA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VA\"(0x30F7)"}, + {"\u30F0\u3099", "\u30F8", + "Katakana \"WI\"(0x30F0)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VI\"(0x30F8)"}, + {"\u30F1\u3099", "\u30F9", + "Katakana \"WE\"(0x30F1)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VE\"(0x30F9)"}, + {"\u30F2\u3099", "\u30FA", + "Katakana \"WO\"(0x30F2)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VO\"(0x30FA)"}, + {"\u3046\u3099", "\u3094", + "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"VU\"(0x3094)"}, + {"\u30A6\u3099", "\u30F4", + "Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"}, + + // verify normalization + {"\u2260", "\u003D\u0338", + "Not Equal To(0x2260) <---> Equal(0x003D)Combining Long Solidus Overlay(0x0338)"}, + {"\u2262", "\u2261\u0338", + "Not Identical To(0x2262) <---> Identical To(0x2261)Combining Long Solidus Overlay(0x0338)"}, + {"\u226E", "\u003C\u0338", + "Not Less-than(0x226E) <---> Less-than Sign(0x003C)Combining Long Solidus Overlay(0x0338)"}, + + // Verify a character which has been added since Unicode 2.1.X. + {"\u798F", "\uFA1B", + "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"}, + }; + + /* + * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP + * -------------------+--------------------+------------------+------------- + * PRIMARY | s1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + * SECONDARY | s1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + * TERTIARY(default) | S1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0) + */ + static final int[][] results5 = { + { 1, 0, 0}, + { 1, 0, 0}, + { 1, 0, 0}, + }; + static final String[][] compData5 = { + /* + * Data to verify normalization + */ + {"\u226D", "\u224D\u0338", + "Not Equivalent To(0x226D) <---> Equivalent To(0x224D)Combining Long Solidus Overlay(0x0338)"}, + }; + + static final int[][] results6 = { + { 1, -1, -1}, + { 1, -1, -1}, + { 1, -1, -1}, + }; + static final String[][] compData6 = { + /* + * Data to verify normalization + */ + {"\u226D", "\u226C", + "Not Equivalent To(0x226D) <---> Between(0x226C)"}, + {"\u226D", "\u225F", + "Not Equivalent To(0x226D) <---> Questioned Equal To(0x225F)"}, + }; + + + /* + * The following data isn't used at the moment because iteration marks + * aren't supported now. + */ + static final String[][] compData0 = { + {"\u307F\u307F", "\u307F\u309D", + "Hiragana \"MIMI\"(0x307F 0x307F) <---> Hiragana \"MI\"(0x307F)Hiragana Iteration Mark(0x309D)"}, + {"\u3044\u3059\u305A", "\u3044\u3059\u309E", + "Hiragana \"ISUZU\"(0x3044 0x3059 0x305A) <---> Hiragana \"ISU\"(0x3044 0x3059)Hiragana Voiced Iteration Mark(0x309E)"}, + {"\u30DF\u30DF", "\u30DF\u30FD", + "Katakana \"MIMI\"(0x30DF 0x30DF) <---> Katakana \"MI\"(0x30DF)Katakana Iteration Mark(0x30FD)"}, + {"\u30A4\u30B9\u30BA", "\u30A4\u30B9\u30FE", + "Katakana \"ISUZU\"(0x30A4 0x30B9 0x30BA) <---> Katakana \"ISU\"(0x30A4 0x30B9)Katakana Voiced Iteration Mark(0x30FE)"}, + }; + + + static final String[] decomp_name = { + "NO_DECOMP", "CANONICAL_DECOMP", "FULL_DECOMP" + }; + + static final String[] strength_name = { + "PRIMARY", "SECONDARY", "TERTIARY" + }; + + + Collator col = Collator.getInstance(Locale.JAPAN); + int result = 0; + + public static void main(String[] args) throws Exception { + new JapaneseTest().run(); + } + + public void run() { + // Use all available localse on the initial testing.... + // Locale[] locales = Locale.getAvailableLocales(); + Locale[] locales = { Locale.getDefault() }; + + for (int l = 0; l < locales.length; l++) { + Locale.setDefault(locales[l]); + + for (int decomp = 0; decomp < 3; decomp++) {// See decomp_name. + col.setDecomposition(decomp); + + for (int strength = 0; strength < 3; strength++) {// See strength_name. +// System.err.println("\n" + locales[l] + ": " + strength_name[strength] + " --- " + decomp_name[decomp]); + + col.setStrength(strength); + doCompare(compData1, results1[strength][decomp], strength, decomp); + doCompare(compData2, results2[strength][decomp], strength, decomp); + doCompare(compData3, results3[strength][decomp], strength, decomp); + doCompare(compData4, results4[strength][decomp], strength, decomp); + doCompare(compData5, results5[strength][decomp], strength, decomp); + doCompare(compData6, results6[strength][decomp], strength, decomp); + } + } + } + + /* Check result */ + if (result !=0) { + throw new RuntimeException("Unexpected results on Japanese collation."); + } + } + + void doCompare(String[][] s, int expectedValue, int strength, int decomp) { + int value; + for (int i=0; i < s.length; i++) { + if ((value = col.compare(s[i][0], s[i][1])) != expectedValue) { + result++; + System.err.println(strength_name[strength] + + ": compare() returned unexpected value.(" + + value + ") on " + decomp_name[decomp] + + " Expected(" + expectedValue + + ") for " + s[i][2]); + } + } + } +} diff --git a/jdk/test/java/text/Collator/KoreanTest.java b/jdk/test/java/text/Collator/KoreanTest.java new file mode 100644 index 00000000000..fd314ee13ed --- /dev/null +++ b/jdk/test/java/text/Collator/KoreanTest.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 1.1 02/09/12 + * @bug 4176141 4655819 + * @summary Regression tests for Korean Collation + */ + +import java.text.*; +import java.util.*; + +public class KoreanTest { + + // NOTE: + // Golden data in this test case is locale data dependent and + // may need to be changed if the Korean locale collation rules + // are changed. + + // And, CollationDecomp has been set to 0(NO_DECOMPOSITION) in + // LocaleElements_ko.java. + // This is very important to consider what is correct behavior in + // Korean Collator. Sometimes different from other locales. + + /* + * TERTIARY(default): s1 < s2, SECONDARY: s1 < s2, PRIMARY: s1 < s2 + */ + static final String[][] compData1 = { + /* + * Data to verify '<' relationship in LocaleElements_ja.java + */ + {"\uACE0\uC591\uC774", "\u732B", + "Hangul \"Cat\"(0xACE0 0xC591 0xC774) <---> Chinese Kanji \"Cat\"(0x732B)"}, + {"\u30FB", "\u2025", + "Katakana middle dot(0x30FB) <---> Two dot leader(0x2025)"}, + + {"\u00B1", "\u2260", + "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"}, + {"\u3011", "\u2260", + "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"}, + {"\u2260", "\u2103", + "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"}, + {"\u2260", "\u2606", + "Not Equal To(0x2260) <---> White Star(0x2606)"}, + + // Unlike other locales' Collator, compare() returns -1 because of + // NO_DECOMPOSITION. + /* above "assumption" is no longer true, now we do normalize ("decomposition") + for the pattern in ko locale, but exclude those hangul syllables, so the + test case below need to be excluded from tiger/1.5 + {"\u003D\u0338", "\u2260", + "Equal(0x003D)Combining Long Solidus Overlay(0x0338) <---> Not Equal To(0x2260)"}, + */ + }; + + /* + * TERTIARY(default): s1 = s2, SECONDARY: s1 = s2, PRIMARY: s1 = s2 + */ + static final String[][] compData2 = { + // Verify a character which has been added since Unicode 2.1.X. + {"\u798F", "\uFA1B", + "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"}, + + }; + + Collator col = Collator.getInstance(Locale.KOREA); + int result = 0; + + public static void main(String[] args) throws Exception { + new KoreanTest().run(); + } + + public void run() { + // + // Test for TERTIARY(default) + // + doCompare(compData1); + doEquals(compData2); + + // + // Test for SECONDARY + // + col.setStrength(Collator.SECONDARY); + doCompare(compData1); + doEquals(compData2); + + // + // Test for PRIMARY + // + col.setStrength(Collator.PRIMARY); + doCompare(compData1); + doEquals(compData2); + + if (result !=0) { + throw new RuntimeException("Unexpected results on Korean collation."); + } + } + + /* compare() should return -1 for each combination. */ + void doCompare(String[][] s) { + int value; + for (int i=0; i < s.length; i++) { + if ((value = col.compare(s[i][0], s[i][1])) > -1) { + result++; + System.err.println("TERTIARY: The first string should be less than the second string: " + + s[i][2] + " compare() returned " + value + "."); + } + } + } + + /* equals() should return true for each combination. */ + void doEquals(String[][] s) { + for (int i=0; i < s.length; i++) { + if (!col.equals(s[i][0], s[i][1])) { + result++; + System.err.println("TERTIARY: The first string should be equals to the second string: " + + s[i][2] + " compare() returned " + + col.compare(s[i][0], s[i][1] + ".")); + } + } + } +} diff --git a/jdk/test/java/text/Collator/MonkeyTest.java b/jdk/test/java/text/Collator/MonkeyTest.java new file mode 100644 index 00000000000..9539bf5f5ae --- /dev/null +++ b/jdk/test/java/text/Collator/MonkeyTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test Collation, Monkey style + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.io.IOException; +import java.util.Random; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.text.CollationKey; + +public class MonkeyTest extends CollatorTest +{ + public static void main(String[] args) throws Exception { + new MonkeyTest().run(args); + } + + public void report(String s, String t, int result, int revResult) + { + if (result == -1) + { + if (revResult != 1) + errln(" --> Test Failed"); + } + else if (result == 1) + { + if (revResult != -1) + errln(" --> Test Failed"); + } + else if (result == 0) + { + if (revResult != 0) + errln(" --> Test Failed"); + } + } + + public void TestCollationKey() + { + String source = "-abcdefghijklmnopqrstuvwxyz#&^$@"; + Random r = new Random(3); + int s = checkValue(r.nextInt() % source.length()); + int t = checkValue(r.nextInt() % source.length()); + int slen = checkValue((r.nextInt() - source.length()) % source.length()); + int tlen = checkValue((r.nextInt() - source.length()) % source.length()); + String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen)); + String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen)); + myCollator.setStrength(Collator.TERTIARY); + CollationKey CollationKey1 = myCollator.getCollationKey(subs); + CollationKey CollationKey2 = myCollator.getCollationKey(subt); + int result = CollationKey1.compareTo(CollationKey2); // Tertiary + int revResult = CollationKey2.compareTo(CollationKey1); // Tertiary + report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult); + myCollator.setStrength(Collator.SECONDARY); + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(subt); + result = CollationKey1.compareTo(CollationKey2); // Secondary + revResult = CollationKey2.compareTo(CollationKey1); // Secondary + report(("CollationKey(" + subs + ")") , ("CollationKey(" + subt + ")"), result, revResult); + myCollator.setStrength(Collator.PRIMARY); + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(subt); + result = CollationKey1.compareTo(CollationKey2); // Primary + revResult = CollationKey2.compareTo(CollationKey1); // Primary + report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult); + String addOne = subs + "\uE000"; + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(addOne); + result = CollationKey1.compareTo(CollationKey2); + if (result != -1) + errln("CollationKey(" + subs + ")" + ".LT." + "CollationKey(" + addOne + ") Failed."); + result = CollationKey2.compareTo(CollationKey1); + if (result != 1) + errln("CollationKey(" + addOne + ")" + ".GT." + "CollationKey(" + subs + ") Failed."); + } + private static int checkValue(int value) + { + value *= (value > 0) ? 1 : -1; + return value; + } + public void TestCompare() + { + String source = "-abcdefghijklmnopqrstuvwxyz#&^$@"; + Random r = new Random(3); + int s = checkValue(r.nextInt() % source.length()); + int t = checkValue(r.nextInt() % source.length()); + int slen = checkValue((r.nextInt() - source.length()) % source.length()); + int tlen = checkValue((r.nextInt() - source.length()) % source.length()); + String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen)); + String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen)); + myCollator.setStrength(Collator.TERTIARY); + int result = myCollator.compare(subs, subt); // Tertiary + int revResult = myCollator.compare(subt, subs); // Tertiary + report(subs, subt, result, revResult); + myCollator.setStrength(Collator.SECONDARY); + result = myCollator.compare(subs, subt); // Secondary + revResult = myCollator.compare(subt, subs); // Secondary + report(subs, subt, result, revResult); + myCollator.setStrength(Collator.PRIMARY); + result = myCollator.compare(subs, subt); // Primary + revResult = myCollator.compare(subt, subs); // Primary + report(subs, subt, result, revResult); + String addOne = subs + "\uE000"; + result = myCollator.compare(subs, addOne); + if (result != -1) + errln("Test : " + subs + " .LT. " + addOne + " Failed."); + result = myCollator.compare(addOne, subs); + if (result != 1) + errln("Test : " + addOne + " .GE. " + subs + " Failed."); + } + private static Collator myCollator = Collator.getInstance(); +} diff --git a/jdk/test/java/text/Collator/Regression.java b/jdk/test/java/text/Collator/Regression.java new file mode 100644 index 00000000000..958ce29c524 --- /dev/null +++ b/jdk/test/java/text/Collator/Regression.java @@ -0,0 +1,940 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4048446 4051866 4053636 4054238 4054734 4054736 4058613 4059820 4060154 + * 4062418 4065540 4066189 4066696 4076676 4078588 4079231 4081866 4087241 + * 4087243 4092260 4095316 4101940 4103436 4114076 4114077 4124632 4132736 + * 4133509 4139572 4141640 4179126 4179686 4244884 4663220 + * @library /java/text/testlib + * @summary Regression tests for Collation and associated classes + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.util.Locale; +import java.util.Vector; + + +public class Regression extends CollatorTest { + + public static void main(String[] args) throws Exception { + new Regression().run(args); + } + + // CollationElementIterator.reset() doesn't work + // + public void Test4048446() { + CollationElementIterator i1 = en_us.getCollationElementIterator(test1); + CollationElementIterator i2 = en_us.getCollationElementIterator(test1); + + while ( i1.next() != CollationElementIterator.NULLORDER ) { + } + i1.reset(); + + assertEqual(i1, i2); + } + + + // Collator -> rules -> Collator round-trip broken for expanding characters + // + public void Test4051866() throws ParseException { + // Build a collator containing expanding characters + RuleBasedCollator c1 = new RuleBasedCollator("< o " + +"& oe ,o\u3080" + +"& oe ,\u1530 ,O" + +"& OE ,O\u3080" + +"& OE ,\u1520" + +"< p ,P"); + + // Build another using the rules from the first + RuleBasedCollator c2 = new RuleBasedCollator(c1.getRules()); + + // Make sure they're the same + if (!c1.getRules().equals(c2.getRules())) { + errln("Rules are not equal"); + } + } + + // Collator thinks "black-bird" == "black" + // + public void Test4053636() { + if (en_us.equals("black-bird","black")) { + errln("black-bird == black"); + } + } + + + // CollationElementIterator will not work correctly if the associated + // Collator object's mode is changed + // + public void Test4054238() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + CollationElementIterator i1 = en_us.getCollationElementIterator(test3); + + c.setDecomposition(Collator.NO_DECOMPOSITION); + CollationElementIterator i2 = en_us.getCollationElementIterator(test3); + + // At this point, BOTH iterators should use NO_DECOMPOSITION, since the + // collator itself is in that mode + assertEqual(i1, i2); + } + + // Collator.IDENTICAL documented but not implemented + // + public void Test4054734() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + try { + c.setStrength(Collator.IDENTICAL); + } + catch (Exception e) { + errln("Caught " + e.toString() + " setting Collator.IDENTICAL"); + } + + String[] decomp = { + "\u0001", "<", "\u0002", + "\u0001", "=", "\u0001", + "A\u0001", ">", "~\u0002", // Ensure A and ~ are not compared bitwise + "\u00C0", "=", "A\u0300" // Decomp should make these equal + }; + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + compareArray(c, decomp); + + String[] nodecomp = { + "\u00C0", ">", "A\u0300" // A-grave vs. A combining-grave + }; + c.setDecomposition(Collator.NO_DECOMPOSITION); + compareArray(c, nodecomp); + } + + // Full Decomposition mode not implemented + // + public void Test4054736() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\uFB4f", "=", "\u05D0\u05DC", // Alef-Lamed vs. Alef, Lamed + }; + + compareArray(c, tests); + } + + // Collator.getInstance() causes an ArrayIndexOutofBoundsException for Korean + // + public void Test4058613() { + // Creating a default collator doesn't work when Korean is the default + // locale + + Locale oldDefault = Locale.getDefault(); + + Locale.setDefault( Locale.KOREAN ); + try { + Collator c = Collator.getInstance(); + + // Since the fix to this bug was to turn of decomposition for Korean collators, + // ensure that's what we got + if (c.getDecomposition() != Collator.NO_DECOMPOSITION) { + errln("Decomposition is not set to NO_DECOMPOSITION"); + } + } + finally { + Locale.setDefault(oldDefault); + } + } + + // RuleBasedCollator.getRules does not return the exact pattern as input + // for expanding character sequences + // + public void Test4059820() { + RuleBasedCollator c = null; + try { + c = new RuleBasedCollator("< a < b , c/a < d < z"); + } catch (ParseException e) { + errln("Exception building collator: " + e.toString()); + return; + } + if ( c.getRules().indexOf("c/a") == -1) { + errln("returned rules do not contain 'c/a'"); + } + } + + // MergeCollation::fixEntry broken for "& H < \u0131, \u0130, i, I" + // + public void Test4060154() { + RuleBasedCollator c = null; + try { + c = new RuleBasedCollator("< g, G < h, H < i, I < j, J" + + " & H < \u0131, \u0130, i, I" ); + } catch (ParseException e) { + errln("Exception building collator: " + e.toString()); + return; + } + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + + String[] tertiary = { + "A", "<", "B", + "H", "<", "\u0131", + "H", "<", "I", + "\u0131", "<", "\u0130", + "\u0130", "<", "i", + "\u0130", ">", "H", + }; + c.setStrength(Collator.TERTIARY); + compareArray(c, tertiary); + + String[] secondary = { + "H", "<", "I", + "\u0131", "=", "\u0130", + }; + c.setStrength(Collator.PRIMARY); + compareArray(c, secondary); + }; + + // Secondary/Tertiary comparison incorrect in French Secondary + // + public void Test4062418() throws ParseException { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "p\u00eache", "<", "p\u00e9ch\u00e9", // Comparing accents from end, p\u00e9ch\u00e9 is greater + }; + + compareArray(c, tests); + } + + // Collator.compare() method broken if either string contains spaces + // + public void Test4065540() { + if (en_us.compare("abcd e", "abcd f") == 0) { + errln("'abcd e' == 'abcd f'"); + } + } + + // Unicode characters need to be recursively decomposed to get the + // correct result. For example, + // u1EB1 -> \u0103 + \u0300 -> a + \u0306 + \u0300. + // + public void Test4066189() { + String test1 = "\u1EB1"; + String test2 = "a\u0306\u0300"; + + RuleBasedCollator c1 = (RuleBasedCollator) en_us.clone(); + c1.setDecomposition(Collator.FULL_DECOMPOSITION); + CollationElementIterator i1 = en_us.getCollationElementIterator(test1); + + RuleBasedCollator c2 = (RuleBasedCollator) en_us.clone(); + c2.setDecomposition(Collator.NO_DECOMPOSITION); + CollationElementIterator i2 = en_us.getCollationElementIterator(test2); + + assertEqual(i1, i2); + } + + // French secondary collation checking at the end of compare iteration fails + // + public void Test4066696() { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "\u00e0", "<", "\u01fa", // a-grave < A-ring-acute + }; + + compareArray(c, tests); + } + + + // Bad canonicalization of same-class combining characters + // + public void Test4076676() { + // These combining characters are all in the same class, so they should not + // be reordered, and they should compare as unequal. + String s1 = "A\u0301\u0302\u0300"; + String s2 = "A\u0302\u0300\u0301"; + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + if (c.compare(s1,s2) == 0) { + errln("Same-class combining chars were reordered"); + } + } + + + // RuleBasedCollator.equals(null) throws NullPointerException + // + public void Test4079231() { + try { + if (en_us.equals(null)) { + errln("en_us.equals(null) returned true"); + } + } + catch (Exception e) { + errln("en_us.equals(null) threw " + e.toString()); + } + } + + // RuleBasedCollator breaks on "< a < bb" rule + // + public void Test4078588() throws ParseException { + RuleBasedCollator rbc=new RuleBasedCollator("< a < bb"); + + int result = rbc.compare("a","bb"); + + if (result != -1) { + errln("Compare(a,bb) returned " + result + "; expected -1"); + } + } + + // Combining characters in different classes not reordered properly. + // + public void Test4081866() throws ParseException { + // These combining characters are all in different classes, + // so they should be reordered and the strings should compare as equal. + String s1 = "A\u0300\u0316\u0327\u0315"; + String s2 = "A\u0327\u0316\u0315\u0300"; + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + // Now that the default collators are set to NO_DECOMPOSITION + // (as a result of fixing bug 4114077), we must set it explicitly + // when we're testing reordering behavior. -- lwerner, 5/5/98 + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + + if (c.compare(s1,s2) != 0) { + errln("Combining chars were not reordered"); + } + } + + // string comparison errors in Scandinavian collators + // + public void Test4087241() { + RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance( + new Locale("da", "DK")); + c.setStrength(Collator.SECONDARY); + + String[] tests = { + "\u007a", "<", "\u00e6", // z < ae + "a\u0308", "<", "a\u030a", // a-unlaut < a-ring + "Y", "<", "u\u0308", // Y < u-umlaut + }; + + compareArray(c, tests); + } + + // CollationKey takes ignorable strings into account when it shouldn't + // + public void Test4087243() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] tests = { + "123", "=", "123\u0001", // 1 2 3 = 1 2 3 ctrl-A + }; + + compareArray(c, tests); + } + + // Mu/micro conflict + // Micro symbol and greek lowercase letter Mu should sort identically + // + public void Test4092260() { + Collator c = Collator.getInstance(new Locale("el", "")); + + // will only be equal when FULL_DECOMPOSITION is used + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\u00B5", "=", "\u03BC", + }; + + compareArray(c, tests); + } + + void Test4095316() { + Collator c = Collator.getInstance(new Locale("el", "GR")); + c.setStrength(Collator.TERTIARY); + // javadocs for RuleBasedCollator clearly specify that characters containing compatability + // chars MUST use FULL_DECOMPOSITION to get accurate comparisons. + c.setDecomposition(Collator.FULL_DECOMPOSITION); + + String[] tests = { + "\u03D4", "=", "\u03AB", + }; + + compareArray(c, tests); + } + + public void Test4101940() { + try { + RuleBasedCollator c = new RuleBasedCollator("< a < b"); + CollationElementIterator i = c.getCollationElementIterator(""); + i.reset(); + + if (i.next() != i.NULLORDER) { + errln("next did not return NULLORDER"); + } + } + catch (Exception e) { + errln("Caught " + e ); + } + } + + // Collator.compare not handling spaces properly + // + public void Test4103436() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] tests = { + "file", "<", "file access", + "file", "<", "fileaccess", + }; + + compareArray(c, tests); + } + + // Collation not Unicode conformant with Hangul syllables + // + public void Test4114076() { + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + // + // With Canonical decomposition, Hangul syllables should get decomposed + // into Jamo, but Jamo characters should not be decomposed into + // conjoining Jamo + // + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + String[] test1 = { + "\ud4db", "=", "\u1111\u1171\u11b6", + }; + compareArray(c, test1); + + // Full decomposition result should be the same as canonical decomposition + // for all hangul. + c.setDecomposition(Collator.FULL_DECOMPOSITION); + compareArray(c, test1); + + } + + + // Collator.getCollationKey was hanging on certain character sequences + // + public void Test4124632() throws Exception { + Collator coll = Collator.getInstance(Locale.JAPAN); + + try { + coll.getCollationKey("A\u0308bc"); + } catch (OutOfMemoryError e) { + errln("Ran out of memory -- probably an infinite loop"); + } + } + + // sort order of french words with multiple accents has errors + // + public void Test4132736() { + Collator c = Collator.getInstance(Locale.FRANCE); + + String[] test1 = { + "e\u0300e\u0301", "<", "e\u0301e\u0300", + "e\u0300\u0301", ">", "e\u0301\u0300", + }; + compareArray(c, test1); + } + + // The sorting using java.text.CollationKey is not in the exact order + // + public void Test4133509() { + String[] test1 = { + "Exception", "<", "ExceptionInInitializerError", + "Graphics", "<", "GraphicsEnvironment", + "String", "<", "StringBuffer", + }; + compareArray(en_us, test1); + } + + // Collation with decomposition off doesn't work for Europe + // + public void Test4114077() { + // Ensure that we get the same results with decomposition off + // as we do with it on.... + + RuleBasedCollator c = (RuleBasedCollator) en_us.clone(); + c.setStrength(Collator.TERTIARY); + + String[] test1 = { + "\u00C0", "=", "A\u0300", // Should be equivalent + "p\u00eache", ">", "p\u00e9ch\u00e9", + "\u0204", "=", "E\u030F", + "\u01fa", "=", "A\u030a\u0301", // a-ring-acute -> a-ring, acute + // -> a, ring, acute + "A\u0300\u0316", "<", "A\u0316\u0300", // No reordering --> unequal + }; + c.setDecomposition(Collator.NO_DECOMPOSITION); + compareArray(c, test1); + + String[] test2 = { + "A\u0300\u0316", "=", "A\u0316\u0300", // Reordering --> equal + }; + c.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + compareArray(c, test2); + } + + // Support for Swedish gone in 1.1.6 (Can't create Swedish collator) + // + public void Test4141640() { + // + // Rather than just creating a Swedish collator, we might as well + // try to instantiate one for every locale available on the system + // in order to prevent this sort of bug from cropping up in the future + // + Locale[] locales = Collator.getAvailableLocales(); + + for (int i = 0; i < locales.length; i++) { + try { + Collator c = Collator.getInstance(locales[i]); + } catch (Exception e) { + errln("Caught " + e + " creating collator for " + locales[i]); + } + } + } + + // getCollationKey throws exception for spanish text + // Cannot reproduce this bug on 1.2, however it DOES fail on 1.1.6 + // + public void Test4139572() { + // + // Code pasted straight from the bug report + // + // create spanish locale and collator + Locale l = new Locale("es", "es"); + Collator col = Collator.getInstance(l); + + // this spanish phrase kills it! + col.getCollationKey("Nombre De Objeto"); + } + + // RuleBasedCollator doesn't use getCollationElementIterator internally + // + public void Test4146160() throws ParseException { + // + // Use a custom collator class whose getCollationElementIterator + // methods increment a count.... + // + My4146160Collator.count = 0; + new My4146160Collator().getCollationKey("1"); + if (My4146160Collator.count < 1) { + errln("getCollationElementIterator not called"); + } + + My4146160Collator.count = 0; + new My4146160Collator().compare("1", "2"); + if (My4146160Collator.count < 1) { + errln("getCollationElementIterator not called"); + } + } + + static class My4146160Collator extends RuleBasedCollator { + public My4146160Collator() throws ParseException { + super(Regression.en_us.getRules()); + } + + public CollationElementIterator getCollationElementIterator( + String text) { + count++; + return super.getCollationElementIterator(text); + } + public CollationElementIterator getCollationElementIterator( + CharacterIterator text) { + count++; + return super.getCollationElementIterator(text); + } + + public static int count = 0; + }; + + // CollationElementIterator.previous broken for expanding char sequences + // + public void Test4179686() throws ParseException { + + // Create a collator with a few expanding character sequences in it.... + RuleBasedCollator coll = new RuleBasedCollator(en_us.getRules() + + " & ae ; \u00e4 & AE ; \u00c4" + + " & oe ; \u00f6 & OE ; \u00d6" + + " & ue ; \u00fc & UE ; \u00dc"); + + String text = "T\u00f6ne"; // o-umlaut + + CollationElementIterator iter = coll.getCollationElementIterator(text); + Vector elements = new Vector(); + int elem; + + // Iterate forward and collect all of the elements into a Vector + while ((elem = iter.next()) != iter.NULLORDER) { + elements.addElement(new Integer(elem)); + } + + // Now iterate backward and make sure they're the same + int index = elements.size() - 1; + while ((elem = iter.previous()) != iter.NULLORDER) { + int expect = ((Integer)elements.elementAt(index)).intValue(); + + if (elem != expect) { + errln("Mismatch at index " + index + + ": got " + Integer.toString(elem,16) + + ", expected " + Integer.toString(expect,16)); + } + index--; + } + } + + public void Test4244884() throws ParseException { + RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US); + coll = new RuleBasedCollator(coll.getRules() + + " & C < ch , cH , Ch , CH < cat < crunchy"); + + String[] testStrings = new String[] { + "car", + "cave", + "clamp", + "cramp", + "czar", + "church", + "catalogue", + "crunchy", + "dog" + }; + + for (int i = 1; i < testStrings.length; i++) { + if (coll.compare(testStrings[i - 1], testStrings[i]) >= 0) { + errln("error: \"" + testStrings[i - 1] + + "\" is greater than or equal to \"" + testStrings[i] + + "\"."); + } + } + } + + public void Test4179216() throws ParseException { + // you can position a CollationElementIterator in the middle of + // a contracting character sequence, yielding a bogus collation + // element + RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US); + coll = new RuleBasedCollator(coll.getRules() + + " & C < ch , cH , Ch , CH < cat < crunchy"); + String testText = "church church catcatcher runcrunchynchy"; + CollationElementIterator iter = coll.getCollationElementIterator( + testText); + + // test that the "ch" combination works properly + iter.setOffset(4); + int elt4 = CollationElementIterator.primaryOrder(iter.next()); + + iter.reset(); + int elt0 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(5); + int elt5 = CollationElementIterator.primaryOrder(iter.next()); + + if (elt4 != elt0 || elt5 != elt0) + errln("The collation elements at positions 0 (" + elt0 + "), 4 (" + + elt4 + "), and 5 (" + elt5 + ") don't match."); + + // test that the "cat" combination works properly + iter.setOffset(14); + int elt14 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(15); + int elt15 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(16); + int elt16 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(17); + int elt17 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(18); + int elt18 = CollationElementIterator.primaryOrder(iter.next()); + + iter.setOffset(19); + int elt19 = CollationElementIterator.primaryOrder(iter.next()); + + if (elt14 != elt15 || elt14 != elt16 || elt14 != elt17 + || elt14 != elt18 || elt14 != elt19) + errln("\"cat\" elements don't match: elt14 = " + elt14 + ", elt15 = " + + elt15 + ", elt16 = " + elt16 + ", elt17 = " + elt17 + + ", elt18 = " + elt18 + ", elt19 = " + elt19); + + // now generate a complete list of the collation elements, + // first using next() and then using setOffset(), and + // make sure both interfaces return the same set of elements + iter.reset(); + + int elt = iter.next(); + int count = 0; + while (elt != CollationElementIterator.NULLORDER) { + ++count; + elt = iter.next(); + } + + String[] nextElements = new String[count]; + String[] setOffsetElements = new String[count]; + int lastPos = 0; + + iter.reset(); + elt = iter.next(); + count = 0; + while (elt != CollationElementIterator.NULLORDER) { + nextElements[count++] = testText.substring(lastPos, iter.getOffset()); + lastPos = iter.getOffset(); + elt = iter.next(); + } + count = 0; + for (int i = 0; i < testText.length(); ) { + iter.setOffset(i); + lastPos = iter.getOffset(); + elt = iter.next(); + setOffsetElements[count++] = testText.substring(lastPos, iter.getOffset()); + i = iter.getOffset(); + } + for (int i = 0; i < nextElements.length; i++) { + if (nextElements[i].equals(setOffsetElements[i])) { + logln(nextElements[i]); + } else { + errln("Error: next() yielded " + nextElements[i] + ", but setOffset() yielded " + + setOffsetElements[i]); + } + } + } + + public void Test4216006() throws Exception { + // rule parser barfs on "<\u00e0=a\u0300", and on other cases + // where the same token (after normalization) appears twice in a row + boolean caughtException = false; + try { + RuleBasedCollator dummy = new RuleBasedCollator("\u00e0= 0) { + errln("List out of order at element #" + i + ": " + + prettify(sortedList[i]) + " >= " + + prettify(sortedList[i + 1])); + } + } + } + + // CollationElementIterator set doesn't work propertly with next/prev + public void Test4663220() { + RuleBasedCollator collator = (RuleBasedCollator)Collator.getInstance(Locale.US); + CharacterIterator stringIter = new StringCharacterIterator("fox"); + CollationElementIterator iter = collator.getCollationElementIterator(stringIter); + + int[] elements_next = new int[3]; + logln("calling next:"); + for (int i = 0; i < 3; ++i) { + logln("[" + i + "] " + (elements_next[i] = iter.next())); + } + + int[] elements_fwd = new int[3]; + logln("calling set/next:"); + for (int i = 0; i < 3; ++i) { + iter.setOffset(i); + logln("[" + i + "] " + (elements_fwd[i] = iter.next())); + } + + for (int i = 0; i < 3; ++i) { + if (elements_next[i] != elements_fwd[i]) { + errln("mismatch at position " + i + + ": " + elements_next[i] + + " != " + elements_fwd[i]); + } + } + } + + //------------------------------------------------------------------------ + // Internal utilities + // + private void compareArray(Collator c, String[] tests) { + for (int i = 0; i < tests.length; i += 3) { + + int expect = 0; + if (tests[i+1].equals("<")) { + expect = -1; + } else if (tests[i+1].equals(">")) { + expect = 1; + } else if (tests[i+1].equals("=")) { + expect = 0; + } else { + expect = Integer.decode(tests[i+1]).intValue(); + } + + int result = c.compare(tests[i], tests[i+2]); + if (sign(result) != sign(expect)) + { + errln( i/3 + ": compare(" + prettify(tests[i]) + + " , " + prettify(tests[i+2]) + + ") got " + result + "; expected " + expect); + } + else + { + // Collator.compare worked OK; now try the collation keys + CollationKey k1 = c.getCollationKey(tests[i]); + CollationKey k2 = c.getCollationKey(tests[i+2]); + + result = k1.compareTo(k2); + if (sign(result) != sign(expect)) { + errln( i/3 + ": key(" + prettify(tests[i]) + + ").compareTo(key(" + prettify(tests[i+2]) + + ")) got " + result + "; expected " + expect); + + errln(" " + prettify(k1) + " vs. " + prettify(k2)); + } + } + } + } + + private static final int sign(int i) { + if (i < 0) return -1; + if (i > 0) return 1; + return 0; + } + + + static RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US); + + String test1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?"; + String test2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?"; + String test3 = "a\u00FCbeck Gr\u00F6\u00DFe L\u00FCbeck"; +} diff --git a/jdk/test/java/text/Collator/SpanishTest.java b/jdk/test/java/text/Collator/SpanishTest.java new file mode 100644 index 00000000000..fab4ef0d66b --- /dev/null +++ b/jdk/test/java/text/Collator/SpanishTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test Spanish Collation + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class SpanishTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new SpanishTest().run(args); + } + + /* + * TestPrimary() + */ + private static final String[] primarySourceData = { + "alias", + "acHc", + "acc", + "Hello" + }; + + private static final String[] primaryTargetData = { + "allias", + "aCHc", + "aCHc", + "hellO" + }; + + private static final int[] primaryResults = { + -1, 0, -1, 0 + }; + + /* + * TestTertiary() + */ + private static final String[] tertiarySourceData = { + "alias", + "Elliot", + "Hello", + "acHc", + "acc" + }; + + private static final String[] tertiaryTargetData = { + "allias", + "Emiot", + "hellO", + "aCHc", + "aCHc" + }; + + private static final int[] tertiaryResults = { + -1, -1, 1, -1, -1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("es", "ES", "")); +} diff --git a/jdk/test/java/text/Collator/SurrogatesTest.java b/jdk/test/java/text/Collator/SurrogatesTest.java new file mode 100644 index 00000000000..87df904e882 --- /dev/null +++ b/jdk/test/java/text/Collator/SurrogatesTest.java @@ -0,0 +1,117 @@ +/* + * 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. + */ + +/* + * @test + * @library /java/text/testlib + * @summary test Supplementary Character Collation + */ + +import java.text.Collator; +import java.text.RuleBasedCollator; + +// Quick dummy program for printing out test results +public class SurrogatesTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new SurrogatesTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "A\ud800\udc04BCD" + }; + + private static final String[] primaryTargetData = { + "A\ud800\udc05BCD" + }; + + private static final int[] primaryResults = { + 0 + }; + + /* + * Data for TestTertiary() + */ + private static final String[] tertiarySourceData = { + "ABCD", + "ABCD", + "A\ud800\udc00CD", + "WXYZ", + "WXYZ", + "AFEM", + "FGM", + "BB", + "BB" + }; + + private static final String[] tertiaryTargetData = { + "A\ud800\udc00CD", + "AB\ud800\udc00D", + "A\ud800\udc01CD", + "W\ud800\udc0aYZ", + "W\ud800\udc0bYZ", + "A\ud800\udc08M", + "\ud800\udc08M", + "\ud800\udc04\ud800\udc02", + "\ud800\udc04\ud800\udc05" + }; + + private static final int[] tertiaryResults = { + -1, 1, 1, 1, -1, -1, -1, -1, 1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private Collator getCollator() { + RuleBasedCollator base = (RuleBasedCollator)Collator.getInstance(); + String rule = base.getRules(); + try { + return new RuleBasedCollator(rule + + "&B < \ud800\udc01 < \ud800\udc00" + + ", \ud800\udc02, \ud800\udc03" + + "; \ud800\udc04, \ud800\udc05" + + "< \ud800\udc06 < \ud800\udc07" + + "&FE < \ud800\udc08" + + "&PE, \ud800\udc09" + + "&Z < \ud800\udc0a < \ud800\udc0b < \ud800\udc0c" + + "&\ud800\udc0a < x, X" + + "&A < \ud800\udc04\ud800\udc05"); + } catch (Exception e) { + errln("Failed to create new RulebasedCollator object"); + return null; + } + } + + private Collator myCollation = getCollator(); +} diff --git a/jdk/test/java/text/Collator/Test4401726.java b/jdk/test/java/text/Collator/Test4401726.java new file mode 100644 index 00000000000..6f9e9ed945e --- /dev/null +++ b/jdk/test/java/text/Collator/Test4401726.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4401726 + * @author John O'Conner + * @library /java/text/testlib + * @summary Regression tests for Collation and associated classes + */ + + +import java.text.*; +import java.util.Locale; +import java.util.Vector; + +public class Test4401726 extends CollatorTest { + + public static void main(String[] args) throws Exception { + new Test4401726().run(args); + } + + public void TestSetOffSet() { + + int[] expected = {0, -1, 65536}; + int[] actual = new int[expected.length]; + + try { + String rule = "< a, A < d; D"; + + RuleBasedCollator rbc = new RuleBasedCollator(rule); + String str = "aD"; + CollationElementIterator iterator = + rbc.getCollationElementIterator(str); + + iterator.setOffset(0); + actual[0] = iterator.getOffset(); + actual[1] = iterator.previous(); + iterator.setOffset(0); + actual[2] = iterator.next(); + + if (compareArray(expected, actual) == false) { + errln("Failed."); + } + + str = "a"; + iterator = rbc.getCollationElementIterator(str); + iterator.setOffset(0); + actual[0] = iterator.getOffset(); + actual[1] = iterator.previous(); + iterator.setOffset(0); + actual[2] = iterator.next(); + + if (compareArray(expected, actual) == false) { + errln("Failed."); + } + + } catch (ParseException e) { + errln("Unexpected ParseException: " + e); + } + + + } + + boolean compareArray(int[] expected, int[] actual) { + boolean retVal = false; + if (expected.length == actual.length) { + int errors = 0; + for(int x=0; x< expected.length; ++x) { + if (expected[x] != actual[x]) { + ++errors; + } + } + if (errors == 0) retVal = true; + } + return retVal; + } +} diff --git a/jdk/test/java/text/Collator/ThaiTest.java b/jdk/test/java/text/Collator/ThaiTest.java new file mode 100644 index 00000000000..7d643446434 --- /dev/null +++ b/jdk/test/java/text/Collator/ThaiTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test Thai Collation + */ +/* + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * + * This software is the proprietary information of Oracle. + * Use is subject to license terms. + * + */ + +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; + +public class ThaiTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new ThaiTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "\u0e01\u0e01", + "\u0e07\u0e42\u0e01\u0e49", + "\u0e10\u0e34\u0e19", + "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32", + "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22", + "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22", + "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30", + "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07", + "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c", + "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07", + "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25", + "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c", + "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21", + "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19", + "\u0e2a\u0e49\u0e28\u0e36\u0e01", + "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27", + "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19", + "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19", + "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19", + "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07", + "\u0e2a\u0e49\u0e44\u0e01\u0e48", + "\u0e2b", + "\u0e2b\u0e0b\u0e2d\u0e07", + "\u0e2b\u0e19", + "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32", + "\u0e2b\u0e21", + "\u0e2b\u0e21\u0e17\u0e2d\u0e07", + "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14", + "\u0e2b\u0e21\u0e49", + "\u0e2b\u0e23\u0e13\u0e22\u0e4c", + "\u0e2b\u0e25", + "\u0e2b\u0e25\u0e19\u0e49\u0e33", + "\u0e2b\u0e25\u0e48", + "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19", + "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b", + "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07", + "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a", + "\u0e2b\u0e49", + "\u0e2d", + "\u0e2d\u0e49", + "\u0e2e\u0e42\u0e25", + "\u0e2e\u0e44\u0e1f", + "\u0e2e\u0e49" + }; + + private static final String[] primaryTargetData = { + "\u0e01\u0e01", + "\u0e07\u0e42\u0e01\u0e49", + "\u0e10\u0e34\u0e19", + "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32", + "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22", + "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22", + "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30", + "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07", + "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c", + "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07", + "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25", + "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c", + "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21", + "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19", + "\u0e2a\u0e49\u0e28\u0e36\u0e01", + "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27", + "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19", + "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19", + "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19", + "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07", + "\u0e2a\u0e49\u0e44\u0e01\u0e48", + "\u0e2b", + "\u0e2b\u0e0b\u0e2d\u0e07", + "\u0e2b\u0e19", + "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32", + "\u0e2b\u0e21", + "\u0e2b\u0e21\u0e17\u0e2d\u0e07", + "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14", + "\u0e2b\u0e21\u0e49", + "\u0e2b\u0e23\u0e13\u0e22\u0e4c", + "\u0e2b\u0e25", + "\u0e2b\u0e25\u0e19\u0e49\u0e33", + "\u0e2b\u0e25\u0e48", + "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19", + "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b", + "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07", + "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a", + "\u0e2b\u0e49", + "\u0e2d", + "\u0e2d\u0e49", + "\u0e2e\u0e42\u0e25", + "\u0e2e\u0e44\u0e1f", + "\u0e2e\u0e49" + }; + + private static final int[] primaryResults = { + 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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("th")); +} diff --git a/jdk/test/java/text/Collator/TurkishTest.java b/jdk/test/java/text/Collator/TurkishTest.java new file mode 100644 index 00000000000..f83ef228e06 --- /dev/null +++ b/jdk/test/java/text/Collator/TurkishTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test Turkish Collation + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class TurkishTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new TurkishTest().run(args); + } + + /* + * Data for TestPrimary() + */ + private static final String[] primarySourceData = { + "\u00FCoid", + "vo\u0131d", + "idea", + "Idea", + "\u0130dea" + }; + + private static final String[] primaryTargetData = { + "void", + "void", + "Idea", + "\u0130dea", + "\u0131dea" + }; + + private static final int[] primaryResults = { + -1, -1, 1, -1, 1 + }; + + /* + * Data for TestTertiary() + */ + private static final String[] tertiarySourceData = { + "s\u0327", + "v\u00E4t", + "old", + "\u00FCoid", + "h\u011Ealt", + "stres\u015E", + "vo\u0131d", + "idea", + "idea", + "\u0131dea" + }; + + private static final String tertiaryTargetData[] = { + "u\u0308", + "vbt", + "\u00D6ay", + "void", + "halt", + "\u015Etre\u015Es", + "void", + "Idea", + "\u0130dea", + "Idea" + }; + + private static final int[] tertiaryResults = { + -1, -1, -1, -1, 1, -1, -1, 1, -1, -1 + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, + primarySourceData, primaryTargetData, primaryResults); + } + + public void TestTertiary() { + doTest(myCollation, Collator.TERTIARY, + tertiarySourceData, tertiaryTargetData, tertiaryResults); + } + + private final Collator myCollation = Collator.getInstance(new Locale("tr", "TR", "")); +} diff --git a/jdk/test/java/text/Collator/VietnameseTest.java b/jdk/test/java/text/Collator/VietnameseTest.java new file mode 100644 index 00000000000..faa4921073c --- /dev/null +++ b/jdk/test/java/text/Collator/VietnameseTest.java @@ -0,0 +1,364 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4932968 5015215 + * @library /java/text/testlib + * @summary test Vietnamese Collation + */ + +/* + ******************************************************************************* + * (C) Copyright IBM Corp. 1996-2003 - All Rights Reserved * + * * + * The original version of this source code and documentation is copyrighted * + * and owned by IBM, These materials are provided under terms of a License * + * Agreement between IBM and Sun. This technology is protected by multiple * + * US and International patents. This notice and attribution to IBM may not * + * to removed. * + ******************************************************************************* + */ + +import java.util.Locale; +import java.text.Collator; + +// Quick dummy program for printing out test results +public class VietnameseTest extends CollatorTest { + + public static void main(String[] args) throws Exception { + new VietnameseTest().run(args); + } + + private final static String testPS[] = { + "a", + "a", + "\u00c2", + "Cz", + "d", + "e", + "e", + "\u1ec7", + "gz", + "i", + "kz", + "nz", + "nh", + "o", + "o", + "\u01a0", + "pz", + "tz", + "tr", + "u", + "u", + "y" + }; + + private final static String testPT[] = { + "\u00e0", + "\u0102", + "\u0102", + "Ch", + "\u0110", + "\u0111", + "\u1eb9", + "\u1eb9", + "gi", + "\u0128", + "kh", + "ng", + "ng", + "\u00f2", + "\u00f4", + "\u00f4", + "ph", + "th", + "th", + "\u1ee5", + "\u01b0", + "\u1ef4" + }; + + private final static int testPR[] = { + 0, + -1, + 1, + 1, + -1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 0, + -1, + 1, + 1, + 1, + 1, + 0, + -1, + 0 + }; + + private final static String testT[] = { + "a", + "A", + "\u00e0", + "\u00c0", + "\u1ea3", + "\u1ea2", + "\u00e3", + "\u00c3", + "\u00e1", + "\u00c1", + "\u1ea1", + "\u1ea0", + "\u0103", + "\u0102", + "\u1eb1", + "\u1eb0", + "\u1eb3", + "\u1eb2", + "\u1eb5", + "\u1eb4", + "\u1eaf", + "\u1eae", + "\u1eb7", + "\u1eb6", + "\u00e2", + "\u00c2", + "\u1ea7", + "\u1ea6", + "\u1ea9", + "\u1ea8", + "\u1eab", + "\u1eaa", + "\u1ea5", + "\u1ea4", + "\u1ead", + "\u1eac", + "b", + "B", + "c", + "C", + "ch", + "Ch", + "CH", + "d", + "D", + "\u0111", + "\u0110", + "e", + "E", + "\u00e8", + "\u00c8", + "\u1ebb", + "\u1eba", + "\u1ebd", + "\u1ebc", + "\u00e9", + "\u00c9", + "\u1eb9", + "\u1eb8", + "\u00ea", + "\u00ca", + "\u1ec1", + "\u1ec0", + "\u1ec3", + "\u1ec2", + "\u1ec5", + "\u1ec4", + "\u1ebf", + "\u1ebe", + "\u1ec7", + "\u1ec6", + "f", + "F", + "g", + "G", + "gi", + "Gi", + "GI", + "gz", + "h", + "H", + "i", + "I", + "\u00ec", + "\u00cc", + "\u1ec9", + "\u1ec8", + "\u0129", + "\u0128", + "\u00ed", + "\u00cd", + "\u1ecb", + "\u1eca", + "j", + "J", + "k", + "K", + "kh", + "Kh", + "KH", + "kz", + "l", + "L", + "m", + "M", + "n", + "N", + "ng", + "Ng", + "NG", + "ngz", + "nh", + "Nh", + "NH", + "nz", + "o", + "O", + "\u00f2", + "\u00d2", + "\u1ecf", + "\u1ece", + "\u00f5", + "\u00d5", + "\u00f3", + "\u00d3", + "\u1ecd", + "\u1ecc", + "\u00f4", + "\u00d4", + "\u1ed3", + "\u1ed2", + "\u1ed5", + "\u1ed4", + "\u1ed7", + "\u1ed6", + "\u1ed1", + "\u1ed0", + "\u1ed9", + "\u1ed8", + "\u01a1", + "\u01a0", + "\u1edd", + "\u1edc", + "\u1edf", + "\u1ede", + "\u1ee1", + "\u1ee0", + "\u1edb", + "\u1eda", + "\u1ee3", + "\u1ee2", + "p", + "P", + "ph", + "Ph", + "PH", + "pz", + "q", + "Q", + "r", + "R", + "s", + "S", + "t", + "T", + "th", + "Th", + "TH", + "thz", + "tr", + "Tr", + "TR", + "tz", + "u", + "U", + "\u00f9", + "\u00d9", + "\u1ee7", + "\u1ee6", + "\u0169", + "\u0168", + "\u00fa", + "\u00da", + "\u1ee5", + "\u1ee4", + "\u01b0", + "\u01af", + "\u1eeb", + "\u1eea", + "\u1eed", + "\u1eec", + "\u1eef", + "\u1eee", + "\u1ee9", + "\u1ee8", + "\u1ef1", + "\u1ef0", + "v", + "V", + "w", + "W", + "x", + "X", + "y", + "Y", + "\u1ef3", + "\u1ef2", + "\u1ef7", + "\u1ef6", + "\u1ef9", + "\u1ef8", + "\u00fd", + "\u00dd", + "\u1ef5", + "\u1ef4", + "z", + "Z" + }; + + public void TestPrimary() { + doTest(myCollation, Collator.PRIMARY, testPS, testPT, testPR); + } + + public void TestTertiary() { + int testLength = testT.length; + + myCollation.setStrength(Collator.TERTIARY); + for (int i = 0; i < testLength - 1; i++) { + for (int j = i+1; j < testLength; j++) { + doTest(myCollation, testT[i], testT[j], -1); + } + } + } + + private final Collator myCollation = Collator.getInstance(new Locale("vi", "VN")); +} diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt new file mode 100644 index 00000000000..23c4e4607fc --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt @@ -0,0 +1,44 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized ChiceFormat for Bug4185732Test. + +aced0005737200166a6176612e746578742e43686f696365466f726d617418e9 +c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61 +76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400 +025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3 +bf137d07e803000b5a000c67726f7570696e67557365644200116d6178467261 +6374696f6e4469676974734200106d6178496e74656765724469676974734900 +156d6178696d756d4672616374696f6e4469676974734900146d6178696d756d +496e74656765724469676974734200116d696e4672616374696f6e4469676974 +734200106d696e496e74656765724469676974734900156d696e696d756d4672 +616374696f6e4469676974734900146d696e696d756d496e7465676572446967 +6974735a00107061727365496e74656765724f6e6c7949001573657269616c56 +657273696f6e4f6e53747265616d787200106a6176612e746578742e466f726d +6174fbd8bc12e90f184302000078700103280000000300000028000100000000 +00000001000000000178757200135b4c6a6176612e6c616e672e537472696e67 +3badd256e7e91d7b470200007870000000067400034d6f6e7400035475657400 +0357656474000454687572740003467269740003536174757200025b443ea68c +14ab635a1e0200007870000000073ff000000000000040000000000000004008 +000000000000401000000000000040140000000000004018000000000000401c +000000000000 diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java new file mode 100644 index 00000000000..06c5dea1f53 --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4185732 + * @library /java/text/testlib + * @build Bug4185732Test IntlTest HexDumpReader + * @run main Bug4185732Test + * @summary test that ChoiceFormat invariants are preserved across serialization + */ +/* + * + * + * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved + * + * Portions copyright (c) 2007 Sun Microsystems, Inc. + * All Rights Reserved. + * + * The original version of this source code and documentation + * is copyrighted and owned by Taligent, Inc., a wholly-owned + * subsidiary of IBM. These materials are provided under terms + * of a License Agreement between Taligent and Sun. This technology + * is protected by multiple US and International patents. + * + * This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + */ + +import java.util.*; +import java.io.*; +import java.text.ChoiceFormat; + +/** + * A Locale can never contains language codes of he, yi or id. + */ +public class Bug4185732Test extends IntlTest { + public static void main(String[] args) throws Exception { + if (args.length == 1 && args[0].equals("prepTest")) { + prepTest(); + } else { + new Bug4185732Test().run(args); + } + } + + public void testIt() throws Exception { + try { + final ObjectInputStream in + = new ObjectInputStream(HexDumpReader.getStreamFromHexDump("Bug4185732.ser.txt")); + final ChoiceFormat loc = (ChoiceFormat)in.readObject(); + if (loc.getFormats().length != loc.getLimits().length) { + errln("ChoiceFormat did not properly check stream"); + } else { + //for some reason, the data file was VALID. This test + //requires a corrupt data file the format and limit + //arrays are of different length. + errln("Test data file was not properly created"); + } + } catch (InvalidObjectException e) { + //this is what we want to have happen + } catch (Exception e) { + errln(e.toString()); + } + } + + /** + * Create a data file for this test. The data file must be corrupted by hand. + */ + private static void prepTest() { + try { + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream("Bug4185732.ser")); + final double[] limits = {1,2,3,4,5,6,7}; + final String[] formats = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}; + final ChoiceFormat fmt = new ChoiceFormat(limits, formats); + out.writeObject(fmt); + out.close(); + System.out.println("You must invalidate the output file before running the test"); + System.out.println("by modifying the length of one of the array"); + } catch (Exception e) { + System.out.println(e); + } + } +} diff --git a/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java b/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java new file mode 100644 index 00000000000..d211bb6976e --- /dev/null +++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4387255 + * @summary Verifies that ChoiceFormat can handle large numbers of choices + */ + +import java.text.ChoiceFormat; + +public class Bug4387255 { + + private static final double[] doubles = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35}; + + private static final String[] strings = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", + "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", + "U", "V", "W", "X", "Y", "Z"}; + + private static final String pattern = + "0#0|1#1|2#2|3#3|4#4|5#5|6#6|7#7|8#8|9#9" + + "|10#A|11#B|12#C|13#D|14#E|15#F|16#G|17#H|18#I|19#J" + + "|20#K|21#L|22#M|23#N|24#O|25#P|26#Q|27#R|28#S|29#T" + + "|30#U|31#V|32#W|33#X|34#Y|35#Z"; + + public static void main(String[] args) throws Exception { + ChoiceFormat choiceFormat1 = new ChoiceFormat(doubles, strings); + ChoiceFormat choiceFormat2 = new ChoiceFormat(pattern); + if (!choiceFormat1.equals(choiceFormat2)) { + System.out.println("choiceFormat1: " + choiceFormat1.toPattern()); + System.out.println("choiceFormat2: " + choiceFormat2.toPattern()); + throw new RuntimeException(); + } + + for (int i = 0; i < doubles.length; i++) { + String result = choiceFormat2.format(doubles[i]); + if (!result.equals(strings[i])) { + throw new RuntimeException("Wrong format result - expected " + + strings[i] + ", got " + result); + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4322313.java b/jdk/test/java/text/Format/DateFormat/Bug4322313.java new file mode 100644 index 00000000000..19987022664 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4322313.java @@ -0,0 +1,364 @@ +/* + * 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. + */ + +/** + * @test + * @bug 4322313 4833268 6302990 6304305 + * @library /java/text/testlib + * @summary Make sure that new implementation for + * SimpleDateFormat.parse('z' or 'Z') and format('z' or 'Z') work correctly. + */ + +import java.io.*; +import java.text.*; +import java.util.*; + +public class Bug4322313 extends IntlTest { + + public void Test4322313() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + boolean err = false; + long mpm = 60 * 1000; /* Milliseconds per a minute */ + + Locale[] locs = {Locale.US, Locale.JAPAN, Locale.UK, new Locale("ar")}; + + String[] formats = { + "z", + "Z", + }; + + Object[][] valids = { + /* given ID offset format('z'), ('Z') index */ + {"GMT+03:04", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(9)}, + {"GMT+13:42", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(9)}, + {"GMT+00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)}, + {"GMT+1:11", new Long(-71 * mpm), "GMT+01:11", "+0111", new Integer(8)}, + {"GMT +13:42", new Long(0), "GMT", "+0000", new Integer(3)}, + {" GMT", new Long(0), "GMT", "+0000", new Integer(4)}, + {"+0304", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(5)}, + {"+1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(5)}, + {"+0000", new Long(0), "GMT+00:00", "+0000", new Integer(5)}, + {" +1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(6)}, + /* ISO-LATIN-1 digits */ + {"GMT+\u0030\u0031:\u0032\u0033", new Long(-83 * mpm), "GMT+01:23", "+0123", new Integer(9)}, + + /* In fact, this test case is skipped because TimeZone class can't + * recognize TimeZone IDs like "+00234" or "-00234". + */ + {"+00234", new Long(-23 * mpm), "GMT+00:23", "+0023", new Integer(5)}, + + {"GMT-03:04", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(9)}, + {"GMT-13:42", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(9)}, + {"GMT-00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)}, + {"GMT-1:11", new Long(71 * mpm), "GMT-01:11", "-0111", new Integer(8)}, + {"GMT -13:42", new Long(0), "GMT", "+0000", new Integer(3)}, + {"-0304", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(5)}, + {"-1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(5)}, + {" -1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(6)}, + /* ISO-LATIN-1 digits */ + {"GMT-\u0030\u0031:\u0032\u0033", new Long(83 * mpm), "GMT-01:23", "-0123", new Integer(9)}, + /* In fact, this test case is skipped because TimeZone class can't + * recognize TimeZone IDs like "+00234" or "-00234". + */ + {"-00234", new Long(23 * mpm), "GMT+00:23", "-0023", new Integer(5)}, + }; + + Object[][] invalids = { + /* given ID error index */ + {"GMT+8", new Integer(5)}, + {"GMT+18", new Integer(6)}, + {"GMT+208", new Integer(6)}, + {"GMT+0304", new Integer(6)}, + {"GMT+42195", new Integer(5)}, + {"GMT+5:8", new Integer(7)}, + {"GMT+23:60", new Integer(8)}, + {"GMT+11:1", new Integer(8)}, + {"GMT+24:13", new Integer(5)}, + {"GMT+421:950", new Integer(5)}, + {"GMT+0a:0A", new Integer(5)}, + {"GMT+ 13:42", new Integer(4)}, + {"GMT+13 :42", new Integer(6)}, + {"GMT+13: 42", new Integer(7)}, + {"GMT+-13:42", new Integer(4)}, + {"G M T", new Integer(0)}, + {"+8", new Integer(2)}, + {"+18", new Integer(3)}, + {"+208", new Integer(4)}, + {"+2360", new Integer(4)}, + {"+2413", new Integer(2)}, + {"+42195", new Integer(2)}, + {"+0AbC", new Integer(2)}, + {"+ 1342", new Integer(1)}, + {"+-1342", new Integer(1)}, + {"1342", new Integer(0)}, + /* Arabic-Indic digits */ + {"GMT+\u0660\u0661:\u0662\u0663", new Integer(4)}, + /* Extended Arabic-Indic digits */ + {"GMT+\u06f0\u06f1:\u06f2\u06f3", new Integer(4)}, + /* Devanagari digits */ + {"GMT+\u0966\u0967:\u0968\u0969", new Integer(4)}, + /* Fullwidth digits */ + {"GMT+\uFF10\uFF11:\uFF12\uFF13", new Integer(4)}, + + {"GMT-8", new Integer(5)}, + {"GMT-18", new Integer(6)}, + {"GMT-208", new Integer(6)}, + {"GMT-0304", new Integer(6)}, + {"GMT-42195", new Integer(5)}, + {"GMT-5:8", new Integer(7)}, + {"GMT-23:60", new Integer(8)}, + {"GMT-11:1", new Integer(8)}, + {"GMT-24:13", new Integer(5)}, + {"GMT-421:950", new Integer(5)}, + {"GMT-0a:0A", new Integer(5)}, + {"GMT- 13:42", new Integer(4)}, + {"GMT-13 :42", new Integer(6)}, + {"GMT-13: 42", new Integer(7)}, + {"GMT-+13:42", new Integer(4)}, + {"-8", new Integer(2)}, + {"-18", new Integer(3)}, + {"-208", new Integer(4)}, + {"-2360", new Integer(4)}, + {"-2413", new Integer(2)}, + {"-42195", new Integer(2)}, + {"-0AbC", new Integer(2)}, + {"- 1342", new Integer(1)}, + {"--1342", new Integer(1)}, + {"-802", new Integer(2)}, + /* Arabic-Indic digits */ + {"GMT-\u0660\u0661:\u0662\u0663", new Integer(4)}, + /* Extended Arabic-Indic digits */ + {"GMT-\u06f0\u06f1:\u06f2\u06f3", new Integer(4)}, + /* Devanagari digits */ + {"GMT-\u0966\u0967:\u0968\u0969", new Integer(4)}, + /* Fullwidth digits */ + {"GMT-\uFF10\uFF11:\uFF12\uFF13", new Integer(4)}, + }; + + try { + for (int i=0; i < locs.length; i++) { + Locale.setDefault(locs[i]); + + for (int j=0; j < formats.length; j++) { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + SimpleDateFormat sdf = new SimpleDateFormat(formats[j]); + Date date; + + /* Okay case */ + for (int k=0; k < valids.length; k++) { + ParsePosition pos = new ParsePosition(0); + try { + date = sdf.parse((String)valids[k][0], pos); + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] Unexpected Exception occurred: " + e); + continue; + } + + int offset = pos.getIndex(); + if (offset != ((Integer)valids[k][4]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] invalid index: expected:" + valids[k][4] + + ", got:" + offset); + } + + if (date.getTime() != ((Long)valids[k][1]).longValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][1] + + ", got:" + date.getTime() + ", " + date); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][1] + + ", got:" + date.getTime() + ", " + date); +*/ + + try { + date = sdf.parse((String)valids[k][0]); + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + valids[k][0] + + "\"] Unexpected Exception occurred: " + e); + continue; + } + + /* Since TimeZone.getTimeZone() don't treat + * "+00234" or "-00234" as a valid ID, skips. + */ + if (((String)valids[k][0]).length() == 6) { + continue; + } + + /* Since TimeZone.getTimeZone() don't recognize + * +hhmm/-hhmm format, add "GMT" as prefix. + */ + sdf.setTimeZone(TimeZone.getTimeZone( + (((((String)valids[k][0]).charAt(0) != 'G') ? + "GMT" : "") + valids[k][0]))); + StringBuffer s = new StringBuffer(); + sdf.format(date, s, new FieldPosition(0)); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + + String got = s.toString(); + String expected = (String)valids[k][2+j]; + if (!got.equals(expected) && + // special case to allow the difference between + // DateFormatSymbols.getZoneStrings() and + // TimeZone.getDisplayName() for "GMT+-00:00" + !(got.equals("GMT-00:00") && + expected.equals("GMT+00:00"))) { + err = true; + System.err.println("\tFormat Error [Locale=" + + Locale.getDefault() + ", " + + formats[j] + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][2+j] + + ", got:" + s + ", " + date); + } else { +/* + logln("\tFormat Okay [Locale=" + + Locale.getDefault() + ", " + + formats[j] + "/\"" + valids[k][0] + + "\"] expected:" + valids[k][2+j] + + ", got:" + s + ", " + date); +*/ + } + } + } + + /* Error case 1 + * using SimpleDateFormat.parse(String, ParsePosition) + */ + for (int k=0; k < invalids.length; k++) { + ParsePosition pos = new ParsePosition(0); + try { + date = sdf.parse((String)invalids[k][0], pos); + if (date != null) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] expected:null , got:" + date); + } + int offset = pos.getErrorIndex(); + if (offset != ((Integer)invalids[k][1]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] incorrect offset. expected:" + + invalids[k][1] + ", got: " + offset); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] correct offset: " + offset); +*/ + } + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Unexpected Exception occurred: " + e); + } + } + + /* Error case 2 + * using DateFormat.parse(String) + */ + boolean correctParseException = false; + for (int k=0; k < invalids.length; k++) { + try { + date = sdf.parse((String)invalids[k][0]); + } + catch (ParseException e) { + correctParseException = true; + int offset = e.getErrorOffset(); + if (offset != ((Integer)invalids[k][1]).intValue()) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception occurred with an incorrect offset. expected:" + + invalids[k][1] + ", got: " + offset); + } else { +/* + logln("\tParse Okay [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception occurred with an correct offset: " + + offset); +*/ + } + } + catch (Exception e) { + err = true; + System.err.println("\tParse Error [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Invalid exception occurred: " + e); + } + finally { + if (!correctParseException) { + err = true; + System.err.println("\tParse Error: [Locale=" + + Locale.getDefault() + ", " + formats[j] + + "/\"" + invalids[k][0] + + "\"] Expected exception didn't occur."); + } + } + } + } + } + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + if (err) { + errln("SimpleDateFormat.parse()/format() test failed"); + } + } + } + + public static void main(String[] args) throws Exception { + new Bug4322313().run(args); + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4407042.java b/jdk/test/java/text/Format/DateFormat/Bug4407042.java new file mode 100644 index 00000000000..8cc557e5a97 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4407042.java @@ -0,0 +1,132 @@ +/* + * 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. + */ + +/** + * @test + * @bug 4407042 + * @summary Make sure that cloned SimpleDateFormat objects work + * independently in multiple threads. + * @run main Bug4407042 10 + */ + +import java.io.*; +import java.text.*; +import java.util.*; + +// Usage: java Bug4407042 [duration] +public class Bug4407042 { + + static final String TIME_STRING = "2000/11/18 00:01:00"; + static final long UTC_LONG = 974534460000L; + static SimpleDateFormat masterFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + static boolean runrun = true; + static int duration = 100; + + void test() { + Locale locale = Locale.getDefault(); + if (locale.equals(new Locale("th", "TH")) || + locale.equals(new Locale("hi", "IN"))) { + return; + } + + masterFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); + DateParseThread d1 = new DateParseThread(); + DateFormatThread d2 = new DateFormatThread(); + d1.start(); + d2.start(); + int n = Thread.activeCount(); + boolean failed = false; + + for (int i = 0; i < duration; i++) { + try { + Thread.sleep(1000); + if (Thread.activeCount() != n) { + failed = true; + break; + } + } catch (InterruptedException e) { + } + } + runrun = false; + try { + d1.join(); + d2.join(); + } catch (InterruptedException e) { + } + if (failed) { + throw new RuntimeException("Failed"); + } + } + + synchronized static SimpleDateFormat getFormatter() { + return (SimpleDateFormat) masterFormat.clone(); + } + + static class DateParseThread extends Thread { + public void run() { + SimpleDateFormat sdf = getFormatter(); + Calendar cal = null; + + try { + int i = 0; + while (runrun) { + Date date =sdf.parse(TIME_STRING); + long t = date.getTime(); + i++; + if (t != UTC_LONG) { + throw new RuntimeException("Parse Error: " + i + + " (" + sdf.format(date) + ") " + t + + " != " + UTC_LONG); + } + } + } catch (ParseException e) { + e.printStackTrace(); + throw new RuntimeException("Parse Error"); + } + } + } + + static class DateFormatThread extends Thread { + public void run () { + SimpleDateFormat sdf = getFormatter(); + Calendar cal = null; + + int i = 0; + while (runrun) { + i++; + String s = sdf.format(new Date(UTC_LONG)); + if (!s.equals(TIME_STRING)) { + throw new RuntimeException("Format Error: " + i + " " + + s + " != " + TIME_STRING); + } + } + } + } + + public static void main (String[] args) { + if (args.length == 1) { + duration = Math.max(10, Integer.parseInt(args[0])); + } + new Bug4407042().test(); + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4736959.java b/jdk/test/java/text/Format/DateFormat/Bug4736959.java new file mode 100644 index 00000000000..cdb9cad20b4 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4736959.java @@ -0,0 +1,53 @@ +/* + * 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 4736959 + * @summary Make sure to parse "PM" (only) and produce the correct value. + */ + +import java.text.*; +import java.util.*; + +public class Bug4736959 { + /** + * 4736959: JSpinner won't work for AM/PM field + */ + public static void main(String[] args) { + SimpleDateFormat f = new SimpleDateFormat("a", Locale.US); + + Date d1 = f.parse("AM", new ParsePosition(0)); + System.out.println("d1: " + d1); + if (d1.getHours() != 0) { + throw new RuntimeException("Parsing \"AM\": expected 0 (midnight), got " + + d1.getHours()); + } + Date d2 = f.parse("PM", new ParsePosition(0)); + System.out.println("d2: " + d2); + if (d2.getHours() != 12) { + throw new RuntimeException("Parsing \"PM\": expected 12 (noon), got " + + d2.getHours()); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4845901.java b/jdk/test/java/text/Format/DateFormat/Bug4845901.java new file mode 100644 index 00000000000..8ed8bd47648 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug4845901.java @@ -0,0 +1,64 @@ +/* + * 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 4845901 + * @summary Make sure that SimpleDateFormat.parse() can distinguish + * the same time zone abbreviation for standard and daylight saving + * time. + */ + +import java.util.*; +import java.text.SimpleDateFormat; + +public class Bug4845901 { + public static void main (String args[]) { + TimeZone savedTZ = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("Australia/Sydney")); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS z"); + try { + testParse(sdf, "2003.01.13 11:10:00.802 AEDT", 11); + testParse(sdf, "2003.06.12 11:10:00.802 AEST", 11); + testParse(sdf, "2004.12.24 10:10:00.002 AEDT", 10); + testParse(sdf, "2004.08.10 10:10:00.002 AEST", 10); + } finally { + TimeZone.setDefault(savedTZ); + } + } + + static void testParse(SimpleDateFormat sdf, String str, int expectedHour) { + try { + Date parsedDate = sdf.parse(str); + if (parsedDate.getHours() != expectedHour) { + throw new RuntimeException( + "parsed date has wrong hour: " + parsedDate.getHours() + + ", expected: " + expectedHour + + "\ngiven string: " + str + + "\nparsedDate = " + parsedDate); + } + } catch (java.text.ParseException e) { + throw new RuntimeException("parse exception", e); + } + } +} diff --git a/hotspot/test/runtime/Unsafe/GetKlassPointerGetJavaMirror.java b/jdk/test/java/text/Format/DateFormat/Bug6251817.java similarity index 58% rename from hotspot/test/runtime/Unsafe/GetKlassPointerGetJavaMirror.java rename to jdk/test/java/text/Format/DateFormat/Bug6251817.java index 7a53be5e7e5..b0dd7fc9c2c 100644 --- a/hotspot/test/runtime/Unsafe/GetKlassPointerGetJavaMirror.java +++ b/jdk/test/java/text/Format/DateFormat/Bug6251817.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,27 +21,25 @@ * questions. */ -/* @test - * @bug 8022853 - * @library /testlibrary - * @modules java.base/jdk.internal.misc - * @build jdk.test.lib.* - * @run main GetKlassPointerGetJavaMirror +/* + * @test + * @bug 6251817 + * @summary Confirm that a typo was corrected. */ -import static jdk.test.lib.Asserts.*; +import java.text.*; +import java.util.*; -import jdk.test.lib.*; -import jdk.internal.misc.Unsafe; +public class Bug6251817 { -public class GetKlassPointerGetJavaMirror { + public static void main(String[] args) { + SimpleDateFormat sdf = new SimpleDateFormat("zzzz", Locale.US); + sdf.setTimeZone(TimeZone.getTimeZone("Australia/Lord_Howe")); + String got = sdf.format(new Date()); - public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); - Object o = new GetKlassPointerGetJavaMirror(); - final long metaspaceKlass = unsafe.getKlassPointer(o); - Class c = unsafe.getJavaMirror(metaspaceKlass); - assertEquals(o.getClass(), c); + if (!got.equals("Lord Howe Standard Time") && + !got.equals("Lord Howe Daylight Time")) { + throw new RuntimeException("Timezone display name for Australia/Lord_Howe is incorrect. Got:" + got); + } } - } diff --git a/jdk/test/java/text/Format/DateFormat/Bug6335238.java b/jdk/test/java/text/Format/DateFormat/Bug6335238.java new file mode 100644 index 00000000000..201a1af8f99 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6335238.java @@ -0,0 +1,163 @@ +/* + * 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. + */ + +/* + * @test 1.1 06/01/24 + * @bug 6335238 + * @summary Make sure that both the original and cloned SimpleDateFormat coexistindependently and don't cut off each other. + * @run main Bug6335238 10 + */ + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +// Usage: java Bug6335238 [duration] +public class Bug6335238 { + + static final long UTC_LONG = 974534460000L; + static final String TIME_STRING = "2000/11/18 00:01:00"; + static SimpleDateFormat masterSdf; + static int duration = 180; + static boolean stopped = false; + static boolean err = false; + + public static void main(String[] args) { + if (args.length == 1) { + duration = Math.max(10, Integer.parseInt(args[0])); + } + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + + TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific")); + Locale.setDefault(Locale.US); + + masterSdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + + try { + // Once it is used, DecimalFormat becomes not thread-safe. + Date d = masterSdf.parse(TIME_STRING); + + new Bug6335238(); + } catch (Exception e) { + System.err.println(e); + err = true; + } finally { + TimeZone.setDefault(savedTimeZone); + Locale.setDefault(savedLocale); + + if (err) { + throw new RuntimeException("Failed: Multiple DateFormat instances didn't work correctly."); + } else { + System.out.println("Passed."); + } + } + } + + public Bug6335238() { + stopped = false; + + DateParseThread d1 = new DateParseThread(); + DateFormatThread d2 = new DateFormatThread(); + DateParseThread d3 = new DateParseThread(); + DateFormatThread d4 = new DateFormatThread(); + + d1.start(); + d2.start(); + d3.start(); + d4.start(); + + try { + Thread.sleep(duration * 1000); + } + catch (Exception e) { + System.err.println(e); + err = true; + } + + stopped = true; + } + + class DateFormatThread extends Thread { + + public void run() { + int i = 0; + + while (!stopped) { + SimpleDateFormat sdf; + synchronized (masterSdf) { + sdf = (SimpleDateFormat)masterSdf.clone(); + } + + i++; + String s = sdf.format(new Date(UTC_LONG)); + + if (!s.equals(TIME_STRING)) { + stopped = true; + err = true; + + throw new RuntimeException("Formatting Date Error: counter=" + + i + ", Got<" + s + "> != Expected<" + TIME_STRING + ">"); + } + } + } + } + + class DateParseThread extends Thread { + + public void run() { + int i = 0; + + while (!stopped) { + SimpleDateFormat sdf; + synchronized (masterSdf) { + sdf = (SimpleDateFormat)masterSdf.clone(); + } + + i++; + Date date; + try { + date = sdf.parse(TIME_STRING); + long t = date.getTime(); + + if (t != UTC_LONG) { + stopped = true; + err = true; + + throw new RuntimeException("Parsing Date Error: counter=" + + i + " Got:" + t + "<" + sdf.format(date) + + "> != " + UTC_LONG); + } + } + catch (ParseException e) { + stopped = true; + err = true; + + throw new RuntimeException(e); + } + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug6530336.java b/jdk/test/java/text/Format/DateFormat/Bug6530336.java new file mode 100644 index 00000000000..d01a96aba9e --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6530336.java @@ -0,0 +1,108 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6530336 6537997 8008577 + * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug6530336 + */ + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class Bug6530336 { + + public static void main(String[] args) throws Exception { + Locale defaultLocale = Locale.getDefault(); + TimeZone defaultTimeZone = TimeZone.getDefault(); + + boolean err = false; + + try { + Locale locales[] = Locale.getAvailableLocales(); + Locale locale_Japan = new Locale("ja", "JP", "JP"); + TimeZone timezone_LA = TimeZone.getTimeZone("America/Los_Angeles"); + TimeZone.setDefault(timezone_LA); + + TimeZone timezones[] = { + TimeZone.getTimeZone("America/New_York"), + TimeZone.getTimeZone("America/Denver"), + }; + + String[] expected = { + "Sun Jul 15 12:00:00 PDT 2007", + "Sun Jul 15 14:00:00 PDT 2007", + }; + + Date[] dates = new Date[2]; + + for (int i = 0; i < locales.length; i++) { + if (locales[i].getLanguage().equals("th") || + locales[i].equals(locale_Japan)) { + continue; + } + + Locale.setDefault(locales[i]); + + for (int j = 0; j < timezones.length; j++) { + Calendar cal = Calendar.getInstance(timezones[j]); + cal.set(2007, 6, 15, 15, 0, 0); + dates[j] = cal.getTime(); + } + + SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); + + for (int j = 0; j < timezones.length; j++) { + sdf.setTimeZone(timezones[j]); + String date = sdf.format(dates[j]); + sdf.setTimeZone(timezone_LA); + String date_LA = sdf.parse(date).toString(); + + if (!expected[j].equals(date_LA)) { + System.err.println("Got wrong Pacific time (" + + date_LA + ") for (" + date + ") in " + locales[i] + + " in " + timezones[j] + + ".\nExpected=" + expected[j]); + err = true; + } + } + } + } + catch (Exception e) { + e.printStackTrace(); + err = true; + } + finally { + Locale.setDefault(defaultLocale); + TimeZone.setDefault(defaultTimeZone); + + if (err) { + throw new RuntimeException("Failed."); + } + } + } + +} diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java b/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java new file mode 100644 index 00000000000..d276aac088b --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java @@ -0,0 +1,1098 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.text.*; +import java.util.*; +import java.io.*; + +/** + * @test + * @bug 4029195 4052408 4056591 4059917 4060212 4061287 4065240 4071441 4073003 + * 4089106 4100302 4101483 4103340 4103341 4104136 4104522 4106807 4108407 + * 4134203 4138203 4148168 4151631 4151706 4153860 4162071 4182066 4209272 4210209 + * 4213086 4250359 4253490 4266432 4406615 4413980 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRegression + */ +public class DateFormatRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new DateFormatRegression().run(args); + } + + public void Test4029195() { + + Date today = new Date(); + + logln("today: " + today); + + SimpleDateFormat sdf = (SimpleDateFormat)SimpleDateFormat.getDateInstance(); + logln("pattern: " + sdf.toPattern()); + logln("today: " + sdf.format(today)); + + sdf.applyPattern("G yyyy DDD"); + String todayS = sdf.format(today); + logln("today: " + todayS); + try { + today = sdf.parse(todayS); + logln("today date: " + today); + } catch(Exception e) { + logln("Error reparsing date: " + e.getMessage()); + } + + try { + String rt = sdf.format(sdf.parse(todayS)); + logln("round trip: " + rt); + if (!rt.equals(todayS)) errln("Fail: Want " + todayS + " Got " + rt); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4052408() { + + DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, + DateFormat.SHORT, Locale.US); + Date date = new Date(97, Calendar.MAY, 3, 8, 55); + String str; + logln(str = fmt.format(date)); + + if (!str.equals("5/3/97 8:55 AM")) + errln("Fail: Test broken; Want 5/3/97 8:55 AM Got " + str); + Hashtable expected = new Hashtable(); + expected.put(new Integer(DateFormat.MONTH_FIELD), "5"); + expected.put(new Integer(DateFormat.DATE_FIELD), "3"); + expected.put(new Integer(DateFormat.YEAR_FIELD), "97"); + expected.put(new Integer(DateFormat.HOUR1_FIELD), "8"); + expected.put(new Integer(DateFormat.MINUTE_FIELD), "55"); + expected.put(new Integer(DateFormat.AM_PM_FIELD), "AM"); + + StringBuffer buf = new StringBuffer(); + String fieldNames[] = { + "ERA_FIELD", + "YEAR_FIELD", + "MONTH_FIELD", + "DATE_FIELD", + "HOUR_OF_DAY1_FIELD", + "HOUR_OF_DAY0_FIELD", + "MINUTE_FIELD", + "SECOND_FIELD", + "MILLISECOND_FIELD", + "DAY_OF_WEEK_FIELD", + "DAY_OF_YEAR_FIELD", + "DAY_OF_WEEK_IN_MONTH_FIELD", + "WEEK_OF_YEAR_FIELD", + "WEEK_OF_MONTH_FIELD", + "AM_PM_FIELD", + "HOUR1_FIELD", + "HOUR0_FIELD", + "TIMEZONE_FIELD", + }; + boolean pass = true; + for (int i=0; i<=17; ++i) { + FieldPosition pos = new FieldPosition(i); + fmt.format(date, buf, pos); + char[] dst = new char[pos.getEndIndex() - pos.getBeginIndex()]; + buf.getChars(pos.getBeginIndex(), pos.getEndIndex(), dst, 0); + str = new String(dst); + log(i + ": " + fieldNames[i] + + ", \"" + str + "\", " + + pos.getBeginIndex() + ", " + + pos.getEndIndex()); + String exp = (String) expected.get(new Integer(i)); + if ((exp == null && str.length() == 0) || + str.equals(exp)) + logln(" ok"); + else { + logln(" expected " + exp); + pass = false; + } + } + if (!pass) errln("Fail: FieldPosition not set right by DateFormat"); + } + + /** + * Verify the function of the [s|g]et2DigitYearStart() API. + */ + public void Test4056591() { + try { + SimpleDateFormat fmt = new SimpleDateFormat("yyMMdd", Locale.US); + Date start = new Date(1809-1900, Calendar.DECEMBER, 25); + fmt.set2DigitYearStart(start); + if (!fmt.get2DigitYearStart().equals(start)) + errln("get2DigitYearStart broken"); + Object[] DATA = { + "091225", new Date(1809-1900, Calendar.DECEMBER, 25), + "091224", new Date(1909-1900, Calendar.DECEMBER, 24), + "091226", new Date(1809-1900, Calendar.DECEMBER, 26), + "611225", new Date(1861-1900, Calendar.DECEMBER, 25), + }; + for (int i=0; i " + got + "; exp " + exp); + if (!got.equals(exp)) errln("set2DigitYearStart broken"); + } + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4059917() { + if (Locale.getDefault().equals(new Locale("hi", "IN"))) { + return; + } + + SimpleDateFormat fmt; + String myDate; + + fmt = new SimpleDateFormat( "yyyy/MM/dd" ); + myDate = "1997/01/01"; + aux917( fmt, myDate ); + + fmt = new SimpleDateFormat( "yyyyMMdd" ); + myDate = "19970101"; + aux917( fmt, myDate ); + } + + void aux917( SimpleDateFormat fmt, String str ) { + try { + logln( "==================" ); + logln( "testIt: pattern=" + fmt.toPattern() + + " string=" + str ); + + Object o; + o = fmt.parseObject( str ); + logln( "Parsed object: " + o ); + + String formatted = fmt.format( o ); + logln( "Formatted string: " + formatted ); + if (!formatted.equals(str)) errln("Fail: Want " + str + " Got " + formatted); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + public void Test4060212() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + String dateString = "1995-040.05:01:29"; + + logln( "dateString= " + dateString ); + logln("Using yyyy-DDD.hh:mm:ss"); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-DDD.hh:mm:ss"); + ParsePosition pos = new ParsePosition(0); + Date myDate = formatter.parse( dateString, pos ); + String myString = DateFormat.getDateTimeInstance( DateFormat.FULL, + DateFormat.LONG).format( myDate ); + logln( myString ); + Calendar cal = new GregorianCalendar(); + cal.setTime(myDate); + if (cal.get(Calendar.DAY_OF_YEAR) != 40) + errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + + " Want 40"); + + logln("Using yyyy-ddd.hh:mm:ss"); + formatter = new SimpleDateFormat("yyyy-ddd.hh:mm:ss"); + pos = new ParsePosition(0); + myDate = formatter.parse( dateString, pos ); + myString = DateFormat.getDateTimeInstance( DateFormat.FULL, + DateFormat.LONG).format( myDate ); + logln( myString ); + cal.setTime(myDate); + if (cal.get(Calendar.DAY_OF_YEAR) != 40) + errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + + " Want 40"); + } + finally { + Locale.setDefault(savedLocale); + } + } + + public void Test4061287() { + SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy"); + try { + logln(df.parse("35/01/1971").toString()); + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + df.setLenient(false); + boolean ok = false; + try { + logln(df.parse("35/01/1971").toString()); + } catch (ParseException e) {ok=true;} + if (!ok) errln("Fail: Lenient not working"); + } + + public void Test4065240() { + Date curDate; + DateFormat shortdate, fulldate; + String strShortDate, strFullDate; + Locale saveLocale = Locale.getDefault(); + TimeZone saveZone = TimeZone.getDefault(); + try { + Locale curLocale = new Locale("de","DE"); + Locale.setDefault(curLocale); + TimeZone.setDefault(TimeZone.getTimeZone("EST")); + curDate = new Date(98, 0, 1); + shortdate = DateFormat.getDateInstance(DateFormat.SHORT); + fulldate = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG + ); + strShortDate = new String("The current date (short form) is " + shortdate. + format(curDate)); + strFullDate = new String("The current date (long form) is " + fulldate.format(curDate)); + + logln(strShortDate); + logln(strFullDate); + + // UPDATE THIS AS ZONE NAME RESOURCE FOR in de_DE is updated + if (!strFullDate.endsWith("EST") + && !strFullDate.endsWith("GMT-05:00")) { + errln("Fail: Want GMT-05:00"); + } + } + finally { + Locale.setDefault(saveLocale); + TimeZone.setDefault(saveZone); + } + } + + /* + DateFormat.equals is too narrowly defined. As a result, MessageFormat + does not work correctly. DateFormat.equals needs to be written so + that the Calendar sub-object is not compared using Calendar.equals, + but rather compared for equivalency. This may necessitate adding a + (package private) method to Calendar to test for equivalency. + + Currently this bug breaks MessageFormat.toPattern + */ + public void Test4071441() { + DateFormat fmtA = DateFormat.getInstance(); + DateFormat fmtB = DateFormat.getInstance(); + Calendar calA = fmtA.getCalendar(); + Calendar calB = fmtB.getCalendar(); + Date epoch = new Date(0); + Date xmas = new Date(61, Calendar.DECEMBER, 25); + calA.setTime(epoch); + calB.setTime(epoch); + if (!calA.equals(calB)) + errln("Fail: Can't complete test; Calendar instances unequal"); + if (!fmtA.equals(fmtB)) + errln("Fail: DateFormat unequal when Calendars equal"); + calB.setTime(xmas); + if (calA.equals(calB)) + errln("Fail: Can't complete test; Calendar instances equal"); + if (!fmtA.equals(fmtB)) + errln("Fail: DateFormat unequal when Calendars equivalent"); + logln("DateFormat.equals ok"); + } + + /* The java.text.DateFormat.parse(String) method expects for the + US locale a string formatted according to mm/dd/yy and parses it + correctly. + + When given a string mm/dd/yyyy it only parses up to the first + two y's, typically resulting in a date in the year 1919. + + Please extend the parsing method(s) to handle strings with + four-digit year values (probably also applicable to various + other locales. */ + public void Test4073003() { + try { + DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US); + String[] tests = { "12/25/61", "12/25/1961", "4/3/2010", "4/3/10" }; + for (int i=0; i is incorrectly serialized/deserialized."); + } else { + logln("DateFormat instance which uses TimeZone <" + + IDs[i] + "> is correctly serialized/deserialized."); + } + } + if (!pass) { + errln("Fail: DateFormat serialization/equality bug"); + } + } + catch (IOException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + catch (ClassNotFoundException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + finally { + TimeZone.setDefault(savedTimeZone); + } + } + + public void Test4101483() { + SimpleDateFormat sdf = new SimpleDateFormat("z", Locale.US); + FieldPosition fp = new FieldPosition(DateFormat.TIMEZONE_FIELD); + Date d= new Date(9234567890L); + StringBuffer buf = new StringBuffer(""); + logln(sdf.format(d, buf, fp).toString()); + logln(d + " => " + buf); + logln("beginIndex = " + fp.getBeginIndex()); + logln("endIndex = " + fp.getEndIndex()); + if (fp.getBeginIndex() == fp.getEndIndex()) errln("Fail: Empty field"); + } + + /** + * Bug 4103340 + * Bug 4138203 + * This bug really only works in Locale.US, since that's what the locale + * used for Date.toString() is. Bug 4138203 reports that it fails on Korean + * NT; it would actually have failed on any non-US locale. Now it should + * work on all locales. + */ + public void Test4103340() { + // choose a date that is the FIRST of some month + // and some arbitrary time + Date d=new Date(97, 3, 1, 1, 1, 1); + SimpleDateFormat df=new SimpleDateFormat("MMMM", Locale.US); + + String s = d.toString(); + String s2 = df.format(d); + logln("Date="+s); + logln("DF="+s2); + if (s.indexOf(s2.substring(0,2)) == -1) + errln("Months should match"); + } + + public void Test4103341() { + TimeZone saveZone =TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("CST")); + SimpleDateFormat simple = new SimpleDateFormat("MM/dd/yyyy HH:mm"); + if (!simple.getTimeZone().equals(TimeZone.getDefault())) + errln("Fail: SimpleDateFormat not using default zone"); + } + finally { + TimeZone.setDefault(saveZone); + } + } + + public void Test4104136() { + SimpleDateFormat sdf = new SimpleDateFormat(); + String pattern = "'time' hh:mm"; + sdf.applyPattern(pattern); + logln("pattern: \"" + pattern + "\""); + + Object[] DATA = { + "time 10:30", new ParsePosition(10), new Date(70, Calendar.JANUARY, 1, 10, 30), + "time 10:x", new ParsePosition(0), null, + "time 10x", new ParsePosition(0), null, + }; + for (int i=0; i \"" + + str + "\", exp \"" + OUT[i] + '"'); + } + } + + // Test parsing + fmt.applyPattern("s.S"); + String[] IN = { "1.4", "1.04", "1.004", "1.45", "1.456", + "1.4567", "1.45678" }; + int[] MS = { 4, 4, 4, 45, 456, 567, 678 }; + for (int i=0; i " + + ms + " ms, exp " + MS[i] + " ms"); + } + } + } + + /** + * SimpleDateFormat incorrect handling of 2 single quotes in format() + */ + public void Test4151631() { + String pattern = "'TO_DATE('''dd'-'MM'-'yyyy HH:mm:ss''' , ''DD-MM-YYYY HH:MI:SS'')'"; + logln("pattern=" + pattern); + SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US); + String result = format.format(new Date(1998-1900, Calendar.JUNE, 30, 13, 30, 0)); + if (!result.equals("TO_DATE('30-06-1998 13:30:00' , 'DD-MM-YYYY HH:MI:SS')")) { + errln("Fail: result=" + result); + } + else { + logln("Pass: result=" + result); + } + } + + /** + * 'z' at end of date format throws index exception in SimpleDateFormat + * CANNOT REPRODUCE THIS BUG ON 1.2FCS + */ + public void Test4151706() { + SimpleDateFormat fmt = + new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss z", Locale.US); + try { + Date d = fmt.parse("Thursday, 31-Dec-98 23:00:00 GMT"); + if (d.getTime() != Date.UTC(1998-1900, Calendar.DECEMBER, 31, 23, 0, 0)) + errln("Incorrect value: " + d); + } catch (Exception e) { + errln("Fail: " + e); + } + } + + /** + * SimpleDateFormat fails to parse redundant data. + * This is actually a bug down in GregorianCalendar, but it was reported + * as follows... + */ + public void Test4153860() throws ParseException { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + SimpleDateFormat sf = (SimpleDateFormat)DateFormat.getDateTimeInstance(); + // Set the pattern + sf.applyPattern("yyyy.MM-dd"); + // Try to create a Date for February 4th + Date d1 = sf.parse("1998.02-04"); + // Set the pattern, this time to use the W value + sf.applyPattern("yyyy.MM-dd W"); + // Try to create a Date for February 4th + Date d2 = sf.parse("1998.02-04 1"); + if (!d1.equals(d2)) { + errln("Parse failed, got " + d2 + + ", expected " + d1); + } + } + finally { + Locale.setDefault(savedLocale); + } + } + + /** + * Confirm that "EST"(GMT-5:00) and "CST"(GMT-6:00) are used in US + * as "EST" or "CST", not Australian "EST" and "CST". + */ + public void Test4406615() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + + Date d1, d2; + String dt = "Mon, 1 Jan 2001 00:00:00"; + SimpleDateFormat sdf = + new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); + + try { + d1 = sdf.parse(dt+" EST"); + d2 = sdf.parse(dt+" CST"); + + if (d1.getYear() != (2000-1900) || d1.getMonth() != 11 || + d1.getDate() != 31 || d1.getHours() != 21 || d1.getMinutes() != 0 || + d2.getYear() != (2000-1900) || d2.getMonth() != 11 || + d2.getDate() != 31 || d2.getHours() != 22 || d2.getMinutes() != 0) { + errln("Parse failed, d1 = " + d1 + ", d2 = " + d2); + } else { + logln("Parse passed"); + } + } + catch (Exception e) { + errln("Parse failed, got Exception " + e); + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + } + + /** + * Cannot reproduce this bug under 1.2 FCS -- it may be a convoluted duplicate + * of some other bug that has been fixed. + */ + public void Test4162071() { + String dateString = "Thu, 30-Jul-1999 11:51:14 GMT"; + String format = "EEE', 'dd-MMM-yyyy HH:mm:ss z"; // RFC 822/1123 + SimpleDateFormat df = new + SimpleDateFormat(format, Locale.US); + + try { + Date x = df.parse(dateString); + logln("Parse format \"" + format + "\" ok"); + logln(dateString + " -> " + df.format(x)); + } catch (Exception e) { + errln("Parse format \"" + format + "\" failed."); + } + } + + /** + * DateFormat shouldn't parse year "-1" as a two-digit year (e.g., "-1" -> 1999). + */ + public void Test4182066() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy", + DateFormatSymbols.getInstance(Locale.US)); + SimpleDateFormat dispFmt = new SimpleDateFormat("MMM dd yyyy GG", + DateFormatSymbols.getInstance(Locale.US)); + /* We expect 2-digit year formats to put 2-digit years in the right + * window. Out of range years, that is, anything less than "00" or + * greater than "99", are treated as literal years. So "1/2/3456" + * becomes 3456 AD. Likewise, "1/2/-3" becomes -3 AD == 2 BC. + */ + Object[] DATA = { + "02/29/00", new Date(2000-1900, Calendar.FEBRUARY, 29), + "01/23/01", new Date(2001-1900, Calendar.JANUARY, 23), + "04/05/-1", new Date( -1-1900, Calendar.APRIL, 5), + "01/23/-9", new Date( -9-1900, Calendar.JANUARY, 23), + "11/12/1314", new Date(1314-1900, Calendar.NOVEMBER, 12), + "10/31/1", new Date( 1-1900, Calendar.OCTOBER, 31), + "09/12/+1", null, // "+1" isn't recognized by US NumberFormat + "09/12/001", new Date( 1-1900, Calendar.SEPTEMBER,12), + }; + StringBuffer out = new StringBuffer(); + boolean pass = true; + for (int i=0; i " + actStr + "\n"); + } else { + String expStr = expected != null + ? dispFmt.format(expected) : String.valueOf(expected); + out.append("FAIL: " + str + " => " + actStr + + ", expected " + expStr + "\n"); + pass = false; + } + } + if (pass) { + log(out.toString()); + } else { + err(out.toString()); + } + } + finally { + Locale.setDefault(savedLocale); + } + } + + /** + * Bug 4210209 + * Bug 4209272 + * DateFormat cannot parse Feb 29 2000 when setLenient(false) + */ + public void Test4210209() { + String pattern = "MMM d, yyyy"; + DateFormat fmt = new SimpleDateFormat(pattern, + DateFormatSymbols.getInstance(Locale.US)); + fmt.getCalendar().setLenient(false); + Date d = new Date(2000-1900, Calendar.FEBRUARY, 29); + String s = fmt.format(d); + logln(d + " x " + pattern + " => " + s); + ParsePosition pos = new ParsePosition(0); + d = fmt.parse(s, pos); + logln(d + " <= " + pattern + " x " + s); + logln("Parse pos = " + pos); + if (pos.getErrorIndex() != -1) { + errln("FAIL"); + } + + // The underlying bug is in GregorianCalendar. If the following lines + // succeed, the bug is fixed. If the bug isn't fixed, they will throw + // an exception. + GregorianCalendar cal = new GregorianCalendar(); + cal.clear(); + cal.setLenient(false); + cal.set(2000, Calendar.FEBRUARY, 29); // This should work! + logln(cal.getTime().toString()); + } + + /** + * DateFormat.getDateTimeInstance() allows illegal parameters. + */ + public void Test4213086() { + int[] DATA = { + // Style value, 0/1 for illegal/legal + -99, 0, + -1, 0, + 0, 1, + 1, 1, + 2, 1, + 3, 1, + 4, 0, + 99, 0, + }; + String[] DESC = { + "getDateTimeInstance(date)", + "getDateTimeInstance(time)", + "getDateInstance", + "getTimeInstance", + }; + String[] GOT = { + "disallowed", "allowed", "" + }; + for (int i=0; i \"" + s + '"'); + } else { + errln("FAIL: " + FORMAT_MS + " ms f* \"" + + FORMAT_PAT[i] + "\" -> \"" + s + "\", expect \"" + + FORMAT_TO[i] + '"'); + } + } + + // Test parsing. We want to make sure all digits are read. + fmt.applyPattern(PARSE_PAT); + for (int i=0; i " + ms + " ms"); + } else { + errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" + + PARSE_PAT + "\" -> " + ms + " ms, expect " + + PARSE_TO[i] + " ms"); + } + } + + // Test LONG parsing. We want to make sure all digits are read. + fmt.applyPattern(PARSE_LPAT); + for (int i=0; i " + ms + " ms"); + } else { + errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" + + PARSE_LPAT + "\" -> " + ms + " ms, expect " + + PARSE_TO[i] + " ms"); + } + } + } + + /** + * Bug in handling of time instance; introduces in fix for 4213086. + */ + public void Test4250359() { + DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT, + Locale.US); + Date d = new Date(1999-1900, Calendar.DECEMBER, 25, + 1, 2, 3); + String s = df.format(d); + // If the bug is present, we see "1:02 AM 1:02 AM". + // Look for more than one instance of "AM". + int i = s.indexOf("AM"); + int j = s.indexOf("AM", i+1); + if (i < 0 || j >= 0) { + errln("FAIL: getTimeInstance().format(d) => \"" + + s + "\""); + } + } + + /** + * Test whether SimpleDataFormat (DateFormatSymbols) can format/parse + * non-localized time zones. + */ + public void Test4261506() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + Locale.setDefault(Locale.JAPAN); + + // XXX: Test assumes "PST" is not TimeZoneNames_ja. Need to + // pick up another time zone when L10N is done to that file. + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + SimpleDateFormat fmt = new SimpleDateFormat("yy/MM/dd hh:ss zzz", Locale.JAPAN); + String result = fmt.format(new Date(1999, 0, 1)); + logln("format()=>" + result); + if (!result.endsWith("PST")) { + errln("FAIL: SimpleDataFormat.format() did not retrun PST"); + } + + Date d = null; + try { + d = fmt.parse("99/1/1 10:10 PST"); + } catch (ParseException e) { + errln("FAIL: SimpleDataFormat.parse() could not parse PST"); + } + + result = fmt.format(d); + logln("roundtrip:" + result); + if (!result.equals("99/01/01 10:10 PST")) { + errln("FAIL: SimpleDataFomat timezone roundtrip failed"); + } + + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + +} + +//eof diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java b/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java new file mode 100644 index 00000000000..73d023163f1 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java @@ -0,0 +1,727 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 + * @summary test Date Format (Round Trip) + * @bug 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRoundTripTest + */ + +import java.text.*; +import java.util.*; + +public class DateFormatRoundTripTest extends IntlTest { + + static Random RANDOM = null; + + static final long FIXED_SEED = 3141592653589793238L; // Arbitrary fixed value + + // Useful for turning up subtle bugs: Use -infinite and run while at lunch. + boolean INFINITE = false; // Warning -- makes test run infinite loop!!! + + boolean random = false; + + // Options used to reproduce failures + Locale locale = null; + String pattern = null; + Date initialDate = null; + + Locale[] avail; + TimeZone defaultZone; + + // If SPARSENESS is > 0, we don't run each exhaustive possibility. + // There are 24 total possible tests per each locale. A SPARSENESS + // of 12 means we run half of them. A SPARSENESS of 23 means we run + // 1 of them. SPARSENESS _must_ be in the range 0..23. + static final int SPARSENESS = 18; + + static final int TRIALS = 4; + + static final int DEPTH = 5; + + static SimpleDateFormat refFormat = + new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); + + public DateFormatRoundTripTest(boolean rand, long seed, boolean infinite, + Date date, String pat, Locale loc) { + random = rand; + if (random) { + RANDOM = new Random(seed); + } + INFINITE = infinite; + + initialDate = date; + locale = loc; + pattern = pat; + } + + /** + * Parse a name like "fr_FR" into new Locale("fr", "FR", ""); + */ + static Locale createLocale(String name) { + String country = "", + variant = ""; + int i; + if ((i = name.indexOf('_')) >= 0) { + country = name.substring(i+1); + name = name.substring(0, i); + } + if ((i = country.indexOf('_')) >= 0) { + variant = country.substring(i+1); + country = country.substring(0, i); + } + return new Locale(name, country, variant); + } + + public static void main(String[] args) throws Exception { + // Command-line parameters + Locale loc = null; + boolean infinite = false; + boolean random = false; + long seed = FIXED_SEED; + String pat = null; + Date date = null; + + Vector newArgs = new Vector(); + for (int i=0; i] [-locale ] [-date ] [-INFINITE]"); + System.out.println(" [-random | -randomseed | -seed ]"); + System.out.println("* Warning: Some patterns will fail with some locales."); + System.out.println("* Do not use -pattern unless you know what you are doing!"); + System.out.println("When specifying a locale, use a format such as fr_FR."); + System.out.println("Use -pattern, -locale, and -date to reproduce a failure."); + System.out.println("-random Random with fixed seed (same data every run)."); + System.out.println("-randomseed Random with a random seed."); + System.out.println("-seed Random using as seed."); + super.usage(); + } + + static private class TestCase { + private int[] date; + TimeZone zone; + FormatFactory ff; + boolean timeOnly; + private Date _date; + + TestCase(int[] d, TimeZone z, FormatFactory f, boolean timeOnly) { + date = d; + zone = z; + ff = f; + this.timeOnly = timeOnly; + } + + TestCase(Date d, TimeZone z, FormatFactory f, boolean timeOnly) { + date = null; + _date = d; + zone = z; + ff = f; + this.timeOnly = timeOnly; + } + + /** + * Create a format for testing. + */ + DateFormat createFormat() { + return ff.createFormat(); + } + + /** + * Return the Date of this test case; must be called with the default + * zone set to this TestCase's zone. + */ + Date getDate() { + if (_date == null) { + // Date constructor will work right iff we are in the target zone + int h = 0; + int m = 0; + int s = 0; + if (date.length >= 4) { + h = date[3]; + if (date.length >= 5) { + m = date[4]; + if (date.length >= 6) { + s = date[5]; + } + } + } + _date = new Date(date[0] - 1900, date[1] - 1, date[2], + h, m, s); + } + return _date; + } + + public String toString() { + return String.valueOf(getDate().getTime()) + " " + + refFormat.format(getDate()) + " : " + ff.createFormat().format(getDate()); + } + }; + + private interface FormatFactory { + DateFormat createFormat(); + } + + TestCase[] TESTS = { + // Feb 29 2004 -- ordinary leap day + new TestCase(new int[] {2004, 2, 29}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // Feb 29 2000 -- century leap day + new TestCase(new int[] {2000, 2, 29}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // 0:00:00 Jan 1 1999 -- first second of normal year + new TestCase(new int[] {1999, 1, 1}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 23:59:59 Dec 31 1999 -- last second of normal year + new TestCase(new int[] {1999, 12, 31, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 0:00:00 Jan 1 2004 -- first second of leap year + new TestCase(new int[] {2004, 1, 1}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // 23:59:59 Dec 31 2004 -- last second of leap year + new TestCase(new int[] {2004, 12, 31, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(); + }}, false), + + // October 25, 1998 1:59:59 AM PDT -- just before DST cessation + new TestCase(new Date(909305999000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 25, 1998 1:00:00 AM PST -- just after DST cessation + new TestCase(new Date(909306000000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // April 4, 1999 1:59:59 AM PST -- just before DST onset + new TestCase(new int[] {1999, 4, 4, 1, 59, 59}, + TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // April 4, 1999 3:00:00 AM PDT -- just after DST onset + new TestCase(new Date(923220000000L), TimeZone.getTimeZone("PST"), + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 4, 1582 11:59:59 PM PDT -- just before Gregorian change + new TestCase(new int[] {1582, 10, 4, 23, 59, 59}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + + // October 15, 1582 12:00:00 AM PDT -- just after Gregorian change + new TestCase(new int[] {1582, 10, 15, 0, 0, 0}, null, + new FormatFactory() { public DateFormat createFormat() { + return DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + }}, false), + }; + + public void TestDateFormatRoundTrip() { + avail = DateFormat.getAvailableLocales(); + logln("DateFormat available locales: " + avail.length); + logln("Default TimeZone: " + + (defaultZone = TimeZone.getDefault()).getID()); + + if (random || initialDate != null) { + if (RANDOM == null) { + // Need this for sparse coverage to reduce combinatorial explosion, + // even for non-random looped testing (i.e., with explicit date but + // not pattern or locale). + RANDOM = new Random(FIXED_SEED); + } + loopedTest(); + } else { + for (int i=0; i= 0 && random < 24 && TEST_TABLE[i]) { + TEST_TABLE[i] = false; + ++i; + } + } + } + + int itable = 0; + for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getDateInstance(style, loc)); + } + + for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getTimeInstance(style, loc), true); + } + + for (int dstyle=DateFormat.FULL; dstyle<=DateFormat.SHORT; ++dstyle) { + for (int tstyle=DateFormat.FULL; tstyle<=DateFormat.SHORT; ++tstyle) { + if (TEST_TABLE[itable++]) + doTest(loc, DateFormat.getDateTimeInstance(dstyle, tstyle, loc)); + } + } + } + + void doTest(Locale loc, DateFormat fmt) { doTest(loc, fmt, false); } + + void doTest(Locale loc, DateFormat fmt, boolean timeOnly) { + doTest(loc, fmt, timeOnly, initialDate != null ? initialDate : generateDate()); + } + + void doTest(Locale loc, DateFormat fmt, boolean timeOnly, Date date) { + // Skip testing with the JapaneseImperialCalendar which + // doesn't support the Gregorian year semantices with 'y'. + if (fmt.getCalendar().getClass().getName().equals("java.util.JapaneseImperialCalendar")) { + return; + } + + String pat = ((SimpleDateFormat)fmt).toPattern(); + String deqPat = dequotePattern(pat); // Remove quoted elements + + boolean hasEra = (deqPat.indexOf("G") != -1); + boolean hasZone = (deqPat.indexOf("z") != -1); + + Calendar cal = fmt.getCalendar(); + + // Because patterns contain incomplete data representing the Date, + // we must be careful of how we do the roundtrip. We start with + // a randomly generated Date because they're easier to generate. + // From this we get a string. The string is our real starting point, + // because this string should parse the same way all the time. Note + // that it will not necessarily parse back to the original date because + // of incompleteness in patterns. For example, a time-only pattern won't + // parse back to the same date. + + try { + for (int i=0; i 0) d[loop] = fmt.parse(s[loop-1]); + s[loop] = fmt.format(d[loop]); + + if (loop > 0) { + if (smatch == 0) { + boolean match = s[loop].equals(s[loop-1]); + if (smatch == 0) { + if (match) smatch = loop; + } + else if (!match) { + // This should never happen; if it does, fail. + smatch = -1; + error = "FAIL: String mismatch after match"; + } + } + + if (dmatch == 0) { + boolean match = d[loop].getTime() == d[loop-1].getTime(); + if (dmatch == 0) { + if (match) dmatch = loop; + } + else if (!match) { + // This should never happen; if it does, fail. + dmatch = -1; + error = "FAIL: Date mismatch after match"; + } + } + + if (smatch != 0 && dmatch != 0) break; + } + } + // At this point loop == DEPTH if we've failed, otherwise loop is the + // max(smatch, dmatch), that is, the index at which we have string and + // date matching. + + // Date usually matches in 2. Exceptions handled below. + int maxDmatch = 2; + int maxSmatch = 1; + if (dmatch > maxDmatch) { + // Time-only pattern with zone information and a starting date in PST. + if (timeOnly && hasZone && fmt.getTimeZone().inDaylightTime(d[0])) { + maxDmatch = 3; + maxSmatch = 2; + } + } + + // String usually matches in 1. Exceptions are checked for here. + if (smatch > maxSmatch) { // Don't compute unless necessary + // Starts in BC, with no era in pattern + if (!hasEra && getField(cal, d[0], Calendar.ERA) == GregorianCalendar.BC) + maxSmatch = 2; + // Starts in DST, no year in pattern + else if (fmt.getTimeZone().inDaylightTime(d[0]) && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Two digit year with zone and year change and zone in pattern + else if (hasZone && + fmt.getTimeZone().inDaylightTime(d[0]) != + fmt.getTimeZone().inDaylightTime(d[dmatch]) && + getField(cal, d[0], Calendar.YEAR) != + getField(cal, d[dmatch], Calendar.YEAR) && + deqPat.indexOf("y") != -1 && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Two digit year, year change, DST changeover hour. Example: + // FAIL: Pattern: dd/MM/yy HH:mm:ss + // Date matched in 2, wanted 2 + // String matched in 2, wanted 1 + // Thu Apr 02 02:35:52.110 PST 1795 AD F> 02/04/95 02:35:52 + // P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52 + // P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52 d== s== + // The problem is that the initial time is not a DST onset day, but + // then the year changes, and the resultant parsed time IS a DST + // onset day. The hour "2:XX" makes no sense if 2:00 is the DST + // onset, so DateFormat interprets it as 1:XX (arbitrary -- could + // also be 3:XX, same problem). This results in an extra iteration + // for String match convergence. + else if (!justBeforeOnset(cal, d[0]) && justBeforeOnset(cal, d[dmatch]) && + getField(cal, d[0], Calendar.YEAR) != + getField(cal, d[dmatch], Calendar.YEAR) && + deqPat.indexOf("y") != -1 && + deqPat.indexOf("yyyy") == -1) + maxSmatch = 2; + // Another spurious failure: + // FAIL: Pattern: dd MMMM yyyy hh:mm:ss + // Date matched in 2, wanted 2 + // String matched in 2, wanted 1 + // Sun Apr 05 14:28:38.410 PDT 3998 AD F> 05 April 3998 02:28:38 + // P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38 + // P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38 d== s== + // The problem here is that with an 'hh' pattern, hour from 1-12, + // a lack of AM/PM -- that is, no 'a' in pattern, and an initial + // time in the onset hour + 12:00. + else if (deqPat.indexOf('h') >= 0 + && deqPat.indexOf('a') < 0 + && justBeforeOnset(cal, new Date(d[0].getTime() - 12*60*60*1000L)) + && justBeforeOnset(cal, d[1])) + maxSmatch = 2; + } + + if (dmatch > maxDmatch || smatch > maxSmatch + || dmatch < 0 || smatch < 0) { + StringBuffer out = new StringBuffer(); + if (error != null) { + out.append(error + '\n'); + } + out.append("FAIL: Pattern: " + pat + ", Locale: " + loc + '\n'); + out.append(" Initial date (ms): " + d[0].getTime() + '\n'); + out.append(" Date matched in " + dmatch + + ", wanted " + maxDmatch + '\n'); + out.append(" String matched in " + smatch + + ", wanted " + maxSmatch); + + for (int j=0; j<=loop && j0?" P> ":" ") + refFormat.format(d[j]) + " F> " + + escape(s[j]) + + (j>0&&d[j].getTime()==d[j-1].getTime()?" d==":"") + + (j>0&&s[j].equals(s[j-1])?" s==":"")); + } + errln(escape(out.toString())); + } + } + } + catch (ParseException e) { + errln(e.toString()); + } + } + + /** + * Return a field of the given date + */ + static int getField(Calendar cal, Date d, int f) { + // Should be synchronized, but we're single threaded so it's ok + cal.setTime(d); + return cal.get(f); + } + + /** + * Return true if the given Date is in the 1 hour window BEFORE the + * change from STD to DST for the given Calendar. + */ + static final boolean justBeforeOnset(Calendar cal, Date d) { + return nearOnset(cal, d, false); + } + + /** + * Return true if the given Date is in the 1 hour window AFTER the + * change from STD to DST for the given Calendar. + */ + static final boolean justAfterOnset(Calendar cal, Date d) { + return nearOnset(cal, d, true); + } + + /** + * Return true if the given Date is in the 1 hour (or whatever the + * DST savings is) window before or after the onset of DST. + */ + static boolean nearOnset(Calendar cal, Date d, boolean after) { + cal.setTime(d); + if ((cal.get(Calendar.DST_OFFSET) == 0) == after) { + return false; + } + int delta; + try { + delta = ((SimpleTimeZone) cal.getTimeZone()).getDSTSavings(); + } catch (ClassCastException e) { + delta = 60*60*1000; // One hour as ms + } + cal.setTime(new Date(d.getTime() + (after ? -delta : delta))); + return (cal.get(Calendar.DST_OFFSET) == 0) == after; + } + + static String escape(String s) { + StringBuffer buf = new StringBuffer(); + for (int i=0; i 0) { + try (FileOutputStream fos = + new FileOutputStream("SDFserialized.ser")) { + ObjectOutputStream oStream = new ObjectOutputStream(fos); + oStream.writeObject(sdf); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + try (InputStream is = + HexDumpReader.getStreamFromHexDump("SDFserialized.ser.txt")) { + ObjectInputStream iStream = new ObjectInputStream(is); + sdf1 = (SimpleDateFormat)iStream.readObject(); + } + + DateFormatSymbols dfs = sdf.getDateFormatSymbols(); + DateFormatSymbols dfs1 = sdf1.getDateFormatSymbols(); + System.out.println(sdf + "," + sdf.toPattern()); + System.out.println(sdf1 + "," + sdf1.toPattern()); + + // time zone display names should not be a part of this + // compatibility test. See 4112924 and 4282899. + dfs.setZoneStrings(dfs1.getZoneStrings()); + // localPatternChars should not be a part of this + // compatibility test. See 4322313. + dfs.setLocalPatternChars(dfs1.getLocalPatternChars()); + sdf.setDateFormatSymbols(dfs); + + // decimal format symbols should not be part of this + // compatibility test - old decimal format symbols get filled + // in with the root locale (4290801) + DecimalFormat df1 = (DecimalFormat) sdf1.getNumberFormat(); + df1.setDecimalFormatSymbols(df.getDecimalFormatSymbols()); + + if (!dfs.equals(dfs1)) { + err = true; + System.err.println( + "Error: serialized DateFormatSymbols is different"); + } + if (!sdf.equals(sdf1)) { + err = true; + System.err.println( + "Error: serialized SimpleDateFormat is different"); + } + if (err) { + throw new Exception("Serialization failed."); + } + } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/DateFormatTest.java b/jdk/test/java/text/Format/DateFormat/DateFormatTest.java new file mode 100644 index 00000000000..c4f148f3d77 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DateFormatTest.java @@ -0,0 +1,1207 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571 + * @summary test DateFormat and SimpleDateFormat. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatTest + */ + +import java.util.*; +import java.text.*; +import static java.util.GregorianCalendar.*; + +public class DateFormatTest extends IntlTest +{ + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new DateFormatTest().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } + + // Test 4 digit year parsing with pattern "yy" + @SuppressWarnings("deprecation") + public void TestYearParsing() + { + String str = "7/Sep/2001"; + Date exp = new Date(2001-1900, SEPTEMBER, 7); + String pat = "d/MMM/yy"; + SimpleDateFormat sdf = new SimpleDateFormat(pat, Locale.US); + try { + Date d = sdf.parse(str); + logln(str + " parses with " + pat + " to " + d); + if (d.getTime() != exp.getTime()) { + errln("FAIL: Expected " + exp); + } + } + catch (ParseException e) { + errln(str + " parse fails with " + pat); + } + } + + // Test written by Wally Wedel and emailed to me. + public void TestWallyWedel() + { + /* + * Instantiate a TimeZone so we can get the ids. + */ + TimeZone tz = new SimpleTimeZone(7,""); + /* + * Computational variables. + */ + int offset, hours, minutes; + /* + * Instantiate a SimpleDateFormat set up to produce a full time + zone name. + */ + SimpleDateFormat sdf = new SimpleDateFormat("zzzz"); + /* + * A String array for the time zone ids. + */ + String[] ids = TimeZone.getAvailableIDs(); + /* + * How many ids do we have? + */ + logln("Time Zone IDs size: " + ids.length); + /* + * Column headings (sort of) + */ + logln("Ordinal ID offset(h:m) name"); + /* + * Loop through the tzs. + */ + Date today = new Date(); + Calendar cal = Calendar.getInstance(); + for (int i = 0; i < ids.length; i++) { + // logln(i + " " + ids[i]); + TimeZone ttz = TimeZone.getTimeZone(ids[i]); + // offset = ttz.getRawOffset(); + cal.setTimeZone(ttz); + cal.setTime(today); + offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); + // logln(i + " " + ids[i] + " offset " + offset); + char sign = '+'; + if (offset < 0) { sign = '-'; offset = -offset; } + hours = offset/3600000; + minutes = (offset%3600000)/60000; + String dstOffset = "" + sign + (hours < 10 ? "0" : "") + + hours + ':' + (minutes < 10 ? "0" : "") + minutes; + /* + * Instantiate a date so we can display the time zone name. + */ + sdf.setTimeZone(ttz); + /* + * Format the output. + */ + StringBuffer tzS = new StringBuffer(); + sdf.format(today,tzS, new FieldPosition(0)); + String fmtOffset = tzS.toString(); + String fmtDstOffset = null; + if (fmtOffset.startsWith("GMT")) + { + fmtDstOffset = fmtOffset.substring(3); + } + /* + * Show our result. + */ + boolean ok = fmtDstOffset == null || fmtDstOffset.equals(dstOffset); + if (ok) + { + logln(i + " " + ids[i] + " " + dstOffset + + " " + fmtOffset + + (fmtDstOffset != null ? " ok" : " ?")); + } + else + { + errln(i + " " + ids[i] + " " + dstOffset + + " " + fmtOffset + " *** FAIL ***"); + } + } + } + + // Test equals + public void TestEquals() + { + DateFormat fmtA = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL); + + DateFormat fmtB = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL); + + if (!fmtA.equals(fmtB)) { + errln("FAIL"); + } + } + + // Check out some specific parsing problem + @SuppressWarnings("deprecation") + public void TestTwoDigitYearDSTParse() + { + SimpleDateFormat fullFmt = + new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); + + //DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL, + // Locale.ENGLISH); + SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yy h:mm:ss 'o''clock' a z", + Locale.ENGLISH); + //Date date = new Date(2004-1900, Calendar.APRIL, 3, 2, 20, 47); + //logln(fmt.format(date)); // This shows what the current locale format is + //logln(((SimpleDateFormat)fmt).toPattern()); + TimeZone save = TimeZone.getDefault(); + TimeZone PST = TimeZone.getTimeZone("PST"); + String s = "03-Apr-04 2:20:47 o'clock AM PST"; + int hour = 2; + try { + TimeZone.setDefault(PST); + Date d = fmt.parse(s); + logln(s + " P> " + fullFmt.format(d)); + if (d.getHours() != hour) { + errln("FAIL: Should parse to hour " + hour); + } + } + catch (ParseException e) { errln("FAIL: " + e.getMessage()); } + finally { + TimeZone.setDefault(save); + } + } + + static String escape(String s) + { + StringBuilder buf = new StringBuilder(); + for (int i=0; i> 12)); + buf.append(Integer.toHexString((c & 0x0F00) >> 8)); + buf.append(Integer.toHexString((c & 0x00F0) >> 4)); + buf.append(Integer.toHexString(c & 0x000F)); + } + } + return buf.toString(); + } + + // Test field position return values + static String fieldNames[] = { + "ERA_FIELD", "YEAR_FIELD", "MONTH_FIELD", + "WEEK_OF_YEAR_FIELD", "WEEK_OF_MONTH_FIELD", "DATE_FIELD", + "DAY_OF_YEAR_FIELD", "DAY_OF_WEEK_FIELD", "DAY_OF_WEEK_IN_MONTH_FIELD", + "AM_PM_FIELD", "HOUR0_FIELD", "HOUR1_FIELD", + "HOUR_OF_DAY0_FIELD", "HOUR_OF_DAY1_FIELD", + "MINUTE_FIELD", "SECOND_FIELD", + "MILLISECOND_FIELD", "TIMEZONE_FIELD", + }; + static int fieldIDs[] = { + DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD, + DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.DATE_FIELD, + DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD, + DateFormat.AM_PM_FIELD, DateFormat.HOUR0_FIELD, DateFormat.HOUR1_FIELD, + DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.HOUR_OF_DAY1_FIELD, + DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD, + DateFormat.MILLISECOND_FIELD, DateFormat.TIMEZONE_FIELD, + }; + + /** + * Bug 4089987 + */ + public void TestFieldPosition() + { + DateFormat[] dateFormats = { + DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL, + Locale.US), + + DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.FRANCE), + new SimpleDateFormat("G, y, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"), + new SimpleDateFormat("G, yy, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"), + new SimpleDateFormat( "GGGG, yyyy, MMMM, dddd, kkkk, HHHH, mmmm, ssss, " + + "SSSS, EEEE, DDDD, " + + "FFFF, wwww, WWWW, aaaa, hhhh, KKKK, zzzz") + }; + String[] expected = + { + "", "1997", "August", "", "", "13", "", "Wednesday", "", + "PM", "", "2", "", "", "34", "12", "", "PDT", + + "", "1997", "ao\u00FBt", "", "", "13", "", "mercredi", "", "", + "", "", "14", "", "34", "", "", "PDT" /*"GMT-07:00"*/, + + "AD", "1997", "8", "33", "3", "13", "225", "Wed", "2", "PM", + "2", "2", "14", "14", "34", "12", "513", "PDT", + + "AD", "97", "8", "33", "3", "13", "225", "Wed", "2", "PM", + "2", "2", "14", "14", "34", "12", "513", "PDT", + + "AD", "1997", "August", "0033", "0003", "0013", "0225", + "Wednesday", "0002", "PM", "0002", "0002", "0014", "0014", + "0034", "0012", "0513", "Pacific Daylight Time", + }; + Date someDate = new Date(871508052513L); + TimeZone PST = TimeZone.getTimeZone("PST"); + for (int j = 0, exp = 0; j < dateFormats.length; ++j) { + DateFormat df = dateFormats[j]; + if (!(df instanceof SimpleDateFormat)) { + continue; + } + df.setTimeZone(PST); + logln(" Pattern = " + ((SimpleDateFormat)df).toPattern()); + logln(" Result = " + df.format(someDate)); + for (int i = 0; i < fieldIDs.length; ++i) + { + String field = getFieldText(df, fieldIDs[i], someDate); + if (!field.equals(expected[exp])) { + errln("FAIL: field #" + i + " " + fieldNames[i] + " = \"" + + escape(field) + "\", expected \"" + escape(expected[exp]) + "\""); + } + ++exp; + } + } + } + // get the string value for the given field for the given date + static String getFieldText(DateFormat df, int field, Date date) + { + StringBuffer buffer = new StringBuffer(); + FieldPosition pos = new FieldPosition(field); + df.format(date, buffer, pos); + return buffer.toString().substring(pos.getBeginIndex(), + pos.getEndIndex()); + } + + // Test parsing of partial strings + @SuppressWarnings("deprecation") + public void TestPartialParse994() + { + SimpleDateFormat f = new SimpleDateFormat(); + Calendar cal = new GregorianCalendar(2014 - 80, JANUARY, 1); + f.set2DigitYearStart(cal.getTime()); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", new Date(97, 1-1, 17, 10, 11, 42)); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null); + } + + void tryPat994(SimpleDateFormat format, String pat, String str, Date expected) + { + logln("Pattern \"" + pat + "\" String \"" + str + "\""); + try { + format.applyPattern(pat); + Date date = format.parse(str); + String f = format.format(date); + logln(" parse(" + str + ") -> " + date.toString()); + logln(" format -> " + f); + if (expected == null || + !date.equals(expected)) { + errln("FAIL: Expected " + expected); + } + if (!f.equals(str)) { + errln("FAIL: Expected " + str); + } + } + catch(ParseException e) { + logln("ParseException: " + e.getMessage()); + if (expected != null) { + errln("FAIL: Expected " + expected); + } + } + catch(Exception e) { + errln("*** Exception:"); + e.printStackTrace(); + } + } + + // Test pattern with runs things together + public void TestRunTogetherPattern985() + { + String format = "yyyyMMddHHmmssSSS"; + String now, then; + + SimpleDateFormat formatter = new SimpleDateFormat(format); + + Date date1 = new Date(); + now = formatter.format(date1); + + logln(now); + + ParsePosition pos = new ParsePosition(0); + + Date date2 = formatter.parse(now, pos); + if (date2 == null) { + then = "Parse stopped at " + pos.getIndex(); + } else { + then = formatter.format(date2); + } + + logln(then); + + if (!date2.equals(date1)) { + errln("FAIL"); + } + } + + // Test patterns which run numbers together + @SuppressWarnings("deprecation") + public void TestRunTogetherPattern917() + { + SimpleDateFormat fmt; + String myDate; + + fmt = new SimpleDateFormat( "yyyy/MM/dd" ); + myDate = "1997/02/03"; + _testIt917( fmt, myDate, new Date(97, 2-1, 3) ); + + fmt = new SimpleDateFormat( "yyyyMMdd" ); + myDate = "19970304"; + _testIt917( fmt, myDate, new Date(97, 3-1, 4) ); + + } + void _testIt917( SimpleDateFormat fmt, String str, Date expected ) + { + logln( "pattern=" + fmt.toPattern() + " string=" + str ); + + Object o; + try { + o = fmt.parseObject( str ); + } catch( ParseException e ) { + e.printStackTrace(); + return; + } + logln( "Parsed object: " + o ); + if (!o.equals(expected)) { + errln("FAIL: Expected " + expected); + } + + String formatted = fmt.format( o ); + logln( "Formatted string: " + formatted ); + if (!formatted.equals(str)) { + errln("FAIL: Expected " + str); + } + } + + // Test Czech month formatting -- this can cause a problem because the June and + // July month names share a common prefix. + @SuppressWarnings("deprecation") + public void TestCzechMonths459() + { + // Use Czech, which has month names with shared prefixes for June and July + DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, new Locale("cs", "", "")); + //((SimpleDateFormat)fmt).applyPattern("MMMM d yyyy"); + logln("Pattern " + ((SimpleDateFormat)fmt).toPattern()); + + Date june = new Date(97, Calendar.JUNE, 15); + Date july = new Date(97, Calendar.JULY, 15); + + String juneStr = fmt.format(june); + String julyStr = fmt.format(july); + + try { + logln("format(June 15 1997) = " + juneStr); + Date d = fmt.parse(juneStr); + String s = fmt.format(d); + int month = d.getMonth(); + logln(" -> parse -> " + s + " (month = " + month + ")"); + if (month != JUNE) { + errln("FAIL: Month should be June"); + } + + logln("format(July 15 1997) = " + julyStr); + d = fmt.parse(julyStr); + s = fmt.format(d); + month = d.getMonth(); + logln(" -> parse -> " + s + " (month = " + month + ")"); + if (month != JULY) { + errln("FAIL: Month should be July"); + } + } + catch (ParseException e) { + errln("Exception: " + e); + } + } + + // Test big D (day of year) versus little d (day of month) + @SuppressWarnings("deprecation") + public void TestLetterDPattern212() + { + String dateString = "1995-040.05:01:29"; + String bigD = "yyyy-DDD.hh:mm:ss"; + String littleD = "yyyy-ddd.hh:mm:ss"; + Date expLittleD = new Date(95, 0, 1, 5, 1, 29); + Date expBigD = new Date(expLittleD.getTime() + 39*24*3600000L); // 39 days + expLittleD = expBigD; // Expect the same, with default lenient parsing + logln( "dateString= " + dateString ); + SimpleDateFormat formatter = new SimpleDateFormat(bigD); + ParsePosition pos = new ParsePosition(0); + Date myDate = formatter.parse( dateString, pos ); + logln("Using " + bigD + " -> " + myDate); + if (myDate.getTime() != expBigD.getTime()) { + errln("FAIL: Expected " + expBigD + " got " + myDate); + } + + formatter = new SimpleDateFormat(littleD); + pos = new ParsePosition(0); + myDate = formatter.parse( dateString, pos ); + logln("Using " + littleD + " -> " + myDate); + if (myDate.getTime() != expLittleD.getTime()) { + errln("FAIL: Expected " + expLittleD + " got " + myDate); + } + } + + // Test the 'G' day of year pattern + @SuppressWarnings("deprecation") + public void TestDayOfYearPattern195() + { + Date today = new Date(); + Date expected = new Date(today.getYear(), today.getMonth(), today.getDate()); + + logln("Test Date: " + today); + + SimpleDateFormat sdf = + (SimpleDateFormat)SimpleDateFormat.getDateInstance(); + + tryPattern(sdf, today, null, expected); + tryPattern(sdf, today, "G yyyy DDD", expected); + } + + void tryPattern(SimpleDateFormat sdf, Date d, String pattern, Date expected) + { + if (pattern != null) { + sdf.applyPattern(pattern); + } + logln("pattern: " + sdf.toPattern()); + + String formatResult = sdf.format(d); + logln(" format -> " + formatResult); + try { + Date d2 = sdf.parse(formatResult); + logln(" parse(" + formatResult + ") -> " + d2); + if (d2.getTime() != expected.getTime()) { + errln("FAIL: Expected " + expected); + } + String format2 = sdf.format(d2); + logln(" format -> " + format2); + if (!formatResult.equals(format2)) { + errln("FAIL: Round trip drift"); + } + } + catch(Exception e) { + errln("Error: " + e.getMessage()); + } + } + + // Test a pattern with single quotes + @SuppressWarnings("deprecation") + public void TestQuotePattern161() + { + // This pattern used to end in " zzz" but that makes this test zone-dependent + SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mm:ss a zzz"); + Date currentTime_1 = new Date(97, Calendar.AUGUST, 13, 10, 42, 28); + String dateString = formatter.format(currentTime_1); + String exp = "08/13/1997 at 10:42:28 AM "; + logln("format(" + currentTime_1 + ") = " + dateString); + if (!dateString.regionMatches(0, exp, 0, exp.length())) { + errln("FAIL: Expected " + exp); + } + } + + // Test the parsing of bad input strings + /** Demonstrates a number of bugs in DateFormat.parse(String) where + * either StringIndexOutOfBoundsException is thrown or null is + * returned instead of ParseException. To reproduce, run this program + * and notice all the "SHOULD NOT HAPPEN" errors. Note also that the + * 1 line that should be correct is off by 100 years. (In this day + * and age, no one would assume that 1/1/00 is Jan 1 1900.) + **/ + public void TestBadInput135() + { + int looks[] = { DateFormat.SHORT, DateFormat.MEDIUM, + DateFormat.LONG, DateFormat.FULL }; + String strings[] = { "Mar 15", "Mar 15 1997", "asdf", + "3/1/97 1:23:", "3/1/00 1:23:45 AM" }; + DateFormat full = DateFormat.getDateTimeInstance(DateFormat.LONG, + DateFormat.LONG); + String expected = "March 1, 2000 1:23:45 AM "; + for ( int i = 0; i < strings.length; ++i ){ + String text = strings[i]; + for ( int j = 0; j < looks.length; ++j ){ + int dateLook = looks[j]; + for ( int k = 0; k < looks.length; ++k ){ + int timeLook = looks[k]; + DateFormat df = DateFormat.getDateTimeInstance(dateLook, timeLook); + String prefix = text + ", " + dateLook + "/" + timeLook + ": "; + try { + Date when = df.parse(text); + if ( when == null ){ + errln(prefix + + "SHOULD NOT HAPPEN: parse returned null."); + continue; + } + String format = full.format(when); + logln(prefix + "OK: " + format); + // Only match the start -- not the zone, which could vary + if (!format.regionMatches(0, expected, 0, expected.length())) { + errln("FAIL: Expected " + expected); + } + } + catch ( ParseException e ){ + //errln(prefix + e); // This is expected. + } + catch ( StringIndexOutOfBoundsException e ){ + errln(prefix + "SHOULD NOT HAPPEN: " + e); + } + } + } + } + } + + final private static String parseFormats[] = + { + "MMMM d, yyyy", // january 1, 1970 or jan 1, 1970 + "MMMM d yyyy", // january 1 1970 or jan 1 1970 + "M/d/yy", // 1/1/70 + "d MMMM, yyyy", // 1 january, 1970 or 1 jan, 1970 + "d MMMM yyyy", // 1 january 1970 or 1 jan 1970 + "d MMMM", // 1 january or 1 jan + "MMMM d", // january 1 or jan 1 + "yyyy", // 1970 + "h:mm a MMMM d, yyyy" // Date and Time + }; + final private static String inputStrings[] = + { + "bogus string", null, null, null, null, null, null, null, null, null, + "April 1, 1997", "April 1, 1997", null, null, null, null, null, "April 1", null, null, + "Jan 1, 1970", "January 1, 1970", null, null, null, null, null, "January 1", null, null, + "Jan 1 2037", null, "January 1 2037", null, null, null, null, "January 1", null, null, + "1/1/70", null, null, "1/1/70", null, null, null, null, "0001", null, + "5 May 1997", null, null, null, null, "5 May 1997", "5 May", null, "0005", null, + "16 May", null, null, null, null, null, "16 May", null, "0016", null, + "April 30", null, null, null, null, null, null, "April 30", null, null, + "1998", null, null, null, null, null, null, null, "1998", null, + "1", null, null, null, null, null, null, null, "0001", null, // Bug620 + "3:00 pm Jan 1, 1997", null, null, null, null, null, null, null, "0003", "3:00 PM January 1, 1997", + }; + // More testing of the parsing of bad input + @SuppressWarnings("UnusedAssignment") + public void TestBadInput135a() + { + SimpleDateFormat dateParse = new SimpleDateFormat(); + String s; + Date date; + int PFLENGTH = parseFormats.length; + + dateParse.applyPattern("d MMMM, yyyy"); + dateParse.setTimeZone(TimeZone.getDefault()); + s = "not parseable"; + logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern()); + try { + date = dateParse.parse(s); + errln("FAIL: Expected exception during parse"); + } catch (Exception ex) { + logln("Exception during parse: " + ex); // This is expected + } + + for (int i=0; i " + d.toString()); + if (d.getTime() != expected.getTime()) { + errln("FAIL: Expected " + expected); + } + } catch (ParseException e) { + errln("FAIL: Got exception"); + } + } + + // Test behavior of DateFormat with applied time zone + public void TestDateFormatZone061() + { + Date date; + DateFormat formatter; + + // 25-Mar-97 00:00:00 GMT + date = new Date( 859248000000L ); + logln( "Date 1997/3/25 00:00 GMT: " + date ); + formatter = new SimpleDateFormat("dd-MMM-yyyyy HH:mm", Locale.UK); + formatter.setTimeZone( TimeZone.getTimeZone( "GMT" ) ); + + String temp = formatter.format( date ); + logln( "Formatted in GMT to: " + temp ); + + /* Parse date string */ + try { + Date tempDate = formatter.parse( temp ); + logln( "Parsed to: " + tempDate ); + if (tempDate.getTime() != date.getTime()) { + errln("FAIL: Expected " + date); + } + } + catch( Throwable t ) { + errln( "Date Formatter throws: " + + t.toString() ); + } + } + + // Make sure DateFormat uses the correct zone. + public void TestDateFormatZone146() + { + TimeZone saveDefault = TimeZone.getDefault(); + + try { + TimeZone thedefault = TimeZone.getTimeZone("GMT"); + TimeZone.setDefault(thedefault); + // java.util.Locale.setDefault(new java.util.Locale("ar", "", "")); + + // check to be sure... its GMT all right + TimeZone testdefault = TimeZone.getDefault(); + String testtimezone = testdefault.getID(); + if (testtimezone.equals("GMT")) { + logln("Test timezone = " + testtimezone); + } else { + errln("Test timezone should be GMT, not " + testtimezone); + } + + // now try to use the default GMT time zone + GregorianCalendar greenwichcalendar = + new GregorianCalendar(1997, 3, 4, 23, 0); + //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault()); + //greenwichcalendar.set(1997, 3, 4, 23, 0); + // try anything to set hour to 23:00 !!! + greenwichcalendar.set(Calendar.HOUR_OF_DAY, 23); + // get time + Date greenwichdate = greenwichcalendar.getTime(); + // format every way + String[] DATA = { + "simple format: ", "04/04/97 23:00 GMT", + "MM/dd/yy HH:mm z", + "full format: ", "Friday, April 4, 1997 11:00:00 o'clock PM GMT", + "EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z", + "long format: ", "April 4, 1997 11:00:00 PM GMT", + "MMMM d, yyyy h:mm:ss a z", + "default format: ", "04-Apr-97 11:00:00 PM", + "dd-MMM-yy h:mm:ss a", + "short format: ", "4/4/97 11:00 PM", + "M/d/yy h:mm a", + }; + + for (int i=0; i4 y's produces just "2001" until 1.3.1. This + // was fixed in 1.4. + String expected = + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000002001\u5e74"; + SimpleDateFormat sdf = new SimpleDateFormat(pat); + String s = sdf.format(new Date(2001-1900, Calendar.JANUARY, 1)); + if (!expected.equals(s)) { + errln("wrong format result: expected="+expected+", got="+s); + } + Date longday = sdf.parse(s); + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(longday); + if (cal.get(YEAR) != 2001) { + errln("wrong parse result: expected=2001, got=" + cal.get(YEAR)); + } + } catch (Exception e) { + throw e; + } finally { + // Restore the initial time zone + TimeZone.setDefault(initialTimeZone); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java new file mode 100644 index 00000000000..bc37d4f7fba --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 + * @summary test International Date Format + * @bug 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestDateFormat + * @key randomness + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestDateFormat extends IntlTest { + // Values in milliseconds (== Date) + private static final long ONESECOND = 1000; + private static final long ONEMINUTE = 60 * ONESECOND; + private static final long ONEHOUR = 60 * ONEMINUTE; + private static final long ONEDAY = 24 * ONEHOUR; + private static final double ONEYEAR = 365.25 * ONEDAY; // Approximate + + // EModes + private static final byte GENERIC = 0; + private static final byte TIME = GENERIC + 1; + private static final byte DATE = TIME + 1; + private static final byte DATE_TIME = DATE + 1; + + private DateFormat fFormat = DateFormat.getInstance(); + private String fTestName = new String("getInstance"); + private int fLimit = 3; // How many iterations it should take to reach convergence + + public static void main(String[] args) throws Exception { + new IntlTestDateFormat().run(args); + } + + public void TestLocale() { + localeTest(Locale.getDefault(), "Default Locale"); + } + + // This test does round-trip testing (format -> parse -> format -> parse -> etc.) of DateFormat. + public void localeTest(final Locale locale, final String localeName) { + int timeStyle, dateStyle; + + // For patterns including only time information and a timezone, it may take + // up to three iterations, since the timezone may shift as the year number + // is determined. For other patterns, 2 iterations should suffice. + fLimit = 3; + + for(timeStyle = 0; timeStyle < 4; timeStyle++) { + fTestName = new String("Time test " + timeStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getTimeInstance(timeStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest time getTimeInstance exception"); + throw e; + } + TestFormat(); + } + + fLimit = 2; + + for(dateStyle = 0; dateStyle < 4; dateStyle++) { + fTestName = new String("Date test " + dateStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getDateInstance(dateStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest date getTimeInstance exception"); + throw e; + } + TestFormat(); + } + + for(dateStyle = 0; dateStyle < 4; dateStyle++) { + for(timeStyle = 0; timeStyle < 4; timeStyle++) { + fTestName = new String("DateTime test " + dateStyle + "/" + timeStyle + " (" + localeName + ")"); + try { + fFormat = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + catch(StringIndexOutOfBoundsException e) { + errln("FAIL: localeTest date/time getDateTimeInstance exception"); + throw e; + } + TestFormat(); + } + } + } + + public void TestFormat() { + if (fFormat == null) { + errln("FAIL: DateFormat creation failed"); + return; + } + // logln("TestFormat: " + fTestName); + Date now = new Date(); + tryDate(new Date(0)); + tryDate(new Date((long) 1278161801778.0)); + tryDate(now); + // Shift 6 months into the future, AT THE SAME TIME OF DAY. + // This will test the DST handling. + tryDate(new Date(now.getTime() + 6*30*ONEDAY)); + + Date limit = new Date(now.getTime() * 10); // Arbitrary limit + for (int i=0; i<2; ++i) + // tryDate(new Date(floor(randDouble() * limit))); + tryDate(new Date((long) (randDouble() * limit.getTime()))); + } + + private void describeTest() { + if (fFormat == null) { + errln("FAIL: no DateFormat"); + return; + } + + // Assume it's a SimpleDateFormat and get some info + SimpleDateFormat s = (SimpleDateFormat) fFormat; + logln(fTestName + " Pattern " + s.toPattern()); + } + + private void tryDate(Date theDate) { + final int DEPTH = 10; + Date[] date = new Date[DEPTH]; + StringBuffer[] string = new StringBuffer[DEPTH]; + + int dateMatch = 0; + int stringMatch = 0; + boolean dump = false; + int i; + for (i=0; i 0) { + if (dateMatch == 0 && date[i] == date[i-1]) dateMatch = i; + else if (dateMatch > 0 && date[i] != date[i-1]) { + describeTest(); + errln("********** FAIL: Date mismatch after match."); + dump = true; + break; + } + if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i; + else if (stringMatch > 0 && string[i] != string[i-1]) { + describeTest(); + errln("********** FAIL: String mismatch after match."); + dump = true; + break; + } + } + if (dateMatch > 0 && stringMatch > 0) break; + } + if (i == DEPTH) --i; + + if (stringMatch > fLimit || dateMatch > fLimit) { + describeTest(); + errln("********** FAIL: No string and/or date match within " + fLimit + " iterations."); + dump = true; + } + + if (dump) { + for (int k=0; k<=i; ++k) { + logln("" + k + ": " + date[k] + " F> " + string[k] + " P> "); + } + } + } + + // Return a random double from 0.01 to 1, inclusive + private double randDouble() { + // Assume 8-bit (or larger) rand values. Also assume + // that the system rand() function is very poor, which it always is. + // double d; + // int i; + // do { + // for (i=0; i < sizeof(double); ++i) + // { + // char poke = (char*)&d; + // poke[i] = (rand() & 0xFF); + // } + // } while (TPlatformUtilities.isNaN(d) || TPlatformUtilities.isInfinite(d)); + + // if (d < 0.0) d = -d; + // if (d > 0.0) + // { + // double e = floor(log10(d)); + // if (e < -2.0) d *= pow(10.0, -e-2); + // else if (e > -1.0) d /= pow(10.0, e+1); + // } + // return d; + Random rand = new Random(); + return rand.nextDouble(); + } + + public void TestAvailableLocales() { + final Locale[] locales = DateFormat.getAvailableLocales(); + long count = locales.length; + logln("" + count + " available locales"); + if (locales != null && count != 0) { + StringBuffer all = new StringBuffer(); + for (int i=0; i 0) { + throw new RuntimeException("FAILED: " + errors + " error(s)"); + } + } + + private static void test(Locale locale) { + Locale.setDefault(locale); + + // Tests with the Japanese imperial calendar + Locale calendarLocale = new Locale("ja", "JP", "JP"); + testRoundTrip(calendarLocale); + testRoundTripSimple(calendarLocale, + locale == Locale.ENGLISH ? JAPANESE_EN : JAPANESE_JA); + testParseExceptions(calendarLocale, + locale == Locale.ENGLISH ? EXCEPTION_JAPANESE_EN : EXCEPTION_JAPANESE_JA); + + // Tests with the Thai Buddhist calendar + calendarLocale = new Locale("th", "TH"); + testRoundTrip(calendarLocale); + testRoundTripSimple(calendarLocale, + locale == Locale.ENGLISH ? BUDDHIST_EN : BUDDHIST_JA); + } + + private static void testRoundTrip(Locale calendarLocale) { + DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, + DateFormat.FULL, + calendarLocale); + + long t = System.currentTimeMillis(); + t = (t / 1000) * 1000; // discard milliseconds + testRoundTrip(df, new Date(t)); + + // H1.8.9 + testRoundTrip(df, new Date(1989-1900, AUGUST, 9)); + + // H17.6.13 + testRoundTrip(df, new Date(2005-1900, JUNE, 13)); + } + + private static void testRoundTrip(DateFormat df, Date orig) { + try { + String s = df.format(orig); + Date parsed = df.parse(s); + if (!orig.equals(parsed)) { + error("testRoundTrip: bad date: origianl: '%s', parsed '%s'%n", orig, parsed); + } + } catch (Exception e) { + error("Unexpected exception: %s%n", e); + } + } + + private static void testRoundTripSimple(Locale calendarLocale, Object[][] data) { + try { + for (Object[] item : data) { + String pattern = (String) item[0]; + String str = (String) item[1]; + Date date = (Date) item[2]; + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + Calendar cal = Calendar.getInstance(calendarLocale); + sdf.setCalendar(cal); + String s = sdf.format(date); + if (!s.equals(str)) { + error("testRoundTripSimple: Got '%s', expected '%s'%n", s, str); + } + Date d = sdf.parse(str); + if (!d.equals(date)) { + error("testRoundTripSimple: Got '%s', expected '%s'%n", d, date); + } + } + } catch (Exception e) { + error("Unexpected exception: %s%n", e); + } + } + + private static void testParseExceptions(Locale calendarLocale, Object[][] data) { + for (Object[] item : data) { + String pattern = (String) item[0]; + String str = (String) item[1]; + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + Calendar cal = Calendar.getInstance(calendarLocale); + sdf.setCalendar(cal); + sdf.setLenient(false); + try { + Date d = sdf.parse(str); + error("testParseExceptions: parsing '%s' doesn't throw a ParseException.%n", str); + } catch (ParseException e) { + // OK + } + } + } + + private static void error(String msg) { + System.out.println(msg); + errors++; + } + + private static void error(String fmt, Object... args) { + System.out.printf(fmt, args); + errors++; + } +} diff --git a/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt b/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt new file mode 100644 index 00000000000..c0ddced4fab --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt @@ -0,0 +1,173 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized DateFormatSymbols for +# DateFormatSymbolsSerializationTest. + +aced00057372001a6a6176612e746578742e53696d706c6544617465466f726d +61744243c9da9394359002000449001573657269616c56657273696f6e4f6e53 +747265616d4c001364656661756c7443656e7475727953746172747400104c6a +6176612f7574696c2f446174653b4c000a666f726d61744461746174001d4c6a +6176612f746578742f44617465466f726d617453796d626f6c733b4c00077061 +747465726e7400124c6a6176612f6c616e672f537472696e673b787200146a61 +76612e746578742e44617465466f726d6174642ca1e4c22615fc0200024c0008 +63616c656e6461727400144c6a6176612f7574696c2f43616c656e6461723b4c +000c6e756d626572466f726d61747400184c6a6176612f746578742f4e756d62 +6572466f726d61743b787200106a6176612e746578742e466f726d6174fbd8bc +12e90f184302000078707372001b6a6176612e7574696c2e477265676f726961 +6e43616c656e6461728f3dd7d6e5b0d0c10200014a0010677265676f7269616e +4375746f766572787200126a6176612e7574696c2e43616c656e646172e6ea4d +1ec8dc5b8e03000b5a000c6172654669656c647353657449000e666972737444 +61794f665765656b5a0009697354696d655365745a00076c656e69656e744900 +166d696e696d616c44617973496e46697273745765656b4900096e6578745374 +616d7049001573657269616c56657273696f6e4f6e53747265616d4a00047469 +6d655b00066669656c64737400025b495b000569735365747400025b5a4c0004 +7a6f6e657400144c6a6176612f7574696c2f54696d655a6f6e653b7870010000 +000101010000000100000002000000010000000000000000757200025b494dba +602676eab2a502000078700000001100000001000007b2000000000000000100 +0000010000000100000001000000050000000100000000000000000000000000 +00000000000000000000000000000000000000757200025b5a578f203914b85d +e20200007870000000110101010101010101010101010101010101737200186a +6176612e7574696c2e53696d706c6554696d655a6f6e65fa675d60d15ef5a603 +001049000a647374536176696e6773490006656e6444617949000c656e644461 +794f665765656b490007656e644d6f6465490008656e644d6f6e746849000765 +6e6454696d654900097261774f666673657449001573657269616c5665727369 +6f6e4f6e53747265616d490008737461727444617949000e7374617274446179 +4f665765656b49000973746172744d6f646549000a73746172744d6f6e746849 +0009737461727454696d654900097374617274596561725a000b757365446179 +6c696768745b000b6d6f6e74684c656e6774687400025b42787200126a617661 +2e7574696c2e54696d655a6f6e6531b3e9f57744aca10200014c000249447100 +7e00037870740003474d540036ee800000000000000000000000000000000000 +0000000000000000000001000000000000000000000000000000000000000000 +00000000757200025b42acf317f8060854e002000078700000000c1f1c1f1e1f +1e1f1f1e1f1e1f770800000004000000007878fffff4e2f964ac00737200176a +6176612e746578742e446563696d616c466f726d61740bff0362d872303a0200 +0b5a001b646563696d616c536570617261746f72416c7761797353686f776e42 +000c67726f7570696e6753697a654200116d696e4578706f6e656e7444696769 +747349000a6d756c7469706c69657249001573657269616c56657273696f6e4f +6e53747265616d5a00167573654578706f6e656e7469616c4e6f746174696f6e +4c000e6e6567617469766550726566697871007e00034c000e6e656761746976 +6553756666697871007e00034c000e706f73697469766550726566697871007e +00034c000e706f73697469766553756666697871007e00034c000773796d626f +6c737400204c6a6176612f746578742f446563696d616c466f726d617453796d +626f6c733b787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000701032800000003000000 +2800010000000000000001000000000178010300000000010000000100740001 +2d74000071007e001f71007e001f7372001e6a6176612e746578742e44656369 +6d616c466f726d617453796d626f6c73501d17990868939c02000f4300106465 +63696d616c536570617261746f72430005646967697443000b6578706f6e656e +7469616c43001167726f7570696e67536570617261746f724300096d696e7573 +5369676e4300116d6f6e6574617279536570617261746f724300107061747465 +726e536570617261746f724300077065724d696c6c43000770657263656e7449 +001573657269616c56657273696f6e4f6e53747265616d4300097a65726f4469 +6769744c00034e614e71007e00034c000e63757272656e637953796d626f6c71 +007e00034c0008696e66696e69747971007e00034c0012696e746c4375727265 +6e637953796d626f6c71007e00037870002e00230045002c002d002e003b2030 +0025000000010030740003efbfbd740002c2a4740003e2889e74000358585800 +0000017372000e6a6176612e7574696c2e44617465686a81014b597419030000 +78707708fffffe8f24e5cdd7787372001b6a6176612e746578742e4461746546 +6f726d617453796d626f6c73ace671c9351717c20200085b0005616d706d7374 +00135b4c6a6176612f6c616e672f537472696e673b5b00046572617371007e00 +294c00116c6f63616c5061747465726e436861727371007e00035b00066d6f6e +74687371007e00295b000b73686f72744d6f6e74687371007e00295b000d7368 +6f72745765656b6461797371007e00295b00087765656b6461797371007e0029 +5b000b7a6f6e65537472696e67737400145b5b4c6a6176612f6c616e672f5374 +72696e673b7870757200135b4c6a6176612e6c616e672e537472696e673badd2 +56e7e91d7b47020000787000000002740002414d740002504d7571007e002c00 +0000027400024243740002414474001247794d646b486d735345444677576168 +4b7a7571007e002c0000000d7400074a616e7561727974000846656272756172 +797400054d61726368740005417072696c7400034d61797400044a756e657400 +044a756c7974000641756775737474000953657074656d6265727400074f6374 +6f6265727400084e6f76656d626572740008446563656d62657271007e001f75 +71007e002c0000000d7400034a616e7400034665627400034d61727400034170 +7271007e00397400034a756e7400034a756c7400034175677400035365707400 +034f63747400034e6f7674000344656371007e001f7571007e002c0000000871 +007e001f74000353756e7400034d6f6e74000354756574000357656474000354 +68757400034672697400035361747571007e002c0000000871007e001f740006 +53756e6461797400064d6f6e646179740007547565736461797400095765646e +6573646179740008546875727364617974000646726964617974000853617475 +72646179757200145b5b4c6a6176612e6c616e672e537472696e673b324d09ad +8432e45702000078700000001d7571007e002c00000005740003505354740015 +50616369666963205374616e646172642054696d6571007e0060740015506163 +69666963204461796c696768742054696d657400035044547571007e002c0000 +0005740013416d65726963612f4c6f735f416e67656c657371007e006171007e +006071007e006271007e00637571007e002c000000057400034d53547400164d +6f756e7461696e205374616e646172642054696d6571007e00677400164d6f75 +6e7461696e204461796c696768742054696d657400034d44547571007e002c00 +00000574000e416d65726963612f44656e76657271007e006871007e00677100 +7e006971007e006a7571007e002c00000005740003504e5471007e006871007e +006771007e006871007e00677571007e002c0000000574000f416d6572696361 +2f50686f656e697871007e006871007e006771007e006871007e00677571007e +002c0000000574000343535474001543656e7472616c205374616e6461726420 +54696d6571007e007274001543656e7472616c204461796c696768742054696d +657400034344547571007e002c0000000574000f416d65726963612f43686963 +61676f71007e007371007e007271007e007471007e00757571007e002c000000 +057400034553547400154561737465726e205374616e646172642054696d6571 +007e00797400154561737465726e204461796c696768742054696d6574000345 +44547571007e002c00000005740010416d65726963612f4e65775f596f726b71 +007e007a71007e007971007e007b71007e007c7571007e002c00000005740003 +49455471007e007a71007e007971007e007a71007e00797571007e002c000000 +05740014416d65726963612f496e6469616e61706f6c697371007e007a71007e +007971007e007a71007e00797571007e002c0000000574000348535474001448 +6177616969205374616e646172642054696d6571007e008471007e008571007e +00847571007e002c00000005740010506163696669632f486f6e6f6c756c7571 +007e008571007e008471007e008571007e00847571007e002c00000005740003 +415354740014416c61736b61205374616e646172642054696d65740004414b53 +54740014416c61736b61204461796c696768742054696d65740004414b445475 +71007e002c00000005740011416d65726963612f416e63686f7261676571007e +008a71007e008b71007e008c71007e008d7571007e002c0000000574000f416d +65726963612f48616c6966617874001641746c616e746963205374616e646172 +642054696d6571007e008974001641746c616e746963204461796c6967687420 +54696d657400034144547571007e002c00000005740003434e5474001a4e6577 +666f756e646c616e64205374616e646172642054696d657400034e535474001a +4e6577666f756e646c616e64204461796c696768742054696d657400034e4454 +7571007e002c00000005740010416d65726963612f53745f4a6f686e7371007e +009771007e009871007e009971007e009a7571007e002c000000057400034543 +5474001e43656e7472616c204575726f7065616e205374616e64617264205469 +6d6574000343455474001e43656e7472616c204575726f7065616e204461796c +696768742054696d65740004434553547571007e002c0000000574000c457572 +6f70652f506172697371007e009f71007e00a071007e00a171007e00a2757100 +7e002c0000000571007e0017740013477265656e77696368204d65616e205469 +6d6571007e001771007e00a671007e00177571007e002c000000057400114166 +726963612f43617361626c616e636171007e00a671007e001771007e00a67100 +7e00177571007e002c0000000574000e417369612f4a65727573616c656d7400 +1449737261656c205374616e646172642054696d657400034953547400144973 +7261656c204461796c696768742054696d657400034944547571007e002c0000 +00057400034a53547400134a6170616e205374616e646172642054696d657100 +7e00b071007e00b171007e00b07571007e002c0000000574000a417369612f54 +6f6b796f71007e00b171007e00b071007e00b171007e00b07571007e002c0000 +00057400104575726f70652f42756368617265737474001e4561737465726e20 +4575726f7065616e205374616e646172642054696d6574000345455474001e45 +61737465726e204575726f7065616e204461796c696768742054696d65740004 +454553547571007e002c000000057400034354547400134368696e6120537461 +6e646172642054696d6571007e007271007e00bc71007e00757571007e002c00 +00000574000d417369612f5368616e6768616971007e00bc71007e007271007e +00bc71007e0075740019797979792e4d4d2e646420452068682e6d6d2e737320 +7a7a7a0a diff --git a/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java b/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java new file mode 100644 index 00000000000..9975672c806 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java @@ -0,0 +1,152 @@ +/* + * 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. + */ + +/** + * @test + * @bug 4348864 4112924 4425386 4495052 4836940 4851113 8008577 + * @summary test time zone display names in en_US locale + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneNameTest + */ + +import java.util.*; +import java.text.*; + +public class TimeZoneNameTest extends IntlTest +{ + static final String[] data = { + // Added to verify the fix for 4836940 + "N", "Antarctica/Rothera", "ROTT", "Rothera Time", "ROTT", "Rothera Time", + "N", "Asia/Tehran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time", + "N", "Iran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time", + + // Added to verify the fix for 4851113 + "N", "America/Rankin_Inlet", "CST", "Central Standard Time", "CDT", "Central Daylight Time", + "N", "Asia/Samarkand", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time", + "N", "Asia/Tashkent", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time", + "N", "Atlantic/Jan_Mayen", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "Europe/Oslo", "CET", "Central European Time", "CEST", "Central European Summer Time", + + "N", "Pacific/Honolulu", "HST", "Hawaii Standard Time", "HST", "Hawaii Standard Time", + "N", "America/Los_Angeles", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time", + "N", "US/Pacific", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time", + "N", "America/Phoenix", "MST", "Mountain Standard Time", "MST", "Mountain Standard Time", + "N", "America/Denver", "MST", "Mountain Standard Time", "MDT", "Mountain Daylight Time", + "N", "America/Chicago", "CST", "Central Standard Time", "CDT", "Central Daylight Time", + "N", "America/Indianapolis", "EST", "Eastern Standard Time", "EST", "Eastern Standard Time", + "N", "America/Montreal", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "N", "America/Toronto", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "N", "America/New_York", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time", + "S", "America/Manaus", "AMT", "Amazon Time", "AMT", "Amazon Time", + "S", "America/Campo_Grande", "AMT", "Amazon Time", "AMST", "Amazon Summer Time", + "S", "America/Bahia", "BRT", "Brasilia Time", "BRST", "Brasilia Summer Time", + "N", "America/Halifax", "AST", "Atlantic Standard Time", "ADT", "Atlantic Daylight Time", + "N", "GMT", "GMT", "Greenwich Mean Time", "GMT", "Greenwich Mean Time", + "N", "Europe/London", "GMT", "Greenwich Mean Time", "BST", "British Summer Time", + "N", "Europe/Paris", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "WET", "WET", "Western European Time", "WEST", "Western European Summer Time", + "N", "Europe/Berlin", "CET", "Central European Time", "CEST", "Central European Summer Time", + "N", "Asia/Jerusalem", "IST", "Israel Standard Time", "IDT", "Israel Daylight Time", + "N", "Europe/Helsinki", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time", + "N", "Africa/Cairo", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time", + "N", "Europe/Moscow", "MSK", "Moscow Standard Time", "MSD", "Moscow Daylight Time", + "N", "Asia/Omsk", "OMST", "Omsk Time", "OMSST", "Omsk Summer Time", + "N", "Asia/Shanghai", "CST", "China Standard Time", "CST", "China Standard Time", + "N", "Asia/Tokyo", "JST", "Japan Standard Time", "JST", "Japan Standard Time", + "N", "Japan", "JST", "Japan Standard Time", "JST", "Japan Standard Time", + "N", "Asia/Seoul", "KST", "Korea Standard Time", "KST", "Korea Standard Time", + "N", "ROK", "KST", "Korea Standard Time", "KST", "Korea Standard Time", + "S", "Australia/Darwin", "ACST", "Australian Central Standard Time (Northern Territory)", + "ACST", "Australian Central Standard Time (Northern Territory)", + "S", "Australia/Adelaide", "ACST", "Australian Central Standard Time (South Australia)", + "ACDT", "Australian Central Daylight Time (South Australia)", + "S", "Australia/Broken_Hill", "ACST", "Australian Central Standard Time (South Australia/New South Wales)", + "ACDT", "Australian Central Daylight Time (South Australia/New South Wales)", + "S", "Australia/Hobart", "AEST", "Australian Eastern Standard Time (Tasmania)", + "AEDT", "Australian Eastern Daylight Time (Tasmania)", + "S", "Australia/Brisbane", "AEST", "Australian Eastern Standard Time (Queensland)", + "AEST", "Australian Eastern Standard Time (Queensland)", + "S", "Australia/Sydney", "AEST", "Australian Eastern Standard Time (New South Wales)", + "AEDT", "Australian Eastern Daylight Time (New South Wales)", + "N", "Pacific/Guam", "ChST", "Chamorro Standard Time", + "ChST", "Chamorro Standard Time", + "N", "Pacific/Saipan", "ChST", "Chamorro Standard Time", + "ChST", "Chamorro Standard Time", + }; + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new TimeZoneNameTest().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } + + public void Test4112924() { + SimpleDateFormat lfmt = new SimpleDateFormat("zzzz"); + SimpleDateFormat sfmt = new SimpleDateFormat("z"); + + GregorianCalendar june = new GregorianCalendar(2000, Calendar.JUNE, 21); + GregorianCalendar december = new GregorianCalendar(2000, Calendar.DECEMBER, 21); + + int count = data.length; + for (int i = 0; i < count; i++) { + GregorianCalendar sol1, sol2; + + // check hemisphere + if ("N".equals(data[i++])) { + sol1 = december; + sol2 = june; + } else { + sol1 = june; + sol2 = december; + } + + TimeZone tz = TimeZone.getTimeZone(data[i++]); + lfmt.setTimeZone(tz); + sfmt.setTimeZone(tz); + + logln(tz.getID() + ": " + sfmt.format(sol1.getTime()) + ", " + lfmt.format(sol1.getTime())); + logln(tz.getID() + ": " + sfmt.format(sol2.getTime()) + ", " + lfmt.format(sol2.getTime())); + String s = sfmt.format(sol1.getTime()); + if (!data[i].equals(s)) { + errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = lfmt.format(sol1.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = sfmt.format(sol2.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + s = lfmt.format(sol2.getTime()); + if (!data[++i].equals(s)) { + errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")"); + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4097450.java b/jdk/test/java/text/Format/DateFormat/bug4097450.java new file mode 100644 index 00000000000..c70194bd877 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4097450.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4097450 + */ + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class bug4097450 +{ + public static void main(String args[]) + { + // + // Date parse requiring 4 digit year. + // + String[] dstring = {"97","1997", "97","1997","01","2001", "01","2001" + , "1", + "1","11", "11","111", "111"}; + String[] dformat = {"yy", "yy","yyyy","yyyy","yy", "yy","yyyy","yyyy" + , + "yy","yyyy","yy","yyyy", "yy","yyyy"}; + boolean[] dresult = {true, false, false, true,true, false, false, true + ,false, + false,true, false,false, false}; + SimpleDateFormat formatter; + SimpleDateFormat resultFormatter = new SimpleDateFormat("yyyy"); + + System.out.println("Format\tSource\tResult"); + System.out.println("-------\t-------\t-------"); + for (int i = 0; i < dstring.length; i++) + { + System.out.print(dformat[i] + "\t" + dstring[i] + "\t"); + formatter = new SimpleDateFormat(dformat[i]); + try { + System.out.print(resultFormatter.format(formatter.parse(dstring[ + i]))); + //if ( !dresult[i] ) System.out.print(" <-- error!"); + } + catch (ParseException exception) { + //if ( dresult[i] ) System.out.print(" <-- error!"); + System.out.print("exception --> " + exception); + } + System.out.println(); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4099975.java b/jdk/test/java/text/Format/DateFormat/bug4099975.java new file mode 100644 index 00000000000..812b4996c0f --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4099975.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4099975 + */ + +import java.text.*; +import java.util.Date; +public class bug4099975 { + public static void main (String args[]){ + DateFormatSymbols symbols = new DateFormatSymbols(); + SimpleDateFormat df = new SimpleDateFormat("E hh:mm", symbols); + System.out.println(df.toLocalizedPattern()); + symbols.setLocalPatternChars("abcdefghijklmonpqr"); // change value of field + System.out.println(df.toLocalizedPattern()); + + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4117335.java b/jdk/test/java/text/Format/DateFormat/bug4117335.java new file mode 100644 index 00000000000..6c9af2a4716 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4117335.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4117335 4432617 + */ + +import java.text.DateFormatSymbols ; +import java.util.Locale; + +public class bug4117335 { + + public static void main(String[] args) throws Exception + { + DateFormatSymbols symbols = new DateFormatSymbols(Locale.JAPAN); + String[] eras = symbols.getEras(); + System.out.println("BC = " + eras[0]); + if (!eras[0].equals(bc)) { + System.out.println("*** Should have been " + bc); + throw new Exception("Error in BC"); + } + System.out.println("AD = " + eras[1]); + if (!eras[1].equals(ad)) { + System.out.println("*** Should have been " + ad); + throw new Exception("Error in AD"); + } + String[][] zones = symbols.getZoneStrings(); + for (int i = 0; i < zones.length; i++) { + if (!"Asia/Tokyo".equals(zones[i][0])) { + continue; + } + System.out.println("Long zone name = " + zones[i][1]); + if (!zones[i][1].equals(jstLong)) { + System.out.println("*** Should have been " + jstLong); + throw new Exception("Error in long TZ name"); + } + System.out.println("Short zone name = " + zones[i][2]); + if (!zones[i][2].equals(jstShort)) { + System.out.println("*** Should have been " + jstShort); + throw new Exception("Error in short TZ name"); + } + System.out.println("Long zone name = " + zones[i][3]); + if (!zones[i][3].equals(jdtLong)) { + System.out.println("*** Should have been " + jdtLong); + throw new Exception("Error in long TZ name"); + } + System.out.println("SHORT zone name = " + zones[i][4]); + if (!zones[i][4].equals(jdtShort)) { + System.out.println("*** Should have been " + jdtShort); + throw new Exception("Error in short TZ name"); + } + } + } + + static final String bc = "\u7d00\u5143\u524d"; + static final String ad = "\u897f\u66a6"; + static final String jstLong = "\u65e5\u672c\u6a19\u6e96\u6642"; + static final String jstShort = "JST"; + static final String jdtLong = "\u65e5\u672c\u590f\u6642\u9593"; + static final String jdtShort = "JDT"; +} diff --git a/jdk/test/java/text/Format/DateFormat/bug4358730.java b/jdk/test/java/text/Format/DateFormat/bug4358730.java new file mode 100644 index 00000000000..dc448ecd767 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug4358730.java @@ -0,0 +1,84 @@ +/* + * 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 java.io.*; +import java.util.*; +import java.text.*; + +/** + * @test + * @bug 4358730 + * @library /java/text/testlib + * @summary test that confirms Zero-Padding on year. + */ + +public class bug4358730 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4358730().run(args); + } + + String[] patterns = {"y", "yy", "yyy", "yyyy", "yyyyy"}; + String[][] data = { + /* 2 A.D. */ {"2", "02", "002", "0002", "00002"}, + /* 20 A.D. */ {"20", "20", "020", "0020", "00020"}, + /* 200 A.D. */ {"200", "00", "200", "0200", "00200"}, + /* 2000 A.D. */ {"2000", "00", "2000", "2000", "02000"}, + }; + int[] year = {2, 20, 200, 2000}; + + SimpleDateFormat sdf = new SimpleDateFormat(); + int datasize = data.length; + int nPatterns = data[0].length; + + public void Test4358730() { + Locale locale = Locale.getDefault(); + if (locale.equals(new Locale("th", "TH")) || + locale.equals(new Locale("hi", "IN"))) { + return; + } + + TimeZone saveZone = TimeZone.getDefault(); + Locale saveLocale = Locale.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + Locale.setDefault(new Locale("en", "US")); + + for (int i = 0; i < datasize; i++) { + Date d = new Date(year[i]-1900, 10, 15); + for (int j = 0; j < nPatterns; j++) { + sdf.applyPattern(patterns[j]); + if (!data[i][j].equals(sdf.format(d))) { + errln("Invalid format : " + sdf.format(d) + + ", expected : " + data[i][j]); + } + } + } + } + finally { + TimeZone.setDefault(saveZone); + Locale.setDefault(saveLocale); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6271375.java b/jdk/test/java/text/Format/DateFormat/bug6271375.java new file mode 100644 index 00000000000..811470a01d8 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6271375.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/** + * @test + * @bug 6271375 7059546 + * @summary Make sure DateFormatSymbols serialization works + * correctly for 'zoneStrings' field + */ + +import java.util.*; +import java.text.*; +import java.io.*; + +public class bug6271375 { + + public static void main(String[] args) throws Exception { + DateFormatSymbols dfsSrc = DateFormatSymbols.getInstance(); + + try (FileOutputStream fos = new FileOutputStream("dfs.ser"); + ObjectOutputStream oStream = new ObjectOutputStream(fos)) { + oStream.writeObject(dfsSrc); + } catch (Exception e) { + throw new RuntimeException("An exception is thrown.", e); + } + + try (FileInputStream fis = new FileInputStream("dfs.ser"); + ObjectInputStream iStream = new ObjectInputStream(fis)) { + DateFormatSymbols dfsDest = (DateFormatSymbols)iStream.readObject(); + + String[][] zoneStringsSrc = dfsSrc.getZoneStrings(); + String[][] zoneStringsDest = dfsDest.getZoneStrings(); + + if (!Arrays.deepEquals(zoneStringsSrc, zoneStringsDest)) { + throw new RuntimeException("src and dest zone strings are not equal"); + } + } catch (Exception e) { + throw new RuntimeException("An exception is thrown.", e); + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6317072.java b/jdk/test/java/text/Format/DateFormat/bug6317072.java new file mode 100644 index 00000000000..d5614223679 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6317072.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +/** + * @test + * @bug 6317072 + * @summary Make sure NPE is thrown with "null" argumemnts in the + * SimpleDateFormat constructors. + */ + +import java.util.*; +import java.text.*; +import java.io.*; + +public class bug6317072 { + + public static void main(String[] args) { + + try { + new SimpleDateFormat("yy", (Locale)null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat((String)null, Locale.getDefault()); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat("yy", (DateFormatSymbols)null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + new SimpleDateFormat((String)null, DateFormatSymbols.getInstance()); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getTimeInstance(DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getDateInstance(DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + + try { + DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, null); + throw new RuntimeException("should thrown a NullPointerException"); + } catch (NullPointerException e) { + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/bug6412896.java b/jdk/test/java/text/Format/DateFormat/bug6412896.java new file mode 100644 index 00000000000..b5422814ac6 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/bug6412896.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/** + * @test + * @bug 6412896 + * @summary Make sure that an IllegalArgumentException is thrown + * if the length of any row in zoneStrings array is less than 5 + */ + +import java.text.*; + +public class bug6412896 { + + static final String[][] zoneOK = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time", "PDT"}}; + static final String[][] zoneNG = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time"}}; + + public static void main(String[] args) { + + DateFormatSymbols dfs = DateFormatSymbols.getInstance(); + + dfs.setZoneStrings(zoneOK); + + try { + dfs.setZoneStrings(zoneNG); + throw new RuntimeException("should throw an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt b/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt new file mode 100644 index 00000000000..1fb54165c49 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt @@ -0,0 +1,58 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized MessageFormat for Bug4185816Test. + +aced0005737200176a6176612e746578742e4d657373616765466f726d617459 +ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e +744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661 +2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75 +74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174 +7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176 +612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572 +00025b494dba602676eab2a502000078700000000a0000000100000000000000 +0000000000000000000000000000000000000000000000000000000000757200 +135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078 +700000000a70737200166a6176612e746578742e43686f696365466f726d6174 +18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c +6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473 +7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000 +2800010000000000000001000000000178757200135b4c6a6176612e6c616e67 +2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066 +696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c +6573757200025b443ea68c14ab635a1e02000078700000000300000000000000 +003ff000000000000040000000000000007070707070707070737200106a6176 +612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863 +6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e +00044c000776617269616e7471007e00047870ffffffff740002555374000265 +6e740000787571007e00070000000a0000000a00000015000000000000000000 +0000000000000000000000000000000000000000000000740016546865206469 +736b20222220636f6e7461696e73202e diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt b/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt new file mode 100644 index 00000000000..459d257339d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt @@ -0,0 +1,58 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a corrupted serialized MessageFormat for Bug4185732Test. + +aced0005737200176a6176612e746578742e4d657373616765466f726d617459 +ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e +744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661 +2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75 +74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174 +7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176 +612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572 +00025b494dba602676eab2a502000078700000000a0000000100000000000000 +0000000000000000000000000000000000000000000000000000000000757200 +135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078 +700000000a70737200166a6176612e746578742e43686f696365466f726d6174 +18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c +6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473 +7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df +f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846 +72616374696f6e4469676974734200106d6178496e7465676572446967697473 +4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d +756d496e74656765724469676974734200116d696e4672616374696f6e446967 +6974734200106d696e496e74656765724469676974734900156d696e696d756d +4672616374696f6e4469676974734900146d696e696d756d496e746567657244 +69676974735a00107061727365496e74656765724f6e6c794900157365726961 +6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000 +2800010000000000000001000000000178757200135b4c6a6176612e6c616e67 +2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066 +696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c +6573757200025b443ea68c14ab635a1e02000078700000000300000000000000 +003ff000000000000040000000000000007070707070707070737200106a6176 +612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863 +6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e +00044c000776617269616e7471007e00047870ffffffff740002555374000265 +6e740000787571007e00070000000a0000000a00000015000000000000000000 +0000000000000000000000000000000000000000000000740010546865206469 +736b20222220636f6e74 diff --git a/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java b/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java new file mode 100644 index 00000000000..65609941f53 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4185816 + * @library /java/text/testlib + * @build Bug4185816Test IntlTest HexDumpReader + * @run main Bug4185816Test + * @summary test that MessageFormat invariants are preserved across serialization + */ +/* + * + * + * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved + * + * Portions copyright (c) 2007 Sun Microsystems, Inc. + * All Rights Reserved. + * + * The original version of this source code and documentation + * is copyrighted and owned by Taligent, Inc., a wholly-owned + * subsidiary of IBM. These materials are provided under terms + * of a License Agreement between Taligent and Sun. This technology + * is protected by multiple US and International patents. + * + * This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + */ + +import java.util.*; +import java.io.*; +import java.text.ChoiceFormat; +import java.text.MessageFormat; + +/** + * A Locale can never contains language codes of he, yi or id. + */ +public class Bug4185816Test extends IntlTest { + private static final String FILE_NAME = "Bug4185816.ser"; + private static final String CORRUPT_FILE_NAME = "Bug4185816Corrupt.ser"; + + public static void main(String[] args) throws Exception { + if (args.length == 1 && args[0].equals("prepTest")) { + prepTest(); + } else { + new Bug4185816Test().run(args); + } + } + + public void testIt() throws Exception { + Exception e = checkStreaming(FILE_NAME); + if (e != null) { + errln("MessageFormat did not stream in valid stream: "+e); + e.printStackTrace(); + } + e = checkStreaming(CORRUPT_FILE_NAME); + if (!(e instanceof InvalidObjectException)) { + errln("MessageFormat did NOT detect corrupt stream: "+e); + e.printStackTrace(); + } + } + + public Exception checkStreaming(final String fileName) { + try { + final InputStream is = HexDumpReader.getStreamFromHexDump(fileName + ".txt"); + final ObjectInputStream in = new ObjectInputStream(is); + final MessageFormat form = (MessageFormat)in.readObject(); + final Object[] testArgs = {new Long(12373), "MyDisk"}; + final String result = form.format(testArgs); + in.close(); + } catch (Exception e) { + return e; + } + return null; + } + + /** + * Create a data file for this test. The data file must be corrupted by hand. + */ + private static void prepTest() { + writeFormatToFile(FILE_NAME); + writeFormatToFile(CORRUPT_FILE_NAME); + } + + private static void writeFormatToFile(final String name) { + try { + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream(name)); + + MessageFormat fmt = new MessageFormat("The disk \"{1}\" contains {0}."); + double[] filelimits = {0,1,2}; + String[] filepart = {"no files","one file","{0,number} files"}; + ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); + fmt.setFormat(1,fileform); // NOT zero, see below + + out.writeObject(fmt); + out.close(); + } catch (Exception e) { + System.out.println(e); + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/Bug6481179.java b/jdk/test/java/text/Format/MessageFormat/Bug6481179.java new file mode 100644 index 00000000000..be8e9e29f11 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug6481179.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 + * @summary Confirm that a bug in an error message has been fixed. + * @bug 6481179 + */ + +import java.text.MessageFormat; +import java.text.ParseException; + +public class Bug6481179 { + + public static void main(String[] args) { + boolean err = false; + + try { + MessageFormat.format("Testdata {1,invalid_format_type}", + new Object[] { "val0", "val1" }); + + System.err.println("Error: IllegalArgumentException should be thrown."); + err = true; + } + catch (IllegalArgumentException e) { + String expected = "unknown format type: invalid_format_type"; + String got = e.getMessage(); + + if (!expected.equals(got)) { + System.err.println("Error: Unexpected error message: " + got); + err = true; + } + } + catch (Exception e) { + System.err.println("Error: Unexpected exception was thrown: " + e); + err = true; + } + + if (err) { + throw new RuntimeException("Failed."); + } + } + +} diff --git a/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java b/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java new file mode 100644 index 00000000000..1a4ca1d092d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java @@ -0,0 +1,121 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4112090 8008577 + * @summary verify that MessageFormat can handle large numbers of arguments + * @run main/othervm -Djava.locale.providers=COMPAT,SPI LargeMessageFormat + */ + +import java.text.MessageFormat; +import java.text.ParseException; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class LargeMessageFormat { + + public static void main(String[] args) throws ParseException { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + Locale.setDefault(Locale.GERMANY); + TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin")); + testFormat(); + testParse(); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + private static final int REPEATS = 89; + + private static void testFormat() { + // construct large argument array + Object[] sample = { + new Integer(0), // replace with running count below + "hello", + new Date(89, 10, 9), + new Integer(567890), + new Double(1234.50) + }; + int samples = sample.length; + Object[] arguments = new Object[REPEATS * (samples + 1)]; + for (int i = 0; i < REPEATS; i++) { + System.arraycopy(sample, 0, arguments, i * samples, samples); + arguments[i * samples] = new Integer(i); + } + + // construct large template + StringBuffer template = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + template.append("section {" + (i * samples) + ", number} - "); + template.append("string: {" + (i * samples + 1) + "}; "); + template.append("date: {" + (i * samples + 2) + ", date}; "); + template.append("integer: {" + (i * samples + 3) + ", number}; "); + template.append("currency: {" + (i * samples + 4) + ", number, currency};\n"); + } + + // construct expected result string + StringBuffer expected = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + expected.append("section " + i + " - "); + expected.append("string: hello; "); + expected.append("date: 09.11.1989; "); + expected.append("integer: 567.890; "); + expected.append("currency: 1.234,50 \u20AC;\n"); + } + + // create message format + MessageFormat format = new MessageFormat(template.toString()); + String result = format.format(arguments); + if (!result.equals(expected.toString())) { + System.out.println("Template:"); + System.out.println(template); + System.out.println("Expected result: "); + System.out.println(expected); + System.out.println("Actual result: "); + System.out.println(result); + throw new RuntimeException(); + } + } + + private static void testParse() throws ParseException { + StringBuffer parseTemplate = new StringBuffer(); + StringBuffer parseInput = new StringBuffer(); + for (int i = 0; i < REPEATS; i++) { + parseTemplate.append("{" + i + ", number} "); + parseInput.append(i + " "); + } + MessageFormat parseFormat = new MessageFormat(parseTemplate.toString()); + Object[] parseResult = parseFormat.parse(parseInput.toString()); + for (int i = 0; i < REPEATS; i++) { + if (((Number) parseResult[i]).intValue() != i) { + throw new RuntimeException("got wrong parse result"); + } + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java b/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java new file mode 100644 index 00000000000..1d69258f68d --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java @@ -0,0 +1,115 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4105380 + * @summary basic tests for new methods getFormatsByArgumentIndex, setFormatByArgumentIndex, setFormatsByArgumentIndex + */ + +import java.text.ChoiceFormat; +import java.text.Format; +import java.text.MessageFormat; +import java.text.NumberFormat; + +public class MessageFormatsByArgumentIndex { + + private static String choicePattern = "0.0#are no files|1.0#is one file|1.0 subsitution failed. result = " + tempBuffer.toString()); + logln("Formatted with extra params : " + tempBuffer); + //This statement gives an exception while formatting... + //If we use pattern[1] for the message with param, + //we get an NullPointerException in MessageFormat.java(617) + //If we use pattern[2] for the message with param, + //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614) + //Both are due to maxOffset not being reset to -1 + //in applyPattern() when the pattern does not + //contain any param. + } catch (Exception foo) { + errln("Exception when formatting with no params."); + } + } + + /* @bug 4058973 + * MessageFormat.toPattern has weird rounding behavior. + */ + public void Test4058973() { + + MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}"); + String pat = fmt.toPattern(); + if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) { + errln("MessageFormat.toPattern failed"); + } + } + /* @bug 4031438 + * More robust message formats. + */ + public void Test4031438() { + String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}."; + String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'."; + + // If the current locale is hi_IN, skip this test case. + if (Locale.getDefault().equals(new Locale("hi", "IN"))) { + return; + } + + MessageFormat messageFormatter = new MessageFormat(""); + + try { + logln("Apply with pattern : " + pattern1); + messageFormatter.applyPattern(pattern1); + Object[] params = {new Integer(7)}; + String tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}.")) + errln("Tests arguments < substitution failed. Formatted text=" + + "<" + tempBuffer + ">"); + logln("Formatted with 7 : " + tempBuffer); + ParsePosition status = new ParsePosition(0); + Object[] objs = messageFormatter.parse(tempBuffer, status); + if (objs[params.length] != null) + errln("Parse failed with more than expected arguments"); + for (int i = 0; i < objs.length; i++) { + if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) { + errln("Parse failed on object " + objs[i] + " at index : " + i); + } + } + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}.")) + errln("Tests with no arguments failed"); + logln("Formatted with null : " + tempBuffer); + logln("Apply with pattern : " + pattern2); + messageFormatter.applyPattern(pattern2); + tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff.")) + errln("quote format test (w/ params) failed."); + logln("Formatted with params : " + tempBuffer); + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff.")) + errln("quote format test (w/ null) failed."); + logln("Formatted with null : " + tempBuffer); + logln("toPattern : " + messageFormatter.toPattern()); + } catch (Exception foo) { + errln("Exception when formatting in bug 4031438. "+foo.getMessage()); + } + } + public void Test4052223() + { + ParsePosition pos = new ParsePosition(0); + if (pos.getErrorIndex() != -1) { + errln("ParsePosition.getErrorIndex initialization failed."); + } + MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree."); + String str = new String("There is one apple growing on the peach tree."); + Object[] objs = fmt.parse(str, pos); + logln("unparsable string , should fail at " + pos.getErrorIndex()); + if (pos.getErrorIndex() == -1) + errln("Bug 4052223 failed : parsing string " + str); + pos.setErrorIndex(4); + if (pos.getErrorIndex() != 4) + errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4"); + ChoiceFormat f = new ChoiceFormat( + "-1#are negative|0#are no or fraction|1#is one|1.0"); + Object[] objs1 = null; + Object[] objs2 = {}; + Object[] objs3 = {null}; + try { + logln("pattern: \"" + mf.toPattern() + "\""); + log("format(null) : "); + logln("\"" + mf.format(objs1) + "\""); + log("format({}) : "); + logln("\"" + mf.format(objs2) + "\""); + log("format({null}) :"); + logln("\"" + mf.format(objs3) + "\""); + } catch (Exception e) { + errln("Exception thrown for null argument tests."); + } + } + + /* @bug 4113018 + * MessageFormat.applyPattern works wrong with illegal patterns. + */ + public void Test4113018() + { + String originalPattern = "initial pattern"; + MessageFormat mf = new MessageFormat(originalPattern); + String illegalPattern = "format: {0, xxxYYY}"; + logln("pattern before: \"" + mf.toPattern() + "\""); + logln("illegal pattern: \"" + illegalPattern + "\""); + try { + mf.applyPattern(illegalPattern); + errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern); + } catch (IllegalArgumentException e) { + if (!originalPattern.equals(mf.toPattern())) + errln("pattern after: \"" + mf.toPattern() + "\""); + } + } + /* @bug 4106661 + * ChoiceFormat is silent about the pattern usage in javadoc. + */ + public void Test4106661() + { + ChoiceFormat fmt = new ChoiceFormat( + "-1#are negative| 0#are no or fraction | 1#is one |1.0 " + + out + "; want \"" + DATA[i+1+j] + '"'); + } + String pat = cf.toPattern(); + String pat2 = new ChoiceFormat(pat).toPattern(); + if (!pat.equals(pat2)) + errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); + else + logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); + } + catch (IllegalArgumentException e) { + errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e); + } + } + } + + /** + * @bug 4112104 + * MessageFormat.equals(null) throws a NullPointerException. The JLS states + * that it should return false. + */ + public void Test4112104() { + MessageFormat format = new MessageFormat(""); + try { + // This should NOT throw an exception + if (format.equals(null)) { + // It also should return false + errln("MessageFormat.equals(null) returns false"); + } + } + catch (NullPointerException e) { + errln("MessageFormat.equals(null) throws " + e); + } + } + + /** + * @bug 4169959 + * MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG. + */ + public void Test4169959() { + // This works + logln(MessageFormat.format( "This will {0}", + new String[]{"work"} ) ); + + // This fails + logln(MessageFormat.format( "This will {0}", + new Object[]{ null } ) ); + } + + public void test4232154() { + boolean gotException = false; + try { + MessageFormat format = new MessageFormat("The date is {0:date}"); + } catch (Exception e) { + gotException = true; + if (!(e instanceof IllegalArgumentException)) { + throw new RuntimeException("got wrong exception type"); + } + if ("argument number too large at ".equals(e.getMessage())) { + throw new RuntimeException("got wrong exception message"); + } + } + if (!gotException) { + throw new RuntimeException("didn't get exception for invalid input"); + } + } + + public void test4293229() { + MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''"); + Object[] args = { null }; + String expected = "'{0}' '{0}'"; + String result = format.format(args); + if (!result.equals(expected)) { + throw new RuntimeException("wrong format result - expected \"" + + expected + "\", got \"" + result + "\""); + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/MessageTest.java b/jdk/test/java/text/Format/MessageFormat/MessageTest.java new file mode 100644 index 00000000000..9234ae90c9f --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/MessageTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1997 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test MessageFormat + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + + +import java.util.*; +import java.io.*; +import java.text.*; + +public class MessageTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new MessageTest().run(args); + } + + + public void TestMSGPatternTest() { + Object[] testArgs = { + new Double (1), new Double(3456), + "Disk", new Date(10000000000L)}; + + String[] testCases = { + "Quotes '', '{', 'a' {0} '{0}'", + "Quotes '', '{', 'a' {0,number} '{0}'", + "'{'1,number,'#',##} {1,number,'#',##}", + "There are {1} files on {2} at {3}", + "On {2}, there are {1} files, with {0,number,currency}.", + "'{1,number,percent}', {1,number,percent}, ", + "'{1,date,full}', {1,date,full}, ", + "'{3,date,full}', {3,date,full}, ", + "'{1,number,#,##}' {1,number,#,##}", + }; + + for (int i = 0; i < testCases.length; ++i) { + Locale save = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + logln(""); + logln( i + " Pat in: " + testCases[i]); + MessageFormat form = new MessageFormat(testCases[i]); + logln( i + " Pat out: " + form.toPattern()); + String result = form.format(testArgs); + logln( i + " Result: " + result); + Object[] values = form.parse(result); + for (int j = 0; j < testArgs.length; ++j) { + Object testArg = testArgs[j]; + Object value = null; + if (j < values.length) { + value = values[j]; + } + if ((testArg == null && value != null) + || (testArg != null && !testArg.equals(value))) { + logln( i + " " + j + " old: " + testArg); + logln( i + " " + j + " new: " + value); + } + } + } + catch(java.text.ParseException pe ) { + throw new RuntimeException("Error: MessageFormat.parse throws ParseException"); + } + finally{ + Locale.setDefault(save); + } + } + } +} diff --git a/jdk/test/java/text/Format/MessageFormat/bug4492719.java b/jdk/test/java/text/Format/MessageFormat/bug4492719.java new file mode 100644 index 00000000000..6a1d2184ffe --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/bug4492719.java @@ -0,0 +1,79 @@ +/* + * 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. + */ + +/* + * @test + * + * @bug 4492719 + * @library /java/text/testlib + * @summary Confirm that Message.parse() interprets time zone which uses "GMT+/-" format correctly and doesn't throw ParseException. + */ + +import java.util.*; +import java.text.*; + +public class bug4492719 extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + MessageFormat mf; + boolean err =false; + + String[] formats = { + "short", "medium", "long", "full" + }; + String[] timezones = { + "America/Los_Angeles", "GMT", "GMT+09:00", "GMT-8:00", + "GMT+123", "GMT-1234", "GMT+2", "GMT-13" + }; + String text; + + Locale.setDefault(Locale.US); + + try { + for (int i = 0; i < timezones.length; i++) { + TimeZone.setDefault(TimeZone.getTimeZone(timezones[i])); + + for (int j = 0; j < formats.length; j++) { + mf = new MessageFormat("{0,time," + formats[j] + "} - time"); + text = MessageFormat.format("{0,time," + formats[j] + "} - time", + new Object [] { new Date(123456789012L)}); + Object[] objs = mf.parse(text); + } + } + } catch (ParseException e) { + err = true; + System.err.println("Invalid ParseException occurred : " + + e.getMessage()); + System.err.println(" TimeZone=" + TimeZone.getDefault()); + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + if (err) { + throw new Exception("MessageFormat.parse(\"GMT format\") failed."); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java new file mode 100644 index 00000000000..1a2e7bf3945 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java @@ -0,0 +1,134 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4018937 + * @summary Confirm that DecimalFormat.parse() parses BigDecimal and BigInteger as expected. + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class BigDecimalCompatibilityTest { + + static boolean err = false; + + static final String[] input_data = { + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + }; + static final String[] exponents = { + "E-100", "E100", "E-900", "E900", "" + }; + static final int[] multipliers = { + -1, 1, -100, 100, -9999, 9999 + }; + + public static void main(String[] args) throws Exception { + Locale loc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + testBigDecimal(); + testBigInteger(); + + Locale.setDefault(loc); + + if (err) { + throw new RuntimeException("Error: Unexpected value"); + } + } + + static private void testBigDecimal() { + DecimalFormat df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMaximumFractionDigits(Integer.MAX_VALUE); + + for (int i = 0; i < input_data.length; i++) { + for (int j = 0; j < input_data.length; j++) { + for (int k = 0; k < input_data.length; k++) { + for (int l = 0; l < input_data.length; l++) { + for (int m = 0; m < exponents.length; m++) { + String s = input_data[i] + input_data[j] + '.' + + input_data[k] + input_data[l] + + exponents[m]; + for (int n = 0; n < multipliers.length; n++) { + test(df, s, multipliers[n]); + test(df, '-'+s, multipliers[n]); + } + } + } + } + } + } + } + + static private void testBigInteger() { + DecimalFormat df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMaximumFractionDigits(Integer.MAX_VALUE); + + for (int i = 0; i < input_data.length; i++) { + for (int j = 0; j < input_data.length; j++) { + String s = input_data[i] + input_data[j]; + for (int k = 0; k < multipliers.length; k++) { + test(df, s, multipliers[k]); + test(df, '-'+s, multipliers[k]); + } + } + } + } + + static void test(DecimalFormat df, String s, int multiplier) { + df.setMultiplier(multiplier); + + Number num = null; + try { + num = df.parse(s); + } + catch (ParseException e) { + err = true; + System.err.println("Failed: Exception occurred: " + e.getMessage()); + return; + } + + BigDecimal bd = new BigDecimal(s); + try { + bd = bd.divide(new BigDecimal(multiplier)); + } + catch (ArithmeticException e) { + bd = bd.divide(new BigDecimal(multiplier), BigDecimal.ROUND_HALF_EVEN); + } + check(num, bd, multiplier); + } + + static void check(Number got, BigDecimal expected, int multiplier) { + if (!got.equals(expected)) { + err = true; + System.err.println("Failed: got:" + got + + ", expected: " + expected + + ", multiplier=" + multiplier); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java new file mode 100644 index 00000000000..14b3a9fec62 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java @@ -0,0 +1,1044 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4018937 8008577 + * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalFormat + */ + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.*; +import java.util.*; + +public class BigDecimalFormat extends IntlTest { + + public static void main(String[] args) throws Exception { + new BigDecimalFormat().run(args); + } + + static final String nonsep_int = + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; + + static final String sep_int = + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890"; + + static final String nonsep_zero = + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000"; + + static final String sep_zero = + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000"; + + static final String fra = + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789"; + + + StringBuffer formatted = new StringBuffer(1000); + FieldPosition fp; + + /** + * Test for normal big numbers which have the fraction part + */ + void test_Format_in_NumberFormat_BigDecimal() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 0.000...789 + // To: 0.000...789 (same as From) + formatted.setLength(0); + from = "0." + nonsep_zero + "123456789"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...789 + // To: -0.000...789 (same as From) + // ~ : FieldPosition(SIGN) + fp = new FieldPosition(NumberFormat.Field.SIGN); + formatted.setLength(0); + from = "-0." + nonsep_zero + "123456789"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 1); + + /* ------------------------------------------------------------------ */ + + // From: 1234...7890.012...789 + // To: 123,4...7,890.012...789 + // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD) + fp = new FieldPosition(DecimalFormat.INTEGER_FIELD); + formatted.setLength(0); + from = nonsep_int + "." + fra; + to = sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 479); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890.012...789 + // To: -123,4...7,890.012...789 + // ~~~~~~~~~ : FieldPosition(FRACTION_FIELD) + fp = new FieldPosition(DecimalFormat.FRACTION_FIELD); + formatted.setLength(0); + from = "-" + nonsep_int + "." + fra; + to = "-" + sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 481, 841); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000.000...789 + // To: 123,4...7,890,000,0...0,000.000...789 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero + fra; + to = sep_int + "," + sep_zero + "." + nonsep_zero + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.000...789 + // To: -123,4...7,890,000,0...0,000.000...789 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + fra; + to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000 + // To: 123,4...7,890,000,0...0,000 + formatted.setLength(0); + from = nonsep_int + nonsep_zero; + to = sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000 + // To: -123,4...7,890,000,0...0,000 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero; + to = "-" + sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000.0...0 + // To: 1,234...7,890,000,0...0,000 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero; + to = sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.0...0 + // To: -1,234...7,890,000,0...0,000 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero; + to = "-" + sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000 + // To: 0 + formatted.setLength(0); + from = nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...0000 + // To: 0 + formatted.setLength(0); + from = "-" + nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 000...00001234 + // To: 1,234 + formatted.setLength(0); + from = nonsep_zero + "1234"; + to = "1,234"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...00001234 + // To: -1,234 + // ~ : FieldPosition(GROUPING_SEPARATOR) + fp = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR); + formatted.setLength(0); + from = "-" + nonsep_zero + "1234"; + to = "-1,234"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 2, 3); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000.0...0 + // To: 0 + formatted.setLength(0); + from = nonsep_zero + "." + nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.0"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1); + + // From: -000...0000.0...0 + // To: 0.0 + formatted.setLength(0); + from = "-" + nonsep_zero + "." + nonsep_zero; + to = "0.0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...7890.012...7890...0 + // To: 1,234...7,890.0123...789 + formatted.setLength(0); + from = nonsep_int + "." + fra + nonsep_zero; + to = sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890.012...7890...0 + // To: -1,234...7,890.0123...789 + formatted.setLength(0); + from = "-" + nonsep_int + "." + fra + nonsep_zero; + to = "-" + sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 1123...890.012...789 + // To : 1.123...8900123...789E360 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "1" + nonsep_int + "." + fra; + to = "1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 723, 726); + + /* ------------------------------------------------------------------ */ + + // From: -1123...890.012...789 + // To : -1.123...8900123...789E360 + formatted.setLength(0); + from = "-1" + nonsep_int + "." + fra; + to = "-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 0.000...0001123...890.012...789 + // To : 1.123...8900123...789E-360 + formatted.setLength(0); + from = "0." + nonsep_zero + "1" + fra; + to = "1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...0001123...890.012...789 + // To : -1.123...8900123...789E-360 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra; + to = "-1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1123...890.012...789000...000 + // To : 1.123...8900123...789E360 + formatted.setLength(0); + from = "1" + nonsep_int + "." + fra + nonsep_zero; + to = "1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1123...890.012...789000...000 + // To : -1.123...8900123...789E360 + // ~ : FieldPosition(EXPONENT_SYMBOL) + fp = new FieldPosition(NumberFormat.Field.EXPONENT_SYMBOL); + formatted.setLength(0); + from = "-1" + nonsep_int + "." + fra + nonsep_zero; + to = "-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 723, 724); + + /* ------------------------------------------------------------------ */ + + // From: 0.000...0001123...890.012...789000...000 + // To : 1.123...8900123...789E-360 + // ~ : FieldPosition(EXPONENT_SIGN) + fp = new FieldPosition(NumberFormat.Field.EXPONENT_SIGN); + formatted.setLength(0); + from = "0." + nonsep_zero + "1" + fra + nonsep_zero; + to = "1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 363, 364); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...0001123...890.012...789000...000 + // To : -1.123...8900123...789E-360 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra + nonsep_zero; + to = "-1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: ABC1123...890.012...789 + // To : ABC1.123...890.0123...789 + formatted = new StringBuffer("ABC"); + from = "1" + nonsep_int + "." + fra; + to = "ABC1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: ABC-1123...890.012...789 + // To : ABC-1.123...890.0123...789 + // ~ : FieldPosition(DECIMAL_SEPARATOR) + fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); + formatted = new StringBuffer("ABC"); + from = "-1" + nonsep_int + "." + fra; + to = "ABC-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 5, 6); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, 726, 0); + + // From: 0.000...000012...7890123456789 + // To: 0.000...000012...789012346 (Shorter than From) + formatted.setLength(0); + from = "0." + nonsep_zero + fra + fra; + to = "0." + nonsep_zero + fra + "012346"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, 723, 0); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...000012...7890123456789 + // To: -0.000...000012...789012 (Shorter than From) + formatted.setLength(0); + from = "-0." + nonsep_zero + fra + fra; + to = "-0." + nonsep_zero + fra + "012"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, 370, 0); + + // From: 1234567890.012...78901234567890 + // To: 12345.67890012...789012346E5 + formatted.setLength(0); + from = "1234567890." + fra + "0123456789"; + to = "12345.67890" + fra + "01235E5"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 364, 0); + + // From: -0.000...0001012...7890123456789 + // To: -1.012...789012E-361 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra + "0123456789"; + to = "-1." + fra + "0123E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 366, 0); + + // From: 1012...78901234567890 + // To: 1.012...789012346E370 + formatted.setLength(0); + from = "1" + fra + "0123456789"; + to = "1." + fra + "012346E370"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 363, 0); + + // From: -1012...7890123456789 + // To: -1.012...789012E370 + formatted.setLength(0); + from = "-1" + fra + "0123456789"; + to = "-1." + fra + "012E370"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 720); + + // From: 1234...78900000...0000.0...0 + // To: 1,234...7,890,000,0...0,000.0...0 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero; + to = sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.0...0 + // To: -1,234...7,890,000,0...0,000.0...0 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero; + to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which have the fraction part with multiplier + */ + void test_Format_in_NumberFormat_BigDecimal_usingMultiplier() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + ((DecimalFormat)nf).setMultiplier(250000000); + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true); + + // From: 1000...0000.000...000 + // To: 250,0...0,000. + formatted.setLength(0); + from = "1" + nonsep_zero + "." + nonsep_zero; + to = "250,000,000," + sep_zero + "."; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false); + + // From: -1000...0000.000...000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero + "." + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + ((DecimalFormat)nf).setMultiplier(-250000000); + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true); + + // From: 1000...0000.000...000 + // To: -250,0...0,000. + formatted.setLength(0); + from = "1" + nonsep_zero + "." + nonsep_zero; + to = "-250,000,000," + sep_zero + "."; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false); + + // From: -1000...0000.000...000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero + "." + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which don't have the fraction part + */ + void test_Format_in_NumberFormat_BigInteger() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1234...7890 + // To: 123,4...7,890 + formatted.setLength(0); + from = nonsep_int; + to = sep_int; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890 + // To: -123,4...7,890 + // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD) + fp = new FieldPosition(DecimalFormat.INTEGER_FIELD); + formatted.setLength(0); + from = "-" + nonsep_int; + to = "-" + sep_int; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 1, 480); + + /* ------------------------------------------------------------------ */ + + // From: 000...0001234...7890 + // To: 123,4...7,890 + formatted.setLength(0); + from = nonsep_zero + nonsep_int; + to = sep_int; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...0001234...7890 + // To: -123,4...7,890 + // ~ : FieldPosition(SIGN) + fp = new FieldPosition(NumberFormat.Field.SIGN); + formatted.setLength(0); + from = "-" + nonsep_zero + nonsep_int; + to = "-" + sep_int; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 1); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000 + // To: 0 + formatted.setLength(0); + from = nonsep_zero; + to = "0"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.0"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1); + + // From: -000...0000 + // To: 0.0 + fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); + formatted.setLength(0); + from = "-" + nonsep_zero; + to = "0.0"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 1, 2); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 10123...789 + // To : 1.0123...789E360 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "1" + fra; + to = "1." + fra + "E360"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 363, 366); + + /* ------------------------------------------------------------------ */ + + // From: -1012...789 + // To : -1.012...789E360 + formatted.setLength(0); + from = "-1" + fra; + to = "-1." + fra + "E360"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, Integer.MAX_VALUE, 720); + + // From: 12345012...789000...000 + // To : 12345.012...789000...000E720 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "12345" + fra + nonsep_zero; + to = "12345." + fra + nonsep_zero + "E720"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 727, 730); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, Integer.MAX_VALUE, 365); + + // From: -1234567890012...789000...000 + // To : -12345.67890012...789E365 + formatted.setLength(0); + from = "-1234567890" + fra; + to = "-12345.67890" + fra + "E365"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which don't have the fraction part with + * multiplier + */ + void test_Format_in_NumberFormat_BigInteger_usingMultiplier() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(250000000); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1000...0000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "1" + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1000...0000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(-250000000); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1000...0000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "1" + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1000...0000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal Long numbers when maximum and minimum digits are + * specified + */ + void test_Format_in_NumberFormat_Long_checkDigits() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0); + + // From: 1234567890 + // To: 000,0...0,000,123,456,789 + // ------------- + // 300 zeros + formatted.setLength(0); + from = "123456789"; + to = sep_zero.substring(0, 399) + ",123,456,789"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("##0.###"); + ((DecimalFormat)nf).setMultiplier(-1); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: 1234567890 + // To: -0000...0000123456789.000...000 + // ------------- + // 300 zeros + formatted.setLength(0); + from = "123456789"; + to = "-" + nonsep_zero.substring(0, 300) + "123456789." + + nonsep_zero.substring(0, 340); + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0); + + // From: Long.MAX_VALUE + // To: 000,0...0,000,019,807,040,619,342,712,359,383,728,129 + // --------------- + // 280 zeros + formatted.setLength(0); + from = Long.toString(Long.MAX_VALUE); + to = sep_zero.substring(0, 373) + + "19,807,040,619,342,712,359,383,728,129"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 360); + + // From: Long.MAX_VALUE + // To: -1.9807040628566084396238503936000...000E28 + // --------- + // 312 zeros + formatted.setLength(0); + from = Long.toString(Long.MAX_VALUE); + to = "-1.9807040628566084396238503936" + + nonsep_zero.substring(0, 312) + "E28"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("##0.###E0"); + ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: Long.MIN_VALUE + // To: -198070406193427123615312117760000...0000.000...000E-280 + // ----------- --------- + // 280 zeros 340 zeros + formatted.setLength(0); + from = Long.toString(Long.MIN_VALUE); + to = "-19807040619342712361531211776" + + nonsep_zero.substring(0, 280) + "." + + nonsep_zero.substring(0, 340) + "E-280"; + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: Long.MIN_VALUE + // To: 000,0...0,000,019,807,040,628,566,084,398,385,987,584.000...000 + // --------------- --------- + // 280 zeros 340 zeros + formatted.setLength(0); + from = Long.toString(Long.MIN_VALUE); + to = sep_zero.substring(0, 373) + + "19,807,040,628,566,084,398,385,987,584." + + nonsep_zero.substring(0, 340); + nf.format(new Long(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for special numbers + * Double.NaN + * Double.POSITIVE_INFINITY + * Double.NEGATIVE_INFINITY + */ + void test_Format_in_NumberFormat_SpecialNumber() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + double[] numbers = { + -0.0, 0.0, Double.NaN, + Double.POSITIVE_INFINITY, 5.1, 5.0, + Double.NEGATIVE_INFINITY, -5.1, -5.0, + }; + int multipliers[] = {0, 5, -5}; + String[][] expected = { + {"-0", "0", "\ufffd", "\ufffd", "0", "0", "\ufffd", "-0", "-0"}, + {"-0", "0", "\ufffd", "\u221e", "25.5", "25", "-\u221e", "-25.5", + "-25"}, + {"0", "-0", "\ufffd", "-\u221e", "-25.5", "-25", "\u221e", "25.5", + "25"}, + }; + + for (int i = 0; i < multipliers.length; i++) { + ((DecimalFormat)nf).setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + formatted.setLength(0); + from = String.valueOf(numbers[j]); + nf.format(numbers[j], formatted, new FieldPosition(0)); + checkFormat(from, formatted, expected[i][j], + ((DecimalFormat)nf).getMultiplier()); + } + } + } + + /** + * Test for Long.MIN_VALUE + * (Formatting Long.MIN_VALUE w/ multiplier=-1 used to return a wrong + * number.) + */ + void test_Format_in_NumberFormat_Other() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + long[] numbers = { + Long.MIN_VALUE, + }; + int multipliers[] = {1, -1}; + String[][] expected = { + {"-9,223,372,036,854,775,808"}, // Long.MIN_VALUE + {"9,223,372,036,854,775,808"}, // Long.MIN_VALUE * (-1) + }; + + for (int i = 0; i < multipliers.length; i++) { + ((DecimalFormat)nf).setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + formatted.setLength(0); + from = String.valueOf(numbers[j]); + nf.format(numbers[j], formatted, new FieldPosition(0)); + checkFormat(from, formatted, expected[i][j], + ((DecimalFormat)nf).getMultiplier()); + } + } + } + + /** + * Test for MessageFormat + */ + void test_Format_in_MessageFormat() { + MessageFormat mf = new MessageFormat( + " {0, number}\n" + + " {0, number, integer}\n" + + " {0, number, currency}\n" + + " {0, number, percent}\n" + + " {0, number,0.###########E0}\n" + + + " {1, number}\n" + + " {1, number, integer}\n" + + " {1, number, currency}\n" + + " {1, number, percent}\n" + + " {1, number,0.#######E0}\n", + Locale.US + ); + Object[] testArgs = { + new BigInteger("9876543210987654321098765432109876543210"), + new BigDecimal("-12345678901234567890.98765432109876543210987654321"), + }; + String expected = + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" + + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" + + " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00\n" + + " 987,654,321,098,765,432,109,876,543,210,987,654,321,000%\n" + + " 9.87654321099E39\n" + + + " -12,345,678,901,234,567,890.988\n" + + " -12,345,678,901,234,567,891\n" + + " ($12,345,678,901,234,567,890.99)\n" + + " -1,234,567,890,123,456,789,099%\n" + + " -1.2345679E19\n" + ; + + if (!expected.equals(mf.format(testArgs))) { + errln("Wrong format.\n got:\n" + mf.format(testArgs) + + " expected:\n" + expected); + } + } + + private void setDigits(NumberFormat nf, + int i_max, int i_min, int f_max, int f_min) { + nf.setMaximumIntegerDigits(i_max); + nf.setMinimumIntegerDigits(i_min); + nf.setMaximumFractionDigits(f_max); + nf.setMinimumFractionDigits(f_min); + } + + private void checkFormat(String orig, StringBuffer got, String expected, + int multiplier) { + if (!expected.equals(new String(got))) { + errln("Formatting... failed." + + "\n original: " + orig + + "\n multiplier: " + multiplier + + "\n formatted: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkFieldPosition(String orig, FieldPosition fp, int begin, + int end) { + int position; + + if ((position = fp.getBeginIndex()) != begin) { + errln("Formatting... wrong Begin index returned for " + + fp.getFieldAttribute() + "." + + "\n original: " + orig + + "\n got: " + position + + "\n expected: " + begin + "\n"); + } + if ((position = fp.getEndIndex()) != end) { + errln("Formatting... wrong End index returned for " + + fp.getFieldAttribute() + "." + + "\n original: " + orig + + "\n got: " + position + + "\n expected: " + end + "\n"); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java b/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java new file mode 100644 index 00000000000..be206052d06 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java @@ -0,0 +1,709 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4018937 8008577 + * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalParse + */ + +import java.math.BigDecimal; +import java.text.*; +import java.util.*; + +public class BigDecimalParse extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale loc = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new BigDecimalParse().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(loc); + } + } + + static final String nonsep_int = + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; + + static final String sep_int = + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890"; + + static final String nonsep_zero = + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000"; + + static final String sep_zero = + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000"; + + static final String fra = + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789"; + + + Number parsed = null; + ParsePosition pp; + boolean exceptionOccurred; + String msg; + DecimalFormat df; + + /** + * Test for normal big numbers which have the fraction part + */ + void test_Parse_in_DecimalFormat_BigDecimal() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 1234...7890.012...789 + // To: BigDecimal 1234...7890.012...789 + check(nonsep_int + "." + fra, new BigDecimal(nonsep_int + "." + fra)); + + // From: -1,234...7,890.012...789 + // To: BigDecimal -1234...7890.012...789 + check("-" + sep_int + "." + fra, + new BigDecimal("-" + nonsep_int + "." + fra)); + + // From: 000...0000.0...0 + // To: BigDecimal 0E-360 + check(nonsep_zero + "." + nonsep_zero, + new BigDecimal(nonsep_zero + "." + nonsep_zero)); + + // From: 0.000...0000123...789E370 + // To: BigDecimal 0.0123...789 + check("0.0000000000" + nonsep_zero + fra + "E370", + new BigDecimal("0.0000000000" + nonsep_zero + fra + "E370")); + + // From: 0.1123...890E-360 + // To: BigDecimal 1.123...890E-361 + check("0.1" + nonsep_int + "E-360", + new BigDecimal("0.1" + nonsep_int + "E-360")); + + // From: 000...0000.0...0123...7890 + // To: BigDecimal 1.234...890E-361 + check(nonsep_zero + "." + nonsep_zero + nonsep_int, + new BigDecimal(nonsep_zero + "." + nonsep_zero + nonsep_int)); + + // From: 0.123...890E360 + // To: BigDecimal 123...890 + check("0." + nonsep_int + "E360", + new BigDecimal("0." + nonsep_int + "E360")); + } + + /** + * Test for normal big numbers which have the fraction part with multiplier + */ + void test_Parse_in_DecimalFormat_BigDecimal_usingMultiplier() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 250,0...0,000.000...000 + // To: 1000...0000.000...000 + df.setMultiplier(250000000); + check("250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("1" + nonsep_zero + "." + nonsep_zero)); + + // From: -250,0...0,000.000...000 + // To: -1000...0000.000...000 + check("-250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // From: 250,0...0,000.000...000 + // To: -1000...0000.000...000 + df.setMultiplier(-250000000); + check("250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // From: -250,0...0,000.000...000 + // To: 1000...0000.000...000 + check("-250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("1" + nonsep_zero + "." + nonsep_zero)); + + // Confirm that ArithmeticException is handled properly + // From: 1000.000 + // To: 333.333 + df.setMultiplier(3); + check("1000.000", new BigDecimal("333.333")); + + // Confirm that ArithmeticException is handled properly + // From: 10000.0000 + // To: 303.0303 + df.setMultiplier(33); + check("10000.0000", new BigDecimal("303.0303")); + } + + /** + * Test for division by zero (BigDecimal) + */ + void test_Parse_in_DecimalFormat_BigDecimal_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMultiplier(0); + + // From: 1000.000 + // To: Double.POSITIVE_INFINITY + check("1000.000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000 + // To: Double.NEGATIVE_INFINITY + check("-1000", new Double(Double.NEGATIVE_INFINITY)); + + // From: -0.00 + // To: Double.NaN + check("-0.00", new Double(Double.NaN)); + } + + /** + * Test for division by zero (Double) + */ + void test_Parse_in_DecimalFormat_Double_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(false); + df.setMultiplier(0); + + // From: 1000.000 + // To: Double.POSITIVE_INFINITY + check("1000.000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000.000 + // To: Double.NEGATIVE_INFINITY + check("-1000.000", new Double(Double.NEGATIVE_INFINITY)); + + // From: 0.0 + // To: Double.NaN + check("0.0", new Double(Double.NaN)); + + // From: -0.0 (Double) + // To: Double.NaN + check("-0.0", new Double(Double.NaN)); + + // From: Double.NaN + // To: Double.NaN + check("\ufffd", new Double(Double.NaN)); + + // From: Double.POSITIVE_INFINITY + // To: Double.NaN + check("\u221e", new Double(Double.POSITIVE_INFINITY)); + + // From: Double.NEGATIVE_INFINITY + // To: Double.NaN + check("-\u221e", new Double(Double.NEGATIVE_INFINITY)); + } + + /** + * Test for division by zero (Long) + */ + void test_Parse_in_DecimalFormat_Long_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(false); + df.setMultiplier(0); + + // From: 1000 + // To: Double.POSITIVE_INFINITY + check("1000", new Double(Double.POSITIVE_INFINITY)); + + // From: -1000 + // To: Double.NEGATIVE_INFINITY + check("-1000", new Double(Double.NEGATIVE_INFINITY)); + + // From: -000 (Long) + // To: Double.NaN + check("-000", new Double(Double.NaN)); + } + + /** + * Test for normal big numbers which don't have the fraction part + */ + void test_Parse_in_DecimalFormat_BigInteger() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 123...890 + // To: BigDecimal 123...890 + check(nonsep_int + nonsep_int, new BigDecimal(nonsep_int + nonsep_int)); + + // From: 123,4...7,890 + // To: BigDecimal 1234...7890 + check(sep_int + "," + sep_int, new BigDecimal(nonsep_int + nonsep_int)); + + // From: -000...000123...890 + // To: BigDecimal -123...890 + check("-" + nonsep_zero + nonsep_int, new BigDecimal("-" + nonsep_int)); + + // From: -000,0...0,000,123,4...7,890 + // To: BigDecimal -123...890 + check("-" + sep_zero + "," + sep_int, new BigDecimal("-" + nonsep_int)); + } + + /** + * Test for normal big numbers which don't have the fraction part with + * multiplier + */ + void test_Parse_in_DecimalFormat_BigInteger_usingMultiplier() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 250,0...0,000 + // To: 1000...0000 + df.setMultiplier(250000000); + check("250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero)); + + // From: -250,0...0,000 + // To: -1000...0000 + check("-250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero)); + + // From: 250,0...0,000 + // To: -1000...0000 + df.setMultiplier(-250000000); + check("250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero)); + + // From: -250,0...0,000 + // To: 1000...0000 + check("-250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero)); + + // From: 250,0...0,000E-360 + // To: -1000...0000.000...000 + check("250,000,000," + sep_zero + "," + sep_zero + "E-360", + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // Confirm that a division which results in a irrational number is done + // properly + // From: 1000 + // To: 333 + df.setMultiplier(3); + check("1000", new BigDecimal("333")); + } + + /** + * Test for special numbers + * Double.NaN + * Double.POSITIVE_INFINITY + * Double.NEGATIVE_INFINITY + */ + void test_Parse_in_DecimalFormat_SpecialNumber() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + String[] numbers = { + "0", "0.0", "25", "25.0", "25.5", "\u221e", "\ufffd", + "-0", "-0.0", "-25", "-25.0", "-25.5", "-\u221e", + }; + int multipliers[] = {5, -5}; + Number[][] expected = { + { + new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"), + new BigDecimal("5.0"), new BigDecimal("5.1"), + new Double(Double.POSITIVE_INFINITY), new Double(Double.NaN), + new BigDecimal("0"), new BigDecimal("0.0"), + new BigDecimal("-5"), new BigDecimal("-5.0"), + new BigDecimal("-5.1"), + new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN), + }, + { + new BigDecimal("0"), new BigDecimal("0.0"), + new BigDecimal("-5"), new BigDecimal("-5.0"), + new BigDecimal("-5.1"), + new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN), + new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"), + new BigDecimal("5.0"), new BigDecimal("5.1"), + new Double(Double.POSITIVE_INFINITY), + }, + }; + + for (int i = 0; i < multipliers.length; i++) { + df.setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + check(String.valueOf(numbers[j]), expected[i][j]); + } + } + } + + /** + * Test for special numbers + */ + void test_Parse_in_DecimalFormat_Other() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + String[] numbers = { + "-9223372036854775808", // Long.MIN_VALUE + }; + int multipliers[] = {1, -1}; + String[][] expected = { + {"-9223372036854775808"}, // Long.MIN_VALUE + {"9223372036854775808"}, // Long.MAX_VALUE+1 = abs(MIN_VALUE) + }; + + for (int i = 0; i < multipliers.length; i++) { + df.setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + check(String.valueOf(numbers[j]), + new BigDecimal(expected[i][j])); + } + } + } + + static final String[] patterns = { + " {0, number} ", + " {0, number} ", + " {0, number, currency} ", + " {0, number, currency} ", + " {0, number, percent} ", + " {0, number, percent} ", + " {0, number,#,##0.###E0} ", + " {0, number,#,##0.###E0} ", + + " {0, number} ", + " {0, number} ", + " {0, number, integer} ", + " {0, number, integer} ", + " {0, number, currency} ", + " {0, number, currency} ", + " {0, number, percent} ", + " {0, number, percent} ", + " {0, number,#,##0.###E0} ", + " {0, number,#,##0.###E0} ", + }; + static final String[] from = { + " 12,345,678,901,234,567,890.98765432109876543210987654321 ", + " -12,345,678,901,234,567,890.98765432109876543210987654321 ", + " $12,345,678,901,234,567,890.98765432109876543210987654321 ", + " ($12,345,678,901,234,567,890.98765432109876543210987654321) ", + " 1,234,567,890,123,456,789,098.76543210987654321098765432100% ", + " -1,234,567,890,123,456,789,098.76543210987654321098765432100% ", + " 12,345,678,901,234,567,890.98765432109876543210987654321E-20 ", + " -12,345,678,901,234,567,890.98765432109876543210987654321E-20 ", + + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210 ", + " -9,876,543,210,987,654,321,098,765,432,109,876,543,210 ", + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210E5 ", + " -9,876,543,210,987,654,321,098,765,432,109,876,543,210E-5 ", + " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00 ", + " ($9,876,543,210,987,654,321,098,765,432,109,876,543,210.00) ", + " 987,654,321,098,765,432,109,876,543,210,987,654,321,012% ", + " -987,654,321,098,765,432,109,876,543,210,987,654,321,012% ", + " 98,765,432,109,876,543,210.98765432109876543210E20 ", + " -987,654,321,098,765,432,109,876,543,210,987,654,321,000,000,000,000,000,000,000E-20 ", + }; + + static final String[] expected1 = { // isParseIntegerOnly() == false + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "0.1234567890123456789098765432109876543210987654321", + "-0.1234567890123456789098765432109876543210987654321", + + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9.876543210987654321098765432109876543210E44", + "-98765432109876543210987654321098765.43210", + "9876543210987654321098765432109876543210.00", + "-9876543210987654321098765432109876543210.00", + "9876543210987654321098765432109876543210.12", + "-9876543210987654321098765432109876543210.12", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210.00000000000000000000", + }; + static final int[] parsePosition1 = { + 60, 61, 61, 63, 64, 65, 64, 65, + 57, 58, 59, 61, 61, 63, 60, 61, 54, 88, + }; + + /** + * Test for MessageFormat: setParseIntegerOnly(false) + */ + void test_Parse_in_MessageFormat_NotParseIntegerOnly() { + for (int i=0; i < patterns.length; i++) { + pp = new ParsePosition(0); + Object[] parsed = null; + + try { + MessageFormat mf = new MessageFormat(patterns[i]); + Format[] formats = mf.getFormats(); + for (int j=0; j < formats.length; j++) { + ((DecimalFormat)formats[j]).setParseBigDecimal(true); + } + + parsed = mf.parse(from[i], pp); + + if (pp.getErrorIndex() != -1) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:-1, got:"+ + pp.getErrorIndex() + " for " + from[i]); + } + if (pp.getIndex() != parsePosition1[i]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition1[i] + ", got:"+ pp.getIndex() + + " for " + from[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + checkType(from[i], getType(new BigDecimal(expected1[i])), + getType((Number)parsed[0])); + checkParse(from[i], new BigDecimal(expected1[i]), + (Number)parsed[0]); + } + } + + static final String[] expected2 = { // isParseIntegerOnly() == true + "12345678901234567890", + "-12345678901234567890", + "12345678901234567890", + "-12345678901234567890", + "12345678901234567890", + "-12345678901234567890", + "0", + "0", + + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9.876543210987654321098765432109876543210E44", + "-98765432109876543210987654321098765.43210", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9876543210987654321098765432109876543210.12", + "-9876543210987654321098765432109876543210.12", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210.00000000000000000000", + }; + static final int[][] parsePosition2 = { // {errorIndex, index} + /* + * Should keep in mind that the expected result is different from + * DecimalFormat.parse() for some cases. + */ + {28, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + {2, 0}, // parsing stopped at '(' because cannot find ')' + {2, 0}, // parsing stopped at the first numeric + // because cannot find '%' + {2, 0}, // parsing stopped at the first numeric + // because cannot find '%' + {28, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + + {-1, 57}, {-1, 58}, {-1, 59}, {-1, 61}, + {56, 0}, // parsing stopped at '.' + // because cannot find '%' + {2, 0}, // parsing stopped at '(' because cannot find ')' + {-1, 60}, {-1, 61}, + {28, 0}, // parsing stopped at '.' + {-1, 88}, + }; + + /** + * Test for MessageFormat: setParseIntegerOnly(true) + */ + void test_Parse_in_MessageFormat_ParseIntegerOnly() { + for (int i=0; i < patterns.length; i++) { + pp = new ParsePosition(0); + Object[] parsed = null; + + try { + MessageFormat mf = new MessageFormat(patterns[i]); + Format[] formats = mf.getFormats(); + for (int j=0; j < formats.length; j++) { + ((DecimalFormat)formats[j]).setParseBigDecimal(true); + ((DecimalFormat)formats[j]).setParseIntegerOnly(true); + } + + parsed = mf.parse(from[i], pp); + + if (pp.getErrorIndex() != parsePosition2[i][0]) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:" + + parsePosition2[i][0] + ", got:"+ pp.getErrorIndex() + + " for " + from[i]); + } + if (pp.getIndex() != parsePosition2[i][1]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition2[i][1] + ", got:"+ pp.getIndex() + + " for " + from[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + if (parsePosition2[i][0] == -1) { + checkType(from[i], getType(new BigDecimal(expected2[i])), + getType((Number)parsed[0])); + checkParse(from[i], new BigDecimal(expected2[i]), + (Number)parsed[0]); + } + } + } + + static final String[] from3 = { + "12,345,678,901,234,567,890.98765432109876543210987654321", + "-12,345,678,901,234,567,890.98765432109876543210987654321", + "9,876,543,210,987,654,321,098,765,432,109,876,543,210", + "-9,876,543,210,987,654,321,098,765,432,109,876,543,210", + "1234556790000E-8", + }; + static final String[] expected3 = { + "12345678901234567890", + "-12345678901234567890", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "12345.56790000", + }; + static final int[][] parsePosition3 = { // {errorIndex, index} + {-1, 26}, + {-1, 27}, + {-1, 53}, + {-1, 54}, + {-1, 16}, + }; + + /** + * Test for DecimalFormat: setParseIntegerOnly(true) + */ + void test_Parse_in_DecimalFormat_ParseIntegerOnly() { + DecimalFormat df = (DecimalFormat)NumberFormat.getIntegerInstance(); + df.setParseBigDecimal(true); + + for (int i=0; i < from3.length; i++) { + pp = new ParsePosition(0); + Number parsed = null; + + try { + parsed = df.parse(from3[i], pp); + + if (pp.getErrorIndex() != parsePosition3[i][0]) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:" + + parsePosition3[i][0] + ", got:"+ pp.getErrorIndex() + + " for " + from3[i]); + } + if (pp.getIndex() != parsePosition3[i][1]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition3[i][1] + ", got:"+ pp.getIndex() + + " for " + from3[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + if (parsePosition3[i][0] == -1) { + checkType(from3[i], getType(new BigDecimal(expected3[i])), + getType(parsed)); + checkParse(from3[i], new BigDecimal(expected3[i]), parsed); + } + } + } + + protected void check(String from, Number to) { + pp = new ParsePosition(0); + try { + parsed = df.parse(from, pp); + } + catch(Exception e) { + exceptionOccurred = true; + errln(e.getMessage()); + } + if (!exceptionOccurred) { + checkParse(from, to, parsed); + checkType(from, getType(to), getType(parsed)); + checkParsePosition(from, from.length(), pp.getIndex()); + } + } + + private void checkParse(String orig, Number expected, Number got) { + if (!expected.equals(got)) { + errln("Parsing... failed." + + "\n original: " + orig + + "\n parsed: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkType(String orig, String expected, String got) { + if (!expected.equals(got)) { + errln("Parsing... unexpected Class returned." + + "\n original: " + orig + + "\n got: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkParsePosition(String orig, int expected, int got) { + if (expected != got) { + errln("Parsing... wrong ParsePosition returned." + + "\n original: " + orig + + "\n got: " + got + + "\n expected: " + expected + "\n"); + } + } + + private String getType(Number number) { + return number.getClass().getName(); + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4208135.java b/jdk/test/java/text/Format/NumberFormat/Bug4208135.java new file mode 100644 index 00000000000..3f5785b6f6c --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4208135.java @@ -0,0 +1,127 @@ +/* + * 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. + */ + +/* + * @test + * @summary Confirm that the decimal separator is shown when explicitly requested. + * @bug 4208135 + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class Bug4208135 { + + static DecimalFormat df; + + static boolean err = false; + + static public void main(String[] args){ + + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + df = new DecimalFormat(); + + df.applyPattern("0.#E0"); + + df.setDecimalSeparatorAlwaysShown(true); + checkFormat(new Double(0.0), "0.E0"); + checkFormat(new Double(10.0), "1.E1"); + checkFormat(new Double(1000.0), "1.E3"); + checkFormat(new Long(0), "0.E0"); + checkFormat(new Long(10), "1.E1"); + checkFormat(new Long(1000), "1.E3"); + checkFormat(new BigDecimal("0.0"), "0.E0"); + checkFormat(new BigDecimal("10.0"), "1.E1"); + checkFormat(new BigDecimal("1000.0"), "1.E3"); + checkFormat(new BigInteger("00"), "0.E0"); + checkFormat(new BigInteger("10"), "1.E1"); + checkFormat(new BigInteger("1000"), "1.E3"); + + df.setDecimalSeparatorAlwaysShown(false); + checkFormat(new Double(0.0), "0E0"); + checkFormat(new Double(10.0), "1E1"); + checkFormat(new Double(1000.0), "1E3"); + checkFormat(new Long(0), "0E0"); + checkFormat(new Long(10), "1E1"); + checkFormat(new Long(1000), "1E3"); + checkFormat(new BigDecimal("0.0"), "0E0"); + checkFormat(new BigDecimal("10.0"), "1E1"); + checkFormat(new BigDecimal("1000.0"), "1E3"); + checkFormat(new BigInteger("0"), "0E0"); + checkFormat(new BigInteger("10"), "1E1"); + checkFormat(new BigInteger("1000"), "1E3"); + + df.applyPattern("0.###"); + + df.setDecimalSeparatorAlwaysShown(true); + checkFormat(new Double(0.0), "0."); + checkFormat(new Double(10.0), "10."); + checkFormat(new Double(1000.0), "1000."); + checkFormat(new Long(0), "0."); + checkFormat(new Long(10), "10."); + checkFormat(new Long(1000), "1000."); + checkFormat(new BigDecimal("0.0"), "0."); + checkFormat(new BigDecimal("10.0"), "10."); + checkFormat(new BigDecimal("1000.0"), "1000."); + checkFormat(new BigInteger("0"), "0."); + checkFormat(new BigInteger("10"), "10."); + checkFormat(new BigInteger("1000"), "1000."); + + df.setDecimalSeparatorAlwaysShown(false); + checkFormat(new Double(0.0), "0"); + checkFormat(new Double(10.0), "10"); + checkFormat(new Double(1000.0), "1000"); + checkFormat(new Long(0), "0"); + checkFormat(new Long(10), "10"); + checkFormat(new Long(1000), "1000"); + checkFormat(new BigDecimal("0.0"), "0"); + checkFormat(new BigDecimal("10.0"), "10"); + checkFormat(new BigDecimal("1000.0"), "1000"); + checkFormat(new BigInteger("0"), "0"); + checkFormat(new BigInteger("10"), "10"); + checkFormat(new BigInteger("1000"), "1000"); + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format/parse with DecimalFormat"); + } + } + + static void checkFormat(Number num, String expected) { + String got = df.format(num); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat format(" + + num.getClass().getName() + + ") error:" + + "\n\tnumber: " + num + + "\n\tSeparatorShown? : " + df.isDecimalSeparatorAlwaysShown() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4833877.java b/jdk/test/java/text/Format/NumberFormat/Bug4833877.java new file mode 100644 index 00000000000..5f3c5056014 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4833877.java @@ -0,0 +1,464 @@ +/* + * 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. + */ + +/* + * @test + * @summary Confirm that the negative multiplier works as expected. + * @bug 4833877 + */ + +import java.math.*; +import java.text.*; +import java.util.*; + +public class Bug4833877 { + + static DecimalFormat df; + + static boolean err = false; + + public static void main(String[] args) throws Exception { + + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + /* ================================================================ */ + + df = new DecimalFormat(); + df.setMaximumFractionDigits(50); + df.setMultiplier(4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "1,010.10101010101"); + checkParse("-1,010.10101010101", new Double(-252.5252525252525)); + + checkFormat(new Double(-2222.2222), "-8,888.8888"); + checkParse("8888.8888", new Double(2222.2222)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "4,000"); + checkParse("-4,000", new Long(-1000)); + + checkFormat(new Long(-250), "-1,000"); + checkParse("1000", new Long(250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("22222.222222222222222222222"), + "88,888.888888888888888888888"); + checkParse("-88,888.888888888888888888888", + new BigDecimal("-22222.222222222222222222222")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "-4,444,444,444,444,444,444.444444444444444444"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "88,888,888,888,888,888,888,888,888"); + checkParse("-88,888,888,888,888,888,888,888,888", + new BigDecimal("-22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "-4,444,444,444,444,444,444,444,444"); + checkParse("4444444444444444444444444", + new BigDecimal("1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "-1,010.10101010101"); + checkParse("-1,010.10101010101", new Double(252.5252525252525)); + + checkFormat(new Double(-2222.2222), "8,888.8888"); + checkParse("8888.8888", new Double(-2222.2222)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "-4,000"); + checkParse("-4,000", new Long(1000)); + + checkFormat(new Long(-250), "1,000"); + checkParse("1000", new Long(-250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("22222.222222222222222222222"), + "-88,888.888888888888888888888"); + checkParse("-88,888.888888888888888888888", + new BigDecimal("22222.222222222222222222222")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "4,444,444,444,444,444,444.444444444444444444"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("-1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "-88,888,888,888,888,888,888,888,888"); + checkParse("-88,888,888,888,888,888,888,888,888", + new BigDecimal("22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "4,444,444,444,444,444,444,444,444"); + checkParse("4444444444444444444444444", + new BigDecimal("-1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-3); + + /* + * Test for double/Double + */ + checkFormat(new Double(3333.3333333), "-9,999.9999999"); + checkParse("-10,000.00000000000", new Double(3333.3333333333335));// rounding error + + df.setParseIntegerOnly(true); + checkFormat(new Double(-3333.3333333), "9,999.9999999"); + checkParse("10,000.00000000000", new Long(-3333)); + df.setParseIntegerOnly(false); + checkFormat(new Double(-3333.3333333), "9,999.9999999"); + checkParse("10,000.00000000000", new Double(-3333.3333333333335));// rounding error + + /* + * Test for long/Long + */ + checkFormat(new Long(3333), "-9,999"); + df.setParseIntegerOnly(true); + checkParse("-10,000", new Long(3333)); + df.setParseIntegerOnly(false); + checkParse("-10000", new Double(3333.3333333333335));// rounding error + + checkFormat(new Long(-3333), "9,999"); + df.setParseIntegerOnly(true); + checkParse("10,000", new Long(-3333)); + df.setParseIntegerOnly(false); + checkParse("10000", new Double(-3333.3333333333335));// rounding error + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + checkFormat(new BigDecimal("33333.333333333333333333333"), + "-99,999.999999999999999999999"); + checkParse("-100,000.000000000000000000000", + new BigDecimal("33333.333333333333333333333")); + + checkFormat(new BigDecimal("-33333.333333333333333333333"), + "99,999.999999999999999999999"); + checkParse("100,000.000000000000000000000", + new BigDecimal("-33333.333333333333333333333")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("33333333333333333333333333"), + "-99,999,999,999,999,999,999,999,999"); + checkParse("-100,000,000,000,000,000,000,000,000", + new BigDecimal("33333333333333333333333333")); + + checkFormat(new BigInteger("-33333333333333333333333333"), + "99,999,999,999,999,999,999,999,999"); + df.setParseIntegerOnly(true); + checkParse("100,000,000,000,000,000,000,000,000.000", + new BigDecimal("-33333333333333333333333333")); + df.setParseIntegerOnly(false); + checkParse("100,000,000,000,000,000,000,000,000.000", + new BigDecimal("-33333333333333333333333333.333")); + + /* ================================================================ */ + + df = new DecimalFormat("0.#E0;-0.#E0"); + df.setMaximumFractionDigits(50); + df.setMultiplier(4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "1.01010101010101E3"); + checkParse("-1.01010101010101E3", new Double(-2.525252525252525E2)); + + checkFormat(new Double(-2222.2222), "-8.8888888E3"); + checkParse("8888.8888", new Double(2.2222222E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "4E3"); + checkParse("-4E3", new Long(-1000)); + + checkFormat(new Long(-250), "-1E3"); + checkParse("1000", new Long(250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("22222.222222222222222222222"), + "8.8888888888888888888888888E4"); + checkParse("-8.8888888888888888888888888E4", + new BigDecimal("-2.2222222222222222222222222E4")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "-4.444444444444444444444444444444444444E18"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "8.8888888888888888888888888E25"); + checkParse("-8.8888888888888888888888888E25", + new BigDecimal("-22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "-4.444444444444444444444444E24"); + checkParse("4444444444444444444444444", + new BigDecimal("1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-4); + + /* + * Test for double/Double + */ + checkFormat(new Double(252.5252525252525), "-1.01010101010101E3"); + checkParse("-1.01010101010101E3", new Double(2.525252525252525E2)); + + checkFormat(new Double(-2222.2222), "8.8888888E3"); + checkParse("8888.8888", new Double(-2.2222222E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(1000), "-4E3"); + checkParse("-4E3", new Long(1000)); + + checkFormat(new Long(-250), "1E3"); + checkParse("1000", new Long(-250)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("22222.222222222222222222222"), + "-8.8888888888888888888888888E4"); + checkParse("-8.8888888888888888888888888E4", + new BigDecimal("2.2222222222222222222222222E4")); + + checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"), + "4.444444444444444444444444444444444444E18"); + checkParse("4444444444444444444.444444444444444444", + new BigDecimal("-1111111111111111111.111111111111111111")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("22222222222222222222222222"), + "-8.8888888888888888888888888E25"); + checkParse("-8.8888888888888888888888888E25", + new BigDecimal("22222222222222222222222222")); + + checkFormat(new BigInteger("-1111111111111111111111111"), + "4.444444444444444444444444E24"); + checkParse("4444444444444444444444444", + new BigDecimal("-1111111111111111111111111")); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(false); + df.setMultiplier(-3); + + /* + * Test for double/Double + */ + checkFormat(new Double(3333.3333333), "-9.9999999999E3"); + checkParse("-1.00000000000000E3", new Double(3.33333333333333333E2)); + + df.setParseIntegerOnly(true); + checkFormat(new Double(-3333.3333333), "9.9999999999E3"); + checkParse("10.00000000000000E3", new Long(-3)); + df.setParseIntegerOnly(false); + checkFormat(new Double(-3333.3333333), "9.9999999999E3"); + checkParse("10.00000000000000E3", new Double(-3.33333333333333333E3)); + + /* + * Test for long/Long + */ + checkFormat(new Long(3333), "-9.999E3"); + df.setParseIntegerOnly(true); + checkParse("-1.0E4", new Long(0)); + df.setParseIntegerOnly(false); + checkParse("-1.0E4", new Double(3333.3333333333335)); + + checkFormat(new Long(-3333), "9.999E3"); + df.setParseIntegerOnly(true); + checkParse("10.0E4", new Long(-3)); + df.setParseIntegerOnly(false); + checkParse("10.0E4", new Double(-33333.3333333333336)); + + /* ---------------------------------------------------------------- */ + + df.setParseBigDecimal(true); + + /* + * Test for BigDecimal + */ + + checkFormat(new BigDecimal("333.333333333333333333333333"), + "-9.99999999999999999999999999E2"); + checkParse("-1.0000000000000000000000000E3", + new BigDecimal("3.333333333333333333333333E2")); + + df.setParseIntegerOnly(true); + checkFormat(new BigDecimal("-333.333333333333333333333333"), + "9.99999999999999999999999999E2"); + checkParse("10.0000000000000000000000000E3", + new BigDecimal("-3")); + df.setParseIntegerOnly(false); + checkFormat(new BigDecimal("-333.333333333333333333333333"), + "9.99999999999999999999999999E2"); + checkParse("1.0000000000000000000000000E3", + new BigDecimal("-3.333333333333333333333333E2")); + + /* + * Test for BigInteger + */ + checkFormat(new BigInteger("33333333333333333333333333"), + "-9.9999999999999999999999999E25"); + checkParse("-100000000000000000000000000", + new BigDecimal("33333333333333333333333333")); + + checkFormat(new BigInteger("-33333333333333333333333333"), + "9.9999999999999999999999999E25"); + df.setParseIntegerOnly(true); + checkParse("100000000000000000000000000000", + new BigDecimal("-33333333333333333333333333333")); + df.setParseIntegerOnly(false); + checkParse("100000000000000000000000000.000", + new BigDecimal("-33333333333333333333333333.333")); + + /* ================================================================ */ + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format/parse with DecimalFormat"); + } + } + + static void checkFormat(Number num, String expected) { + String got = df.format(num); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat format(" + + num.getClass().getName() + + ") error:" + + "\n\tnumber: " + num + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, Double expected) { + Double got = (Double)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(double) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, Long expected) { + Long got = (Long)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(long) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } + + static void checkParse(String text, BigDecimal expected) { + BigDecimal got = (BigDecimal)df.parse(text, new ParsePosition(0)); + if (!got.equals(expected)) { + err = true; + System.err.println(" DecimalFormat parse(BigDecimal) error:" + + "\n\ttext: " + text + + "\n\tpattern: " + df.toPattern() + + "\n\tmultiplier: " + df.getMultiplier() + + "\n\tgot: " + got + + "\n\texpected: " + expected); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4838107.java b/jdk/test/java/text/Format/NumberFormat/Bug4838107.java new file mode 100644 index 00000000000..a15d537d8e6 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4838107.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4838107 8008577 + * @summary Confirm that DecimalFormat can format a number with negative exponent number correctly. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug4838107 + */ + +import java.math.*; +import java.util.*; +import java.text.*; + +public class Bug4838107 extends IntlTest { + + static DecimalFormat df; + static DecimalFormatSymbols dfs; + static boolean err = false; + + static public void main(String[] args) { + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + /** + * This bug is about exponential formatting. But I added test cases for: + * - Double and BigDecimal numbers which don't have exponent parts. + * - Long and BigInteger numbers which don't support exponential + * notation. + * because there are few test cases for suffix and prefix. + * And also, I added test cases to guarantee further formatting and + * parsing using the same DecimalFormat instance will not change the + * Number's value anymore. + */ + + test_double(); + test_long(); + test_BigDecimal(); + test_BigInteger(); + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong format with DecimalFormat"); + } + } + + static void test_double() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new Double(1234), "1,234"); + test(new Double(0.1234), "0.123"); // rounded + test(new Double(-1234), "-1,234"); + test(new Double(-0.1234), "-0.123"); // rounded + + test(new Double(Double.POSITIVE_INFINITY), "\u221e"); + test(new Double(Double.NEGATIVE_INFINITY), "-\u221e"); + test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix + test(new Double(0.0), "0"); + test(new Double(-0.0), "-0"); // with the minus sign + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

    #.###E00", 'm'); + test(new Double(1234), "

    1.234E03"); + test(new Double(0.1234), "

    1.234Em01"); + test(new Double(-1234), "m

    1.234E03"); + test(new Double(-0.1234), "m

    1.234Em01"); + + prepareFormatter("

    #.###E00;#.###E00", 'm'); + test(new Double(1234), "

    1.234E03"); + test(new Double(0.1234), "

    1.234Em01"); + test(new Double(-1234), "1.234E03"); + test(new Double(-0.1234), "1.234Em01"); + + prepareFormatter("#.###E00;

    #.###E00", 'm'); + test(new Double(1234), "1.234E03"); + test(new Double(0.1234), "1.234Em01"); + test(new Double(-1234), "

    1.234E03"); + test(new Double(-0.1234), "

    1.234Em01"); + + prepareFormatter("

    #.###E00;

    -#.###E00", 'm'); + test(new Double(1234), "

    1.234E03"); + test(new Double(0.1234), "

    1.234Em01"); + test(new Double(-1234), "

    m1.234E03"); + test(new Double(-0.1234), "

    m1.234Em01"); + + test(new Double(Double.POSITIVE_INFINITY), "

    \u221e"); + test(new Double(Double.NEGATIVE_INFINITY), "

    m\u221e"); + test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix + test(new Double(0.0), "

    0E00"); + test(new Double(-0.0), "

    m0E00"); // with the minus sign + } + + static void test_BigDecimal() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new BigDecimal("123456789012345678901234567890"), + "123,456,789,012,345,678,901,234,567,890"); + test(new BigDecimal("0.000000000123456789012345678901234567890"), + "0"); + test(new BigDecimal("-123456789012345678901234567890"), + "-123,456,789,012,345,678,901,234,567,890"); + test(new BigDecimal("-0.000000000123456789012345678901234567890"), + "-0"); + + test(new BigDecimal("0"), "0"); + test(new BigDecimal("-0"), "0"); + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

    #.####################E00;

    -#.####################E00", 'm'); + test(new BigDecimal("123456789012345678901234567890"), + "

    1.23456789012345678901E29"); + test(new BigDecimal("0.000000000123456789012345678901234567890"), + "

    1.23456789012345678901Em10"); + test(new BigDecimal("-123456789012345678901234567890"), + "

    m1.23456789012345678901E29"); + test(new BigDecimal("-0.000000000123456789012345678901234567890"), + "

    m1.23456789012345678901Em10"); + + test(new BigDecimal("0"), "

    0E00"); + test(new BigDecimal("-0"), "

    0E00"); + } + + static void test_long() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new Long(123456789), "123,456,789"); + test(new Long(-123456789), "-123,456,789"); + + test(new Long(0), "0"); + test(new Long(-0), "0"); + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

    #,###;

    -#,###", 'm'); + test(new Long(123456789), "

    123,456,789"); + test(new Long(-123456789), "

    m123,456,789"); + + test(new Long(0), "

    0"); + test(new Long(-0), "

    0"); + } + + static void test_BigInteger() { + df = new DecimalFormat(); + dfs = df.getDecimalFormatSymbols(); + + /* Test with default pattern */ + test(new BigInteger("123456789012345678901234567890"), + "123,456,789,012,345,678,901,234,567,890"); + test(new BigInteger("-123456789012345678901234567890"), + "-123,456,789,012,345,678,901,234,567,890"); + + test(new BigInteger("0"), "0"); + test(new BigInteger("-0"), "0"); + + /* Specify a pattern and the minus sign. */ + prepareFormatter("

    #,###;

    -#,###", 'm'); + test(new BigInteger("123456789012345678901234567890"), + "

    123,456,789,012,345,678,901,234,567,890"); + test(new BigInteger("-123456789012345678901234567890"), + "

    m123,456,789,012,345,678,901,234,567,890"); + + test(new BigInteger("0"), "

    0"); + test(new BigInteger("-0"), "

    0"); + } + + static void prepareFormatter(String pattern, char minusSign) { + dfs = df.getDecimalFormatSymbols(); + df.applyPattern(pattern); + dfs.setMinusSign(minusSign); + df.setDecimalFormatSymbols(dfs); + } + + static void test(Number num, String str) { + String formatted = df.format(num); + if (!formatted.equals(str)) { + err = true; + System.err.println(" DecimalFormat format(" + + num.getClass().getName() + + ") error: \n\tnumber: " + num + + "\n\tminus sign: " + dfs.getMinusSign() + + "\n\tgot: " + formatted + + "\n\texpected: " + str); + return; + } + + if (num instanceof BigDecimal || num instanceof BigInteger) { + df.setParseBigDecimal(true); + } + Number parsed1 = null, parsed2 = null; + try { + parsed1 = df.parse(formatted); + formatted = df.format(parsed1); + parsed2 = df.parse(formatted); + if (!parsed1.equals(parsed2)) { + err = true; + System.err.println(" DecimalFormat roundtrip parse(" + + num.getClass().getName() + + ") error: \n\toriginal number: " + str + + "\n\tparsed number: " + parsed1 + + " (" + parsed1.getClass().getName() + ")" + + "\n\tformatted number: " + formatted + + "\n\tre-parsed number: " + parsed2 + + " (" + parsed2.getClass().getName() + ")" + + "\n\tminus sign: " + dfs.getMinusSign()); + } + } + catch (Exception e) { + err = true; + System.err.println(" DecimalFormat parse(" + + num.getClass().getName() + + ") threw an Exception: " + e.getMessage() + + "\n\toriginal number: " + str + + "\n\tparsed number : " + parsed1 + + " (" + parsed1.getClass().getName() + ")" + + "\n\tformatted number: " + formatted + + "\n\tre-parsed number: " + parsed2 + + " (" + parsed2.getClass().getName() + ")" + + "\n\tminus sign: " + dfs.getMinusSign()); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4944439.java b/jdk/test/java/text/Format/NumberFormat/Bug4944439.java new file mode 100644 index 00000000000..beb4d77c235 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4944439.java @@ -0,0 +1,111 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4944439 + * @summary Confirm that numbers where all digits after the decimal separator are 0 + * and which are between Long.MIN_VALUE and Long.MAX_VALUE are returned as Long(not double). + */ + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.DecimalFormat; +import java.util.Locale; + +public class Bug4944439 { + + static boolean err = false; + static DecimalFormat df; + + public static void main(String[] args) throws Exception { + + Locale defaultLoc = Locale.getDefault(); + Locale.setDefault(Locale.US); + + df = new DecimalFormat(); + String s = "-9223372036854775809"; // Long.MIN_VALUE-1 + check_Double(s); + + test(Long.MIN_VALUE, Long.MIN_VALUE+10); + test(-10, 10); + test(Long.MAX_VALUE-10, Long.MAX_VALUE-1); + + s = "9223372036854775807.00"; // Long.MAX_VALUE + check_Long(s); + s = "9223372036854775808"; // Long.MAX_VALUE+1 + check_Double(s); + + s = "-0.0"; + check_Double(s); + s = "0.0"; + check_Long(s); + + Locale.setDefault(defaultLoc); + + if (err) { + throw new RuntimeException("Wrong parsing with DecimalFormat"); + } + } + + private static void test(long from, long to) throws Exception { + for (long l = from; l <= to; l++) { + check_Long(Long.toString(l) + ".00"); + } + } + + private static void check_Long(String s) throws Exception { + Number number = df.parse(s); + if (!(number instanceof Long)) { + err = true; + System.err.println("Failed: DecimalFormat.parse(\"" + s + + "\") should return a Long, but returned a " + + number.getClass().getName()); + } + + int index = s.indexOf('.'); + Long l = new Long(s.substring(0, index)); + if (!l.equals(number)) { + err = true; + System.err.println("Failed: DecimalFormat.parse(" + s + + ") should return a Long(" + l + "), but returned " + number); + } + } + + private static void check_Double(String s) throws Exception { + Number number = df.parse(s); + if (!(number instanceof Double)) { + err = true; + System.err.println("Failed: DecimalFormat.parse(\"" + s + + "\") should return a Double, but returned a " + + number.getClass().getName()); + } + + Double d = new Double(s); + if (!d.equals(number)) { + err = true; + System.err.println("Failed: DecimalFormat.parse(" + s + + ") should return a Double(" + d + "), but returned " + number); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug4990596.java b/jdk/test/java/text/Format/NumberFormat/Bug4990596.java new file mode 100644 index 00000000000..a8c03b8a035 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug4990596.java @@ -0,0 +1,59 @@ +/* + * 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 4990596 + * @summary Make sure that any subclass of Number can be formatted using DecimalFormat.format(). + */ + +import java.text.DecimalFormat; + +public class Bug4990596 { + + public static void main(String[] args) { + new DecimalFormat().format(new MutableInteger(0)); + } + + public static class MutableInteger extends Number { + public int value; + + public MutableInteger() { + } + public MutableInteger(int value) { + this.value = value; + } + public double doubleValue() { + return this.value; + } + public float floatValue() { + return this.value; + } + public int intValue() { + return this.value; + } + public long longValue() { + return this.value; + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/Bug6278616.java b/jdk/test/java/text/Format/NumberFormat/Bug6278616.java new file mode 100644 index 00000000000..9066a7da02e --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/Bug6278616.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +/* + * @test + * @summary Confirm that AtomicInteger and AtomicLong are formatted correctly. + * @bug 6278616 + */ + +import java.text.NumberFormat; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import java.util.Locale; + +public class Bug6278616 { + + static final int[] ints = { + Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE + }; + + static final long[] longs = { + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE + }; + + public static void main(String[] args) { + NumberFormat nf = NumberFormat.getInstance(); + + for (int j = 0; j < ints.length; j++) { + String s_i = nf.format(new Integer(ints[j])); + String s_ai = nf.format(new AtomicInteger(ints[j])); + if (!s_i.equals(s_ai)) { + throw new RuntimeException("format(AtomicInteger " + s_ai + + ") doesn't equal format(Integer " + + s_i + ")"); + } + } + + for (int j = 0; j < longs.length; j++) { + String s_l = nf.format(new Long(longs[j])); + String s_al = nf.format(new AtomicLong(longs[j])); + if (!s_l.equals(s_al)) { + throw new RuntimeException("format(AtomicLong " + s_al + + ") doesn't equal format(Long " + + s_l + ")"); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/CurrencyFormat.java b/jdk/test/java/text/Format/NumberFormat/CurrencyFormat.java new file mode 100644 index 00000000000..96fa3976701 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/CurrencyFormat.java @@ -0,0 +1,141 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4290801 4942982 5102005 8008577 8021121 + * @summary Basic tests for currency formatting. + * @run main/othervm -Djava.locale.providers=JRE,SPI CurrencyFormat + */ + +import java.io.File; +import java.io.FileInputStream; +import java.util.Currency; +import java.util.Locale; +import java.util.Properties; +import java.util.StringTokenizer; +import java.util.TimeZone; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; + +public class CurrencyFormat { + + public static void main(String[] args) throws Exception { + testFormatting(); + testSymbols(); + } + + static void testFormatting() { + boolean failed = false; + Locale[] locales = { + Locale.US, + Locale.JAPAN, + Locale.GERMANY, + Locale.ITALY, + new Locale("it", "IT", "EURO") }; + Currency[] currencies = { + null, + Currency.getInstance("USD"), + Currency.getInstance("JPY"), + Currency.getInstance("DEM"), + Currency.getInstance("EUR"), + }; + String[][] expecteds = { + {"$1,234.56", "$1,234.56", "JPY1,235", "DEM1,234.56", "EUR1,234.56"}, + {"\uFFE51,235", "USD1,234.56", "\uFFE51,235", "DEM1,234.56", "EUR1,234.56"}, + {"1.234,56 \u20AC", "1.234,56 USD", "1.235 JPY", "1.234,56 DM", "1.234,56 \u20AC"}, + {"\u20AC 1.234,56", "USD 1.234,56", "JPY 1.235", "DEM 1.234,56", "\u20AC 1.234,56"}, + {"\u20AC 1.234,56", "USD 1.234,56", "JPY 1.235", "DEM 1.234,56", "\u20AC 1.234,56"}, + }; + + for (int i = 0; i < locales.length; i++) { + Locale locale = locales[i]; + NumberFormat format = NumberFormat.getCurrencyInstance(locale); + for (int j = 0; j < currencies.length; j++) { + Currency currency = currencies[j]; + String expected = expecteds[i][j]; + if (currency != null) { + format.setCurrency(currency); + int digits = currency.getDefaultFractionDigits(); + format.setMinimumFractionDigits(digits); + format.setMaximumFractionDigits(digits); + } + String result = format.format(1234.56); + if (!result.equals(expected)) { + failed = true; + System.out.println("FAIL: Locale " + locale + + (currency == null ? ", default currency" : (", currency: " + currency)) + + ", expected: " + expected + + ", actual: " + result); + } + } + } + + if (failed) { + throw new RuntimeException(); + } + } + + static void testSymbols() throws Exception { + FileInputStream stream = new FileInputStream(new File(System.getProperty("test.src", "."), "CurrencySymbols.properties")); + Properties props = new Properties(); + props.load(stream); + SimpleDateFormat format = null; + + Locale[] locales = NumberFormat.getAvailableLocales(); + for (int i = 0; i < locales.length; i++) { + Locale locale = locales[i]; + DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale); + String result = symbols.getCurrencySymbol(); + String expected = (String) props.get(locale.toString()); + + if (expected == null) { + System.out.println("Warning: No expected currency symbol defined for locale " + locale); + } else { + if (expected.contains(";")) { + StringTokenizer tokens = new StringTokenizer(expected, ";"); + int tokensCount = tokens.countTokens(); + + if (tokensCount == 3) { + expected = tokens.nextToken(); + if (format == null) { + format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + format.setLenient(false); + } + + if (format.parse(tokens.nextToken()).getTime() < System.currentTimeMillis()) { + expected = tokens.nextToken(); + } + } + } + + if (!expected.equals(result)) { + throw new RuntimeException("Wrong currency symbol for locale " + + locale + ", expected: " + expected + ", got: " + result); + } + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/CurrencySymbols.properties b/jdk/test/java/text/Format/NumberFormat/CurrencySymbols.properties new file mode 100644 index 00000000000..cc919005db7 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/CurrencySymbols.properties @@ -0,0 +1,134 @@ +ar=\u00A4 +ar_AE=\u062F.\u0625.\u200F +ar_BH=\u062F.\u0628.\u200F +ar_DZ=\u062F.\u062C.\u200F +ar_EG=\u062C.\u0645.\u200F +ar_IQ=\u062F.\u0639.\u200F +ar_JO=\u062F.\u0623.\u200F +ar_KW=\u062F.\u0643.\u200F +ar_LB=\u0644.\u0644.\u200F +ar_LY=\u062F.\u0644.\u200F +ar_MA=\u062F.\u0645.\u200F +ar_OM=\u0631.\u0639.\u200F +ar_QA=\u0631.\u0642.\u200F +ar_SA=\u0631.\u0633.\u200F +# see bug 4412080 +# ar_SD=\u062C.\u0633.\u200F +ar_SY=\u0644.\u0633.\u200F +ar_TN=\u062F.\u062A.\u200F +ar_YE=\u0631.\u064A.\u200F +be=\u00A4 +# see bug 4412080 +# be_BY=\u0420\u0443\u0431 +bg=\u00A4 +# see bug 4412080 +# bg_BG=Lr +ca=\u00A4 +ca_ES=\u20AC +cs=\u00A4 +cs_CZ=K\u010D +da=\u00A4 +da_DK=kr +de=\u00A4 +de_AT=\u20AC +de_CH=SFr. +de_DE=\u20AC +de_LU=\u20AC +el=\u00A4 +el_GR=\u20AC +en=\u00A4 +en_AU=$ +en_CA=$ +en_GB=\u00A3 +en_IE=\u20AC +en_NZ=$ +en_US=$ +en_ZA=R +es=\u00A4 +es_AR=$ +es_BO=B$ +es_CL=Ch$ +# 5102005 +es_CO=$ +es_CR=C +es_CU=CU$ +es_DO=RD$ +# see bug 4412080 +# es_EC=S/ +es_ES=\u20AC +es_GT=Q +es_HN=L +es_MX=$ +es_NI=$C +es_PA=B +es_PE=S/. +es_PR=$ +es_PY=G +es_SV=C +es_UY=NU$ +es_VE=Bs.F. +et=\u00A4 +et_EE=\u20AC +fi=\u00A4 +fi_FI=\u20AC +fr=\u00A4 +fr_BE=\u20AC +fr_CA=$ +fr_CH=SFr. +fr_FR=\u20AC +fr_LU=\u20AC +hi_IN=\u0930\u0942 +hr=\u00A4 +hr_HR=Kn +hu=\u00A4 +hu_HU=Ft +is=\u00A4 +is_IS=kr. +it=\u00A4 +it_CH=SFr. +it_IT=\u20AC +iw=\u00A4 +iw_IL=\u05E9"\u05D7 +ja=\u00A4 +ja_JP=\uFFE5 +ko=\u00A4 +ko_KR=\uFFE6 +lt=\u00A4 +lt_LT=Lt;2014-12-31-22-00-00;\u20AC +lv=\u00A4 +lv_LV=Ls;2013-12-31-22-00-00;\u20AC +mk=\u00A4 +mk_MK=Den +nl=\u00A4 +nl_BE=\u20AC +nl_NL=\u20AC +no=\u00A4 +no_NO=kr +no_NO_NY=kr +pl=\u00A4 +pl_PL=z\u0142 +pt=\u00A4 +pt_BR=R$ +pt_PT=\u20AC +ro=\u00A4 +ro_RO=LEI +ru=\u00A4 +ru_RU=\u0440\u0443\u0431. +sk=\u00A4 +sk_SK=\u20AC +sl=\u00A4 +sl_SI=\u20AC +sq=\u00A4 +sq_AL=Lek +sv=\u00A4 +sv_SE=kr +th=\u00A4 +th_TH=\u0E3F +tr=\u00A4 +tr_TR=TL +uk=\u00A4 +uk_UA=\u0433\u0440\u043d. +zh=\u00A4 +zh_CN=\uFFE5 +zh_HK=HK$ +zh_TW=NT$ diff --git a/jdk/test/java/text/Format/NumberFormat/DFSDeserialization142.java b/jdk/test/java/text/Format/NumberFormat/DFSDeserialization142.java new file mode 100644 index 00000000000..2927f4e2c3b --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DFSDeserialization142.java @@ -0,0 +1,56 @@ +/* + * 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. + */ + +/* + * No at-test for this test, because it needs to be run on older version JDK than 1.6 to test. + * It was tested using 1.4.2. The file object was created using JDK1.6. + */ + + + +import java.awt.*; +import java.text.*; +import java.util.*; +import java.io.*; + +public class DFSDeserialization142{ + + public static void main(String[] args) + { + try { + + File file = new File("DecimalFormatSymbols.current"); + FileInputStream istream = new FileInputStream(file); + ObjectInputStream p = new ObjectInputStream(istream); + DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject(); + if (dfs.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){ + System.out.println("Serialization/Deserialization Test Passed."); + }else{ + throw new Exception("Serialization/Deserialization Test Failed:"+dfs.getCurrencySymbol()); + } + istream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/DFSExponential.java b/jdk/test/java/text/Format/NumberFormat/DFSExponential.java new file mode 100644 index 00000000000..898fb3feccb --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DFSExponential.java @@ -0,0 +1,87 @@ +/* + * 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. + */ + +/** + * @test + * @bug 4068067 + * @library /java/text/testlib + * @summary test NumberFormat with exponential separator symbols. It also tests the new + * public methods in DecimalFormatSymbols, setExponentSeparator() and + * getExponentSeparator() + */ + +import java.util.*; +import java.text.*; + +public class DFSExponential extends IntlTest +{ + + public static void main(String[] args) throws Exception { + new DFSExponential().run(args); + } + + + public void DFSExponenTest() throws Exception { + DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); + String pat[] = { "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" }; + double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 }; + long lval[] = { 0, -1, 1, 123456789 }; + String valFormat[][] = { + {"1.234x10^-2", "1.2346x10^8", "1.23x10^300", "-3.1416x10^-271"}, + {"12.340x10^-03", "12.346x10^07", "12.300x10^299", "-31.416x10^-272"}, + {"12.34x10^-003", "123.4568x10^006", "1.23x10^300", "-314.1593x10^-273"}, + {"1.234x10^-2", "1.235x10^8", "1.23x10^300", "[3.142x10^-271]"}, + }; + + + int ival = 0, ilval = 0; + logln("Default exponent separator: "+sym.getExponentSeparator()); + try { + sym.setExponentSeparator("x10^"); + } catch (NullPointerException e){ + errln("null String was passed to set an exponent separator symbol"); + throw new RuntimeException("Test Malfunction: null String was passed to set an exponent separator symbol" ); + } + logln("Current exponent separator: "+sym.getExponentSeparator()); + + for (int p=0; p "+s); + if(valFormat[p][v].equals(s)){ + logln(": Passed"); + }else{ + errln(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s); + throw new RuntimeException(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s); + } + } + } //end of the first for loop + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/DFSSerialization.java b/jdk/test/java/text/Format/NumberFormat/DFSSerialization.java new file mode 100644 index 00000000000..40b40b39b87 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DFSSerialization.java @@ -0,0 +1,151 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4068067 + * @library /java/text/testlib + * @build DFSSerialization IntlTest HexDumpReader + * @run main DFSSerialization + * @summary Three different tests are done. 1.read from the object created using jdk1.4.2 2.create a valid DecimalFormatSymbols object with current JDK, then read the object 3.Try to create an valid DecimalFormatSymbols object by passing null to set null for the exponent separator symbol. Expect the NullPointerException. + */ + +import java.awt.*; +import java.text.*; +import java.util.*; +import java.io.*; + +public class DFSSerialization extends IntlTest{ + public static void main(String[] args) throws Exception { + new DFSSerialization().run(args); + } + public void TestDFSSerialization(){ + /* + * 1. read from the object created using jdk1.4.2 + */ + File oldFile = new File(System.getProperty("test.src", "."), "DecimalFormatSymbols.142.txt"); + DecimalFormatSymbols dfs142 = readTestObject(oldFile); + if (dfs142 != null){ + if (dfs142.getExponentSeparator().equals("E") && dfs142.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){ + System.out.println("\n Deserialization of JDK1.4.2 Object from the current JDK: Passed."); + logln(" Deserialization of JDK1.4.2 Object from the current JDK: Passed."); + } else { + errln(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:" + +dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator()); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:" + +dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator()); + } + } + /* + * 2. create a valid DecimalFormatSymbols object with current JDK, then read the object + */ + String validObject = "DecimalFormatSymbols.current"; + File currentFile = createTestObject(validObject, "*SpecialExponentSeparator*"); + + DecimalFormatSymbols dfsValid = readTestObject(currentFile); + if (dfsValid != null){ + if (dfsValid.getExponentSeparator().equals("*SpecialExponentSeparator*") && + dfsValid.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){ + System.out.println(" Deserialization of current JDK Object from the current JDK: Passed."); + logln(" Deserialization of current JDK Object from the current JDK: Passed."); + } else { + errln(" Deserialization of current JDK Object from the current JDK was Failed:" + +dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator()); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException(" Deserialization of current Object from the current JDK was Failed:" + +dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator()); + } + } + /* + * 3. Try to create an valid DecimalFormatSymbols object by passing null + * to set null for the exponent separator symbol. Expect the NullPointerException. + */ + DecimalFormatSymbols symNPE = new DecimalFormatSymbols(Locale.US); + boolean npePassed = false; + try { + symNPE.setExponentSeparator(null); + } catch (NullPointerException npe){ + npePassed = true; + System.out.println(" Trying to set exponent separator with null: Passed."); + logln(" Trying to set exponent separator with null: Passed."); + } + if (!npePassed){ + System.out.println(" Trying to set exponent separator with null:Failed."); + errln(" Trying to set exponent separator with null:Failed."); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException(" Trying to set exponent separator with null:Failed."); + } + + } + + private DecimalFormatSymbols readTestObject(File inputFile){ + try (InputStream istream = inputFile.getName().endsWith(".txt") ? + HexDumpReader.getStreamFromHexDump(inputFile) : + new FileInputStream(inputFile)) { + ObjectInputStream p = new ObjectInputStream(istream); + DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject(); + return dfs; + } catch (Exception e) { + errln("Test Malfunction in DFSSerialization: Exception while reading the object"); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException("Test Malfunction: re-throwing the exception", e); + } + } + + private File createTestObject(String objectName, String expString){ + DecimalFormatSymbols dfs= new DecimalFormatSymbols(); + dfs.setExponentSeparator(expString); + dfs.setCurrencySymbol("*SpecialCurrencySymbol*"); + logln(" The special exponent separator is set : " + dfs.getExponentSeparator()); + logln(" The special currency symbol is set : " + dfs.getCurrencySymbol()); + + // 6345659: create a test object in the test.class dir where test user has a write permission. + File file = new File(System.getProperty("test.class", "."), objectName); + try (FileOutputStream ostream = new FileOutputStream(file)) { + ObjectOutputStream p = new ObjectOutputStream(ostream); + p.writeObject(dfs); + //System.out.println(" The special currency symbol is set : " + dfs.getCurrencySymbol()); + return file; + } catch (Exception e){ + errln("Test Malfunction in DFSSerialization: Exception while creating an object"); + /* + * logically should not throw this exception as errln throws exception + * if not thrown yet - but in case errln got changed + */ + throw new RuntimeException("Test Malfunction: re-throwing the exception", e); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/DFSSerialization142.java b/jdk/test/java/text/Format/NumberFormat/DFSSerialization142.java new file mode 100644 index 00000000000..4a5e873ee23 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DFSSerialization142.java @@ -0,0 +1,54 @@ +/* + * 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. + */ + +/* + * No at-test for this test, because it needs to be run on JDK 1.4.2 + * Instead, the resulting serialized file + * DecimalFormatSymbols.142 is archived. + */ + +import java.awt.*; +import java.text.*; +import java.util.*; +import java.io.*; + +public class DFSSerialization142 { + + public static void main(String[] args) + { + try { + + DecimalFormatSymbols dfs= new DecimalFormatSymbols(); + System.out.println("Default currency symbol in the default locale : " + dfs.getCurrencySymbol()); + dfs.setCurrencySymbol("*SpecialCurrencySymbol*"); + System.out.println("The special currency symbol is set : " + dfs.getCurrencySymbol()); + FileOutputStream ostream = new FileOutputStream("DecimalFormatSymbols.142"); + ObjectOutputStream p = new ObjectOutputStream(ostream); + p.writeObject(dfs); + ostream.close(); + System.out.println("DecimalFormatSymbols saved ok."); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/DecimalFormat.114.txt b/jdk/test/java/text/Format/NumberFormat/DecimalFormat.114.txt new file mode 100644 index 00000000000..efa6df41419 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormat.114.txt @@ -0,0 +1,54 @@ +# +# Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized DecimalFormat for SerializationLoadTest. + +aced000573720012436865636b446563696d616c466f726d6174aa9218d3b530 +540a0200014c000a5f646563466f726d61747400194c6a6176612f746578742f +446563696d616c466f726d61743b7870737200176a6176612e746578742e4465 +63696d616c466f726d61740bff0362d872303a0200085a001b646563696d616c +536570617261746f72416c7761797353686f776e42000c67726f7570696e6753 +697a6549000a6d756c7469706c6965724c000e6e656761746976655072656669 +787400124c6a6176612f6c616e672f537472696e673b4c000e6e656761746976 +655375666669787400124c6a6176612f6c616e672f537472696e673b4c000e70 +6f7369746976655072656669787400124c6a6176612f6c616e672f537472696e +673b4c000e706f7369746976655375666669787400124c6a6176612f6c616e67 +2f537472696e673b4c000773796d626f6c737400204c6a6176612f746578742f +446563696d616c466f726d617453796d626f6c733b787200166a6176612e7465 +78742e4e756d626572466f726d6174dff6b3bf137d07e80200065a000c67726f +7570696e67557365644200116d61784672616374696f6e446967697473420010 +6d6178496e74656765724469676974734200116d696e4672616374696f6e4469 +676974734200106d696e496e74656765724469676974735a0010706172736549 +6e74656765724f6e6c79787200106a6176612e746578742e466f726d6174fbd8 +bc12e90f1843020000787001037f0001000003000000017400012d7400007400 +007400007372001e6a6176612e746578742e446563696d616c466f726d617453 +796d626f6c73501d17990868939c02000c430010646563696d616c5365706172 +61746f72430005646967697443001167726f7570696e67536570617261746f72 +4300096d696e75735369676e4300107061747465726e536570617261746f7243 +00077065724d696c6c43000770657263656e744300097a65726f44696769744c +00034e614e7400124c6a6176612f6c616e672f537472696e673b4c000e637572 +72656e637953796d626f6c7400124c6a6176612f6c616e672f537472696e673b +4c0008696e66696e6974797400124c6a6176612f6c616e672f537472696e673b +4c0012696e746c43757272656e637953796d626f6c7400124c6a6176612f6c61 +6e672f537472696e673b7870002e0023002c002d003b203000250030740003ef +bfbd74000124740003e2889e740003555344 diff --git a/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt new file mode 100644 index 00000000000..6707e375a99 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt @@ -0,0 +1,39 @@ +# +# Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized DecimalFormatSymbols for SerializationLoadTest. + +aced000573720019436865636b446563696d616c466f726d617453796d626f6c +737763237e1aa359bb0200014c00115f646563466f726d617453796d626f6c73 +7400204c6a6176612f746578742f446563696d616c466f726d617453796d626f +6c733b78707372001e6a6176612e746578742e446563696d616c466f726d6174 +53796d626f6c73501d17990868939c02000c430010646563696d616c53657061 +7261746f72430005646967697443001167726f7570696e67536570617261746f +724300096d696e75735369676e4300107061747465726e536570617261746f72 +4300077065724d696c6c43000770657263656e744300097a65726f4469676974 +4c00034e614e7400124c6a6176612f6c616e672f537472696e673b4c000e6375 +7272656e637953796d626f6c7400124c6a6176612f6c616e672f537472696e67 +3b4c0008696e66696e6974797400124c6a6176612f6c616e672f537472696e67 +3b4c0012696e746c43757272656e637953796d626f6c7400124c6a6176612f6c +616e672f537472696e673b7870002e0023002c002d003b203000250030740003 +efbfbd74000124740003e2889e740003555344 diff --git a/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt new file mode 100644 index 00000000000..723f107b402 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt @@ -0,0 +1,42 @@ +# +# Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized DecimalFormatSymbols for SerializationLoadTest. + +aced00057372001e6a6176612e746578742e446563696d616c466f726d617453 +796d626f6c73501d17990868939c020010430010646563696d616c5365706172 +61746f72430005646967697443000b6578706f6e656e7469616c43001167726f +7570696e67536570617261746f724300096d696e75735369676e4300116d6f6e +6574617279536570617261746f724300107061747465726e536570617261746f +724300077065724d696c6c43000770657263656e7449001573657269616c5665 +7273696f6e4f6e53747265616d4300097a65726f44696769744c00034e614e74 +00124c6a6176612f6c616e672f537472696e673b4c000e63757272656e637953 +796d626f6c71007e00014c0008696e66696e69747971007e00014c0012696e74 +6c43757272656e637953796d626f6c71007e00014c00066c6f63616c65740012 +4c6a6176612f7574696c2f4c6f63616c653b7870002e00230045002c002d002e +003b20300025000000020030740003efbfbd7400172a5370656369616c437572 +72656e637953796d626f6c2a740003e2889e740003434e59737200106a617661 +2e7574696c2e4c6f63616c657ef811609c30f9ec03000449000868617368636f +64654c0007636f756e74727971007e00014c00086c616e677561676571007e00 +014c000776617269616e7471007e00017870ffffffff740002434e7400027a68 +74000078 diff --git a/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java new file mode 100644 index 00000000000..fcda5b863b4 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test International Decimal Format API + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestDecimalFormatAPI extends IntlTest +{ + public static void main(String[] args) throws Exception { + new IntlTestDecimalFormatAPI().run(args); + } + + // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage. + public void TestAPI() + { + Locale reservedLocale = Locale.getDefault(); + try { + logln("DecimalFormat API test---"); logln(""); + Locale.setDefault(Locale.ENGLISH); + + // ======= Test constructors + + logln("Testing DecimalFormat constructors"); + + DecimalFormat def = new DecimalFormat(); + + final String pattern = new String("#,##0.# FF"); + DecimalFormat pat = null; + try { + pat = new DecimalFormat(pattern); + } + catch (IllegalArgumentException e) { + errln("ERROR: Could not create DecimalFormat (pattern)"); + } + + DecimalFormatSymbols symbols = + new DecimalFormatSymbols(Locale.FRENCH); + + DecimalFormat cust1 = new DecimalFormat(pattern, symbols); + + // ======= Test clone(), assignment, and equality + + logln("Testing clone() and equality operators"); + + Format clone = (Format) def.clone(); + if( ! def.equals(clone)) { + errln("ERROR: Clone() failed"); + } + + // ======= Test various format() methods + + logln("Testing various format() methods"); + +// final double d = -10456.0037; // this appears as + // -10456.003700000001 on NT +// final double d = -1.04560037e-4; // this appears as + // -1.0456003700000002E-4 on NT + final double d = -10456.00370000000000; // this works! + final long l = 100000000; + logln("" + d + " is the double value"); + + StringBuffer res1 = new StringBuffer(); + StringBuffer res2 = new StringBuffer(); + StringBuffer res3 = new StringBuffer(); + StringBuffer res4 = new StringBuffer(); + FieldPosition pos1 = new FieldPosition(0); + FieldPosition pos2 = new FieldPosition(0); + FieldPosition pos3 = new FieldPosition(0); + FieldPosition pos4 = new FieldPosition(0); + + res1 = def.format(d, res1, pos1); + logln("" + d + " formatted to " + res1); + + res2 = pat.format(l, res2, pos2); + logln("" + l + " formatted to " + res2); + + res3 = cust1.format(d, res3, pos3); + logln("" + d + " formatted to " + res3); + + res4 = cust1.format(l, res4, pos4); + logln("" + l + " formatted to " + res4); + + // ======= Test parse() + + logln("Testing parse()"); + + String text = new String("-10,456.0037"); + ParsePosition pos = new ParsePosition(0); + String patt = new String("#,##0.#"); + pat.applyPattern(patt); + double d2 = pat.parse(text, pos).doubleValue(); + if(d2 != d) { + errln("ERROR: Roundtrip failed (via parse(" + + d2 + " != " + d + ")) for " + text); + } + logln(text + " parsed into " + (long) d2); + + // ======= Test getters and setters + + logln("Testing getters and setters"); + + final DecimalFormatSymbols syms = pat.getDecimalFormatSymbols(); + def.setDecimalFormatSymbols(syms); + if(!pat.getDecimalFormatSymbols().equals( + def.getDecimalFormatSymbols())) { + errln("ERROR: set DecimalFormatSymbols() failed"); + } + + String posPrefix; + pat.setPositivePrefix("+"); + posPrefix = pat.getPositivePrefix(); + logln("Positive prefix (should be +): " + posPrefix); + if(posPrefix != "+") { + errln("ERROR: setPositivePrefix() failed"); + } + + String negPrefix; + pat.setNegativePrefix("-"); + negPrefix = pat.getNegativePrefix(); + logln("Negative prefix (should be -): " + negPrefix); + if(negPrefix != "-") { + errln("ERROR: setNegativePrefix() failed"); + } + + String posSuffix; + pat.setPositiveSuffix("_"); + posSuffix = pat.getPositiveSuffix(); + logln("Positive suffix (should be _): " + posSuffix); + if(posSuffix != "_") { + errln("ERROR: setPositiveSuffix() failed"); + } + + String negSuffix; + pat.setNegativeSuffix("~"); + negSuffix = pat.getNegativeSuffix(); + logln("Negative suffix (should be ~): " + negSuffix); + if(negSuffix != "~") { + errln("ERROR: setNegativeSuffix() failed"); + } + + long multiplier = 0; + pat.setMultiplier(8); + multiplier = pat.getMultiplier(); + logln("Multiplier (should be 8): " + multiplier); + if(multiplier != 8) { + errln("ERROR: setMultiplier() failed"); + } + + int groupingSize = 0; + pat.setGroupingSize(2); + groupingSize = pat.getGroupingSize(); + logln("Grouping size (should be 2): " + (long) groupingSize); + if(groupingSize != 2) { + errln("ERROR: setGroupingSize() failed"); + } + + pat.setDecimalSeparatorAlwaysShown(true); + boolean tf = pat.isDecimalSeparatorAlwaysShown(); + logln("DecimalSeparatorIsAlwaysShown (should be true) is " + + (tf ? "true" : "false")); + if(tf != true) { + errln("ERROR: setDecimalSeparatorAlwaysShown() failed"); + } + + String funkyPat; + funkyPat = pat.toPattern(); + logln("Pattern is " + funkyPat); + + String locPat; + locPat = pat.toLocalizedPattern(); + logln("Localized pattern is " + locPat); + + // ======= Test applyPattern() + + logln("Testing applyPattern()"); + + String p1 = new String("#,##0.0#;(#,##0.0#)"); + logln("Applying pattern " + p1); + pat.applyPattern(p1); + String s2; + s2 = pat.toPattern(); + logln("Extracted pattern is " + s2); + if( ! s2.equals(p1) ) { + errln("ERROR: toPattern() result did not match " + + "pattern applied"); + } + + String p2 = new String("#,##0.0# FF;(#,##0.0# FF)"); + logln("Applying pattern " + p2); + pat.applyLocalizedPattern(p2); + String s3; + s3 = pat.toLocalizedPattern(); + logln("Extracted pattern is " + s3); + if( ! s3.equals(p2) ) { + errln("ERROR: toLocalizedPattern() result did not match " + + "pattern applied"); + } + + // ======= Test getStaticClassID() + +// logln("Testing instanceof()"); + +// try { +// NumberFormat test = new DecimalFormat(); + +// if (! (test instanceof DecimalFormat)) { +// errln("ERROR: instanceof failed"); +// } +// } +// catch (Exception e) { +// errln("ERROR: Couldn't create a DecimalFormat"); +// } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java new file mode 100644 index 00000000000..cd19fee1e35 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test International Decimal Format Symbols + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestDecimalFormatSymbols extends IntlTest +{ + public static void main(String[] args) throws Exception { + new IntlTestDecimalFormatSymbols().run(args); + } + + // Test the API of DecimalFormatSymbols; primarily a simple get/set set. + public void TestSymbols() + { + DecimalFormatSymbols fr = new DecimalFormatSymbols(Locale.FRENCH); + + DecimalFormatSymbols en = new DecimalFormatSymbols(Locale.ENGLISH); + + if(en.equals(fr)) { + errln("ERROR: English DecimalFormatSymbols equal to French"); + } + + // just do some VERY basic tests to make sure that get/set work + + char zero = en.getZeroDigit(); + fr.setZeroDigit(zero); + if(fr.getZeroDigit() != en.getZeroDigit()) { + errln("ERROR: get/set ZeroDigit failed"); + } + + char group = en.getGroupingSeparator(); + fr.setGroupingSeparator(group); + if(fr.getGroupingSeparator() != en.getGroupingSeparator()) { + errln("ERROR: get/set GroupingSeparator failed"); + } + + char decimal = en.getDecimalSeparator(); + fr.setDecimalSeparator(decimal); + if(fr.getDecimalSeparator() != en.getDecimalSeparator()) { + errln("ERROR: get/set DecimalSeparator failed"); + } + + char perMill = en.getPerMill(); + fr.setPerMill(perMill); + if(fr.getPerMill() != en.getPerMill()) { + errln("ERROR: get/set PerMill failed"); + } + + char percent = en.getPercent(); + fr.setPercent(percent); + if(fr.getPercent() != en.getPercent()) { + errln("ERROR: get/set Percent failed"); + } + + char digit = en.getDigit(); + fr.setDigit(digit); + if(fr.getPercent() != en.getPercent()) { + errln("ERROR: get/set Percent failed"); + } + + char patternSeparator = en.getPatternSeparator(); + fr.setPatternSeparator(patternSeparator); + if(fr.getPatternSeparator() != en.getPatternSeparator()) { + errln("ERROR: get/set PatternSeparator failed"); + } + + String infinity = en.getInfinity(); + fr.setInfinity(infinity); + String infinity2 = fr.getInfinity(); + if(! infinity.equals(infinity2)) { + errln("ERROR: get/set Infinity failed"); + } + + String nan = en.getNaN(); + fr.setNaN(nan); + String nan2 = fr.getNaN(); + if(! nan.equals(nan2)) { + errln("ERROR: get/set NaN failed"); + } + + char minusSign = en.getMinusSign(); + fr.setMinusSign(minusSign); + if(fr.getMinusSign() != en.getMinusSign()) { + errln("ERROR: get/set MinusSign failed"); + } + +// char exponential = en.getExponentialSymbol(); +// fr.setExponentialSymbol(exponential); +// if(fr.getExponentialSymbol() != en.getExponentialSymbol()) { +// errln("ERROR: get/set Exponential failed"); +// } + + DecimalFormatSymbols foo = new DecimalFormatSymbols(); + + en = (DecimalFormatSymbols) fr.clone(); + + if(! en.equals(fr)) { + errln("ERROR: Clone failed"); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java b/jdk/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java new file mode 100644 index 00000000000..ab1069bdfc2 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test International Number Format API + */ +/* +(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved +(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.util.*; + +public class IntlTestNumberFormatAPI extends IntlTest +{ + public static void main(String[] args) throws Exception { + new IntlTestNumberFormatAPI().run(args); + } + + // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage. + public void TestAPI() + { + Locale reservedLocale = Locale.getDefault(); + try { + logln("NumberFormat API test---"); logln(""); + Locale.setDefault(Locale.ENGLISH); + + // ======= Test constructors + + logln("Testing NumberFormat constructors"); + + NumberFormat def = NumberFormat.getInstance(); + + NumberFormat fr = NumberFormat.getInstance(Locale.FRENCH); + + NumberFormat cur = NumberFormat.getCurrencyInstance(); + + NumberFormat cur_fr = + NumberFormat.getCurrencyInstance(Locale.FRENCH); + + NumberFormat per = NumberFormat.getPercentInstance(); + + NumberFormat per_fr = + NumberFormat.getPercentInstance(Locale.FRENCH); + + // ======= Test equality + + logln("Testing equality operator"); + + if( per_fr.equals(cur_fr) ) { + errln("ERROR: == failed"); + } + + // ======= Test various format() methods + + logln("Testing various format() methods"); + +// final double d = -10456.0037; // this appears as + // -10456.003700000001 on NT +// final double d = -1.04560037e-4; // this appears as + // -1.0456003700000002E-4 on NT + final double d = -10456.00370000000000; // this works! + final long l = 100000000; + + String res1 = new String(); + String res2 = new String(); + StringBuffer res3 = new StringBuffer(); + StringBuffer res4 = new StringBuffer(); + StringBuffer res5 = new StringBuffer(); + StringBuffer res6 = new StringBuffer(); + FieldPosition pos1 = new FieldPosition(0); + FieldPosition pos2 = new FieldPosition(0); + FieldPosition pos3 = new FieldPosition(0); + FieldPosition pos4 = new FieldPosition(0); + + res1 = cur_fr.format(d); + logln( "" + d + " formatted to " + res1); + + res2 = cur_fr.format(l); + logln("" + l + " formatted to " + res2); + + res3 = cur_fr.format(d, res3, pos1); + logln( "" + d + " formatted to " + res3); + + res4 = cur_fr.format(l, res4, pos2); + logln("" + l + " formatted to " + res4); + + res5 = cur_fr.format(d, res5, pos3); + logln("" + d + " formatted to " + res5); + + res6 = cur_fr.format(l, res6, pos4); + logln("" + l + " formatted to " + res6); + + + // ======= Test parse() + + logln("Testing parse()"); + +// String text = new String("-10,456.0037"); + String text = new String("-10456,0037"); + ParsePosition pos = new ParsePosition(0); + ParsePosition pos01 = new ParsePosition(0); + double d1 = ((Number)fr.parseObject(text, pos)).doubleValue(); + if(d1 != d) { + errln("ERROR: Roundtrip failed (via parse()) for " + text); + } + logln(text + " parsed into " + d1); + + double d2 = fr.parse(text, pos01).doubleValue(); + if(d2 != d) { + errln("ERROR: Roundtrip failed (via parse()) for " + text); + } + logln(text + " parsed into " + d2); + + double d3 = 0; + try { + d3 = fr.parse(text).doubleValue(); + } + catch (ParseException e) { + errln("ERROR: parse() failed"); + } + if(d3 != d) { + errln("ERROR: Roundtrip failed (via parse()) for " + text); + } + logln(text + " parsed into " + d3); + + + // ======= Test getters and setters + + logln("Testing getters and setters"); + + final Locale[] locales = NumberFormat.getAvailableLocales(); + long count = locales.length; + logln("Got " + count + " locales" ); + for(int i = 0; i < count; i++) { + String name; + name = locales[i].getDisplayName(); + logln(name); + } + + fr.setParseIntegerOnly( def.isParseIntegerOnly() ); + if(fr.isParseIntegerOnly() != def.isParseIntegerOnly() ) { + errln("ERROR: setParseIntegerOnly() failed"); + } + + fr.setGroupingUsed( def.isGroupingUsed() ); + if(fr.isGroupingUsed() != def.isGroupingUsed() ) { + errln("ERROR: setGroupingUsed() failed"); + } + + fr.setMaximumIntegerDigits( def.getMaximumIntegerDigits() ); + if(fr.getMaximumIntegerDigits() != def.getMaximumIntegerDigits() ) { + errln("ERROR: setMaximumIntegerDigits() failed"); + } + + fr.setMinimumIntegerDigits( def.getMinimumIntegerDigits() ); + if(fr.getMinimumIntegerDigits() != def.getMinimumIntegerDigits() ) { + errln("ERROR: setMinimumIntegerDigits() failed"); + } + + fr.setMaximumFractionDigits( def.getMaximumFractionDigits() ); + if(fr.getMaximumFractionDigits() != def.getMaximumFractionDigits() ) { + errln("ERROR: setMaximumFractionDigits() failed"); + } + + fr.setMinimumFractionDigits( def.getMinimumFractionDigits() ); + if(fr.getMinimumFractionDigits() != def.getMinimumFractionDigits() ) { + errln("ERROR: setMinimumFractionDigits() failed"); + } + + // ======= Test getStaticClassID() + +// logln("Testing instanceof()"); + +// try { +// NumberFormat test = new DecimalFormat(); + +// if (! (test instanceof DecimalFormat)) { +// errln("ERROR: instanceof failed"); +// } +// } +// catch (Exception e) { +// errln("ERROR: Couldn't create a DecimalFormat"); +// } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt new file mode 100644 index 00000000000..d27bb94eb69 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt @@ -0,0 +1,57 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized NumberFormat for NumberRegression. + +aced0005737200176a6176612e746578742e446563696d616c466f726d61740b +ff0362d872303a02000b5a001b646563696d616c536570617261746f72416c77 +61797353686f776e42000c67726f7570696e6753697a654200116d696e457870 +6f6e656e7444696769747349000a6d756c7469706c6965724900157365726961 +6c56657273696f6e4f6e53747265616d5a00167573654578706f6e656e746961 +6c4e6f746174696f6e4c000e6e656761746976655072656669787400124c6a61 +76612f6c616e672f537472696e673b4c000e6e65676174697665537566666978 +71007e00014c000e706f73697469766550726566697871007e00014c000e706f +73697469766553756666697871007e00014c000773796d626f6c737400204c6a +6176612f746578742f446563696d616c466f726d617453796d626f6c733b7872 +00166a6176612e746578742e4e756d626572466f726d6174dff6b3bf137d07e8 +03000b5a000c67726f7570696e67557365644200116d61784672616374696f6e +4469676974734200106d6178496e74656765724469676974734900156d617869 +6d756d4672616374696f6e4469676974734900146d6178696d756d496e746567 +65724469676974734200116d696e4672616374696f6e4469676974734200106d +696e496e74656765724469676974734900156d696e696d756d4672616374696f +6e4469676974734900146d696e696d756d496e74656765724469676974735a00 +107061727365496e74656765724f6e6c7949001573657269616c56657273696f +6e4f6e53747265616d787200106a6176612e746578742e466f726d6174fbd8bc +12e90f18430200007870017f7f00000123000001217f7f000001240000012200 +00000001780003000000000100000001007400012d7400007400007400007372 +001e6a6176612e746578742e446563696d616c466f726d617453796d626f6c73 +501d17990868939c02000f430010646563696d616c536570617261746f724300 +05646967697443000b6578706f6e656e7469616c43001167726f7570696e6753 +6570617261746f724300096d696e75735369676e4300116d6f6e657461727953 +6570617261746f724300107061747465726e536570617261746f724300077065 +724d696c6c43000770657263656e7449001573657269616c56657273696f6e4f +6e53747265616d4300097a65726f44696769744c00034e614e71007e00014c00 +0e63757272656e637953796d626f6c71007e00014c0008696e66696e69747971 +007e00014c0012696e746c43757272656e637953796d626f6c71007e00017870 +002e00230045002c002d002e003b20300025000000010030740003efbfbd7400 +0124740003e2889e740003555344 diff --git a/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt new file mode 100644 index 00000000000..8da4dde6bd1 --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt @@ -0,0 +1,57 @@ +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Hex dump of a serialized NumberFormat for NumberRegression. + +aced0005737200176a6176612e746578742e446563696d616c466f726d61740b +ff0362d872303a02000b5a001b646563696d616c536570617261746f72416c77 +61797353686f776e42000c67726f7570696e6753697a654200116d696e457870 +6f6e656e7444696769747349000a6d756c7469706c6965724900157365726961 +6c56657273696f6e4f6e53747265616d5a00167573654578706f6e656e746961 +6c4e6f746174696f6e4c000e6e656761746976655072656669787400124c6a61 +76612f6c616e672f537472696e673b4c000e6e65676174697665537566666978 +71007e00014c000e706f73697469766550726566697871007e00014c000e706f +73697469766553756666697871007e00014c000773796d626f6c737400204c6a +6176612f746578742f446563696d616c466f726d617453796d626f6c733b7872 +00166a6176612e746578742e4e756d626572466f726d6174dff6b3bf137d07e8 +03000b5a000c67726f7570696e67557365644200116d61784672616374696f6e +4469676974734200106d6178496e74656765724469676974734900156d617869 +6d756d4672616374696f6e4469676974734900146d6178696d756d496e746567 +65724469676974734200116d696e4672616374696f6e4469676974734200106d +696e496e74656765724469676974734900156d696e696d756d4672616374696f +6e4469676974734900146d696e696d756d496e74656765724469676974735a00 +107061727365496e74656765724f6e6c7949001573657269616c56657273696f +6e4f6e53747265616d787200106a6176612e746578742e466f726d6174fbd8bc +12e90f18430200007870017f7f00000314000003127f7f000003130000031100 +00000001780003000000000100000001007400012d7400007400007400007372 +001e6a6176612e746578742e446563696d616c466f726d617453796d626f6c73 +501d17990868939c02000f430010646563696d616c536570617261746f724300 +05646967697443000b6578706f6e656e7469616c43001167726f7570696e6753 +6570617261746f724300096d696e75735369676e4300116d6f6e657461727953 +6570617261746f724300107061747465726e536570617261746f724300077065 +724d696c6c43000770657263656e7449001573657269616c56657273696f6e4f +6e53747265616d4300097a65726f44696769744c00034e614e71007e00014c00 +0e63757272656e637953796d626f6c71007e00014c0008696e66696e69747971 +007e00014c0012696e746c43757272656e637953796d626f6c71007e00017870 +002e00230045002c002d002e003b20300025000000010030740003efbfbd7400 +0124740003e2889e740003555344 diff --git a/jdk/test/java/text/Format/NumberFormat/NumberFormatRounding.java b/jdk/test/java/text/Format/NumberFormat/NumberFormatRounding.java new file mode 100644 index 00000000000..895d885ff2e --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberFormatRounding.java @@ -0,0 +1,130 @@ +/* + * 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. + */ + +/** + * @test + * @bug 4092330 6246348 + * @summary Tests for rounding mode in NumberFormat + */ + +import java.math.*; +import java.text.*; + +public class NumberFormatRounding { + + static final String AE = "ArithmeticException"; + + static final double src[] = {5.5, 2.5, 1.6, 1.1, 1.0, -1.0, -1.1, -1.6, -2.5, -5.5, + 5.501, -5.501, 5.500, -5.500, 1.001, -1.001, 4.501, -4.501, 4.500, -4.500}; + static final String up[] = {"6", "3", "2", "2", "1", "-1", "-2", "-2", "-3", "-6", + "6", "-6", "6", "-6", "2", "-2", "5", "-5", "5", "-5"}; + static final String down[] = {"5", "2", "1", "1", "1", "-1", "-1", "-1", "-2", "-5", + "5", "-5", "5", "-5", "1", "-1", "4", "-4", "4", "-4"}; + static final String ceiling[] = {"6", "3", "2", "2", "1", "-1", "-1", "-1", "-2", "-5", + "6", "-5", "6", "-5", "2", "-1", "5", "-4", "5", "-4"}; + static final String floor[] = {"5", "2", "1", "1", "1", "-1", "-2", "-2", "-3", "-6", + "5", "-6", "5", "-6", "1", "-2", "4", "-5", "4", "-5"}; + static final String half_up[] = {"6", "3", "2", "1", "1", "-1", "-1", "-2", "-3", "-6", + "6", "-6", "6", "-6", "1", "-1", "5", "-5", "5", "-5"}; + static final String half_down[] = {"5", "2", "2", "1", "1", "-1", "-1", "-2", "-2", "-5", + "6", "-6", "5", "-5", "1", "-1", "5", "-5", "4", "-4"}; + static final String half_even[] = {"6", "2", "2", "1", "1", "-1", "-1", "-2", "-2", "-6", + "6", "-6", "6", "-6", "1", "-1", "5", "-5", "4", "-4"}; + static final String unnecessary[] = {AE, AE, AE, AE, "1", "-1", AE, AE, AE, AE, + AE, AE, AE, AE, AE, AE, AE, AE, AE, AE}; + + public static void main(String[] args) { + basicTest(); + + roundTest(RoundingMode.UP, up); + roundTest(RoundingMode.DOWN, down); + roundTest(RoundingMode.CEILING, ceiling); + roundTest(RoundingMode.FLOOR, floor); + roundTest(RoundingMode.HALF_UP, half_up); + roundTest(RoundingMode.HALF_DOWN, half_down); + roundTest(RoundingMode.HALF_EVEN, half_even); + roundTest(RoundingMode.UNNECESSARY, unnecessary); + } + + static void basicTest() { + NumberFormat nf = NumberFormat.getIntegerInstance(); + + if (nf.getRoundingMode() != RoundingMode.HALF_EVEN) { + throw new RuntimeException("default rounding is not HALF_EVEN"); + } + + try { + nf.setRoundingMode(null); + throw new RuntimeException( + "NullPointerException is not thrown by calling setRoundingMode(null)"); + } catch (NullPointerException npe) { + // continue testing + } + + ChoiceFormat cf = new ChoiceFormat(""); + + try { + cf.setRoundingMode(RoundingMode.HALF_EVEN); + throw new RuntimeException( + "UnsupportedOperationException is not thrown by calling setRoundingMode()"); + } catch (UnsupportedOperationException uoe) { + // continue testing + } + + try { + cf.getRoundingMode(); + throw new RuntimeException( + "UnsupportedOperationException is not thrown by calling getRoundingMode()"); + } catch (UnsupportedOperationException uoe) { + // continue testing + } + } + + static void roundTest(RoundingMode rm, String[] expected) { + NumberFormat nf = NumberFormat.getIntegerInstance(); + nf.setRoundingMode(rm); + + if (nf.getRoundingMode() != rm) { + throw new RuntimeException("set rounding mode is not returned by get method"); + } + + for (int i = 0; i < src.length; i ++) { + String result = null; + try { + result = nf.parse(nf.format(src[i])).toString(); + if (!result.equals(expected[i])) { + throw new RuntimeException("rounding test #"+i+" failed. mode: "+rm+" src: "+src[i]+" expected: "+expected[i]+" result: "+result); + } + } catch (ArithmeticException ae) { + if (expected[i].equals(AE)) { + continue; + } else { + result = AE; + throw new RuntimeException("rounding test #"+i+" failed. mode: "+rm+" src: "+src[i]+" expected: "+expected[i]+" result: "+result); + } + } catch (ParseException pe) { + throw new RuntimeException("ParseException ocurred.", pe); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/NumberRegression.java b/jdk/test/java/text/Format/NumberFormat/NumberRegression.java new file mode 100644 index 00000000000..674fdd619ca --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberRegression.java @@ -0,0 +1,1824 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4052223 4059870 4061302 4062486 4066646 4068693 4070798 4071005 4071014 + * 4071492 4071859 4074454 4074620 4075713 4083018 4086575 4087244 4087245 + * 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713 + * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840 + * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198 + * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742 + * 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577 + * @summary Regression tests for NumberFormat and associated classes + * @library /java/text/testlib + * @build IntlTest HexDumpReader + * @modules java.base/sun.util.resources + * @compile -XDignore.symbol.file NumberRegression.java + * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberRegression + */ + +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.util.*; +import java.math.BigDecimal; +import java.io.*; +import java.math.BigInteger; +import sun.util.resources.LocaleData; + +public class NumberRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new NumberRegression().run(args); + } + + /** + * NumberFormat.equals comparing with null should always return false. + */ + public void Test4075713(){ + + try { + MyNumberFormatTest tmp = new MyNumberFormatTest(); + if (!tmp.equals(null)) + logln("NumberFormat.equals passed"); + } catch (NullPointerException e) { + errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception"); + } + } + + /** + * NumberFormat.equals comparing two obj equal even the setGroupingUsed + * flag is different. + */ + public void Test4074620() { + + MyNumberFormatTest nf1 = new MyNumberFormatTest(); + MyNumberFormatTest nf2 = new MyNumberFormatTest(); + + nf1.setGroupingUsed(false); + nf2.setGroupingUsed(true); + + if (nf1.equals(nf2)) errln("Test for bug 4074620 failed"); + else logln("Test for bug 4074620 passed."); + return; + } + + + /** + * DecimalFormat.format() incorrectly uses maxFractionDigits setting. + */ + + public void Test4088161 (){ + DecimalFormat df = new DecimalFormat(); + double d = 100; + df.setMinimumFractionDigits(0); + df.setMaximumFractionDigits(16); + StringBuffer sBuf1 = new StringBuffer(""); + FieldPosition fp1 = new FieldPosition(0); + logln("d = " + d); + logln("maxFractionDigits = " + df.getMaximumFractionDigits()); + logln(" format(d) = '" + df.format(d, sBuf1, fp1) + "'"); + df.setMaximumFractionDigits(17); + StringBuffer sBuf2 = new StringBuffer(""); + FieldPosition fp2 = new FieldPosition(0); + logln("maxFractionDigits = " + df.getMaximumFractionDigits()); + df.format(d, sBuf2, fp2); + String expected = Locale.getDefault().equals(new Locale("hi", "IN")) ? + "\u0967\u0966\u0966" : "100"; + if (!sBuf2.toString().equals(expected)) + errln(" format(d) = '" + sBuf2 + "'"); + } + /** + * DecimalFormatSymbols should be cloned in the ctor DecimalFormat. + * DecimalFormat(String, DecimalFormatSymbols). + */ + public void Test4087245 (){ + DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(); + DecimalFormat df = new DecimalFormat("#,##0.0", symbols); + long n = 123; + StringBuffer buf1 = new StringBuffer(); + StringBuffer buf2 = new StringBuffer(); + logln("format(" + n + ") = " + + df.format(n, buf1, new FieldPosition(0))); + symbols.setDecimalSeparator('p'); // change value of field + logln("format(" + n + ") = " + + df.format(n, buf2, new FieldPosition(0))); + if (!buf1.toString().equals(buf2.toString())) + errln("Test for bug 4087245 failed"); + } + /** + * DecimalFormat.format() incorrectly formats 0.0 + */ + public void Test4087535 () + { + DecimalFormat df = new DecimalFormat(); + df.setMinimumIntegerDigits(0); + + double n = 0; + String buffer = new String(); + buffer = df.format(n); + if (buffer.length() == 0) + errln(n + ": '" + buffer + "'"); + n = 0.1; + buffer = df.format(n); + if (buffer.length() == 0) + errln(n + ": '" + buffer + "'"); + } + + /** + * DecimalFormat.format fails when groupingSize is set to 0. + */ + public void Test4088503 (){ + DecimalFormat df = new DecimalFormat(); + df.setGroupingSize(0); + StringBuffer sBuf = new StringBuffer(""); + FieldPosition fp = new FieldPosition(0); + try { + logln(df.format(123, sBuf, fp).toString()); + } catch (Exception foo) { + errln("Test for bug 4088503 failed."); + } + + } + /** + * NumberFormat.getCurrencyInstance is wrong. + */ + public void Test4066646 () { + float returnfloat = 0.0f; + assignFloatValue(2.04f); + assignFloatValue(2.03f); + assignFloatValue(2.02f); + assignFloatValue(0.0f); + } + + public float assignFloatValue(float returnfloat) + { + logln(" VALUE " + returnfloat); + NumberFormat nfcommon = NumberFormat.getCurrencyInstance(Locale.US); + nfcommon.setGroupingUsed(false); + + String stringValue = nfcommon.format(returnfloat).substring(1); + if (Float.valueOf(stringValue).floatValue() != returnfloat) + errln(" DISPLAYVALUE " + stringValue); + return returnfloat; + } // End Of assignFloatValue() + + /** + * DecimalFormat throws exception when parsing "0" + */ + public void Test4059870() { + DecimalFormat format = new DecimalFormat("00"); + try { + logln(format.parse("0").toString()); + } catch (Exception e) { errln("Test for bug 4059870 failed : " + e); } + } + /** + * DecimalFormatSymbol.equals should always return false when + * comparing with null. + */ + + public void Test4083018 (){ + DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(); + try { + if (!dfs.equals(null)) + logln("Test Passed!"); + } catch (Exception foo) { + errln("Test for bug 4083018 failed => Message : " + foo.getMessage()); + } + } + /** + * DecimalFormat does not round up correctly. + */ + public void Test4071492 (){ + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + double x = 0.00159999; + NumberFormat nf = NumberFormat.getInstance(); + nf.setMaximumFractionDigits(4); + String out = nf.format(x); + logln("0.00159999 formats with 4 fractional digits to " + out); + String expected = "0.0016"; + if (!out.equals(expected)) + errln("FAIL: Expected " + expected); + Locale.setDefault(savedLocale); + } + + /** + * A space as a group separator for localized pattern causes + * wrong format. WorkAround : use non-breaking space. + */ + public void Test4086575() { + + NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE); + logln("nf toPattern1: " + ((DecimalFormat)nf).toPattern()); + logln("nf toLocPattern1: " + ((DecimalFormat)nf).toLocalizedPattern()); + + // No group separator + logln("...applyLocalizedPattern ###,00;(###,00) "); + ((DecimalFormat)nf).applyLocalizedPattern("###,00;(###,00)"); + logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern()); + logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern()); + + logln("nf: " + nf.format(1234)); // 1234,00 + logln("nf: " + nf.format(-1234)); // (1234,00) + + // Space as group separator + + logln("...applyLocalizedPattern # ###,00;(# ###,00) "); + ((DecimalFormat)nf).applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)"); + logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern()); + logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern()); + String buffer = nf.format(1234); + if (!buffer.equals("1\u00a0234,00")) + errln("nf : " + buffer); // Expect 1 234,00 + buffer = nf.format(-1234); + if (!buffer.equals("(1\u00a0234,00)")) + errln("nf : " + buffer); // Expect (1 234,00) + + // Erroneously prints: + // 1234,00 , + // (1234,00 ,) + + } + /** + * DecimalFormat.parse returns wrong value + */ + public void Test4068693() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + logln("----- Test Application -----"); + ParsePosition pos; + DecimalFormat df = new DecimalFormat(); + Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0)); + if (!d.toString().equals("123.55456")) { + errln("Result -> " + d.doubleValue()); + } + Locale.setDefault(savedLocale); + } + + /* bugs 4069754, 4067878 + * null pointer thrown when accessing a deserialized DecimalFormat + * object. + */ + public void Test4069754() + { + try { + myformat it = new myformat(); + logln(it.Now()); + FileOutputStream ostream = new FileOutputStream("t.tmp"); + ObjectOutputStream p = new ObjectOutputStream(ostream); + p.writeObject(it); + ostream.close(); + logln("Saved ok."); + + FileInputStream istream = new FileInputStream("t.tmp"); + ObjectInputStream p2 = new ObjectInputStream(istream); + myformat it2 = (myformat)p2.readObject(); + logln(it2.Now()); + istream.close(); + logln("Loaded ok."); + } catch (Exception foo) { + errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage()); + } + } + + /** + * DecimalFormat.applyPattern(String) allows illegal patterns + */ + public void Test4087251 (){ + DecimalFormat df = new DecimalFormat(); + try { + df.applyPattern("#.#.#"); + logln("toPattern() returns \"" + df.toPattern() + "\""); + errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + logln("Caught Illegal Argument Error !"); + } + // Second test; added 5/11/98 when reported to fail on 1.2b3 + try { + df.applyPattern("#0.0#0#0"); + logln("toPattern() returns \"" + df.toPattern() + "\""); + errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + logln("Ok - IllegalArgumentException for #0.0#0#0"); + } + } + + /** + * DecimalFormat.format() loses precision + */ + public void Test4090489 (){ + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + df.setMinimumFractionDigits(10); + df.setGroupingUsed(false); + double d = 1.000000000000001E7; + BigDecimal bd = new BigDecimal(d); + StringBuffer sb = new StringBuffer(""); + FieldPosition fp = new FieldPosition(0); + logln("d = " + d); + logln("BigDecimal.toString(): " + bd.toString()); + df.format(d, sb, fp); + if (!sb.toString().equals("10000000.0000000100")) { + errln("DecimalFormat.format(): " + sb.toString()); + } + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat.format() loses precision + */ + public void Test4090504 () + { + double d = 1; + logln("d = " + d); + DecimalFormat df = new DecimalFormat(); + StringBuffer sb; + FieldPosition fp; + try { + for (int i = 17; i <= 20; i++) { + df.setMaximumFractionDigits(i); + sb = new StringBuffer(""); + fp = new FieldPosition(0); + logln(" getMaximumFractionDigits() = " + i); + logln(" formated: " + df.format(d, sb, fp)); + } + } catch (Exception foo) { + errln("Bug 4090504 regression test failed. Message : " + foo.getMessage()); + } + } + /** + * DecimalFormat.parse(String str, ParsePosition pp) loses precision + */ + public void Test4095713 () + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + String str = "0.1234"; + Double d1 = new Double(str); + Double d2 = (Double) df.parse(str, new ParsePosition(0)); + logln(d1.toString()); + if (d2.doubleValue() != d1.doubleValue()) + errln("Bug 4095713 test failed, new double value : " + d2.doubleValue()); + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat.parse() fails when multiplier is not set to 1 + */ + public void Test4092561 () + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + + String str = Long.toString(Long.MIN_VALUE); + logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString()); + df.setMultiplier(100); + Number num = df.parse(str, new ParsePosition(0)); + if (num.doubleValue() != -9.223372036854776E16) { + errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue()); + } + + df.setMultiplier(-100); + num = df.parse(str, new ParsePosition(0)); + if (num.doubleValue() != 9.223372036854776E16) { + errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue()); + } + + str = Long.toString(Long.MAX_VALUE); + logln("Long.MAX_VALUE : " + df.parse(str, new ParsePosition(0)).toString()); + + df.setMultiplier(100); + num = df.parse(str, new ParsePosition(0)); + if (num.doubleValue() != 9.223372036854776E16) { + errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue()); + } + + df.setMultiplier(-100); + num = df.parse(str, new ParsePosition(0)); + if (num.doubleValue() != -9.223372036854776E16) { + errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue()); + } + + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat: Negative format ignored. + */ + public void Test4092480 () + { + DecimalFormat dfFoo = new DecimalFormat("000"); + + try { + dfFoo.applyPattern("0000;-000"); + if (!dfFoo.toPattern().equals("#0000")) + errln("dfFoo.toPattern : " + dfFoo.toPattern()); + logln(dfFoo.format(42)); + logln(dfFoo.format(-42)); + dfFoo.applyPattern("000;-000"); + if (!dfFoo.toPattern().equals("#000")) + errln("dfFoo.toPattern : " + dfFoo.toPattern()); + logln(dfFoo.format(42)); + logln(dfFoo.format(-42)); + + dfFoo.applyPattern("000;-0000"); + if (!dfFoo.toPattern().equals("#000")) + errln("dfFoo.toPattern : " + dfFoo.toPattern()); + logln(dfFoo.format(42)); + logln(dfFoo.format(-42)); + + dfFoo.applyPattern("0000;-000"); + if (!dfFoo.toPattern().equals("#0000")) + errln("dfFoo.toPattern : " + dfFoo.toPattern()); + logln(dfFoo.format(42)); + logln(dfFoo.format(-42)); + } catch (Exception foo) { + errln("Message " + foo.getMessage()); + } + } + /** + * NumberFormat.getCurrencyInstance() produces format that uses + * decimal separator instead of monetary decimal separator. + * + * Rewrote this test not to depend on the actual pattern. Pattern should + * never contain the monetary separator! Decimal separator in pattern is + * interpreted as monetary separator if currency symbol is seen! + */ + public void Test4087244 () { + Locale de = new Locale("pt", "PT"); + DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(de); + DecimalFormatSymbols sym = df.getDecimalFormatSymbols(); + sym.setMonetaryDecimalSeparator('$'); + df.setDecimalFormatSymbols(sym); + char decSep = sym.getDecimalSeparator(); + char monSep = sym.getMonetaryDecimalSeparator(); + char zero = sym.getZeroDigit(); + if (decSep == monSep) { + errln("ERROR in test: want decimal sep != monetary sep"); + } else { + df.setMinimumIntegerDigits(1); + df.setMinimumFractionDigits(2); + String str = df.format(1.23); + String monStr = "1" + monSep + "23"; + String decStr = "1" + decSep + "23"; + if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) { + logln("OK: 1.23 -> \"" + str + "\" contains \"" + + monStr + "\" and not \"" + decStr + '"'); + } else { + errln("FAIL: 1.23 -> \"" + str + "\", should contain \"" + + monStr + + "\" and not \"" + decStr + '"'); + } + } + } + /** + * Number format data rounding errors for locale FR + */ + public void Test4070798 () { + NumberFormat formatter; + String tempString; + /* User error : + String expectedDefault = "-5\u00a0789,987"; + String expectedCurrency = "5\u00a0789,98 F"; + String expectedPercent = "-578\u00a0998%"; + */ + String expectedDefault = "-5\u00a0789,988"; + String expectedCurrency = "5\u00a0789,99 \u20AC"; + // changed for bug 6547501 + String expectedPercent = "-578\u00a0999 %"; + + formatter = NumberFormat.getNumberInstance(Locale.FRANCE); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedDefault)) { + logln ("Bug 4070798 default test passed."); + } else { + errln("Failed:" + + " Expected " + expectedDefault + + " Received " + tempString ); + } + + + formatter = NumberFormat.getCurrencyInstance(Locale.FRANCE); + tempString = formatter.format( 5789.9876 ); + + if (tempString.equals(expectedCurrency) ) { + logln ("Bug 4070798 currency test assed."); + } else { + errln("Failed:" + + " Expected " + expectedCurrency + + " Received " + tempString ); + } + + + formatter = NumberFormat.getPercentInstance(Locale.FRANCE); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedPercent) ) { + logln ("Bug 4070798 percentage test passed."); + } else { + errln("Failed:" + + " Expected " + expectedPercent + + " Received " + tempString ); + } + } + /** + * Data rounding errors for French (Canada) locale + */ + public void Test4071005 () { + + NumberFormat formatter; + String tempString; + /* user error : + String expectedDefault = "-5 789,987"; + String expectedCurrency = "5 789,98 $"; + String expectedPercent = "-578 998%"; + */ + String expectedDefault = "-5\u00a0789,988"; + String expectedCurrency = "5\u00a0789,99 $"; + // changed for bug 6547501 + String expectedPercent = "-578\u00a0999 %"; + + formatter = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH); + tempString = formatter.format (-5789.9876); + if (tempString.equals(expectedDefault)) { + logln ("Bug 4071005 default test passed."); + } else { + errln("Failed:" + + " Expected " + expectedDefault + + " Received " + tempString ); + } + + formatter = NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH); + tempString = formatter.format( 5789.9876 ) ; + + if (tempString.equals(expectedCurrency) ) { + logln ("Bug 4071005 currency test passed."); + } else { + errln("Failed:" + + " Expected " + expectedCurrency + + " Received " + tempString ); + } + formatter = NumberFormat.getPercentInstance(Locale.CANADA_FRENCH); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedPercent) ) { + logln ("Bug 4071005 percentage test passed."); + } else { + errln("Failed:" + + " Expected " + expectedPercent + + " Received " + tempString ); + } + } + + /** + * Data rounding errors for German (Germany) locale + */ + public void Test4071014 () { + NumberFormat formatter; + String tempString; + /* user error : + String expectedDefault = "-5.789,987"; + String expectedCurrency = "5.789,98 DM"; + String expectedPercent = "-578.998%"; + */ + String expectedDefault = "-5.789,988"; + String expectedCurrency = "5.789,99 \u20AC"; + String expectedPercent = "-578.999%"; + + formatter = NumberFormat.getNumberInstance(Locale.GERMANY); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedDefault)) { + logln ("Bug 4071014 default test passed."); + } else { + errln("Failed:" + + " Expected " + expectedDefault + + " Received " + tempString ); + } + + formatter = NumberFormat.getCurrencyInstance(Locale.GERMANY); + tempString = formatter.format( 5789.9876 ) ; + + if (tempString.equals(expectedCurrency) ) { + logln ("Bug 4071014 currency test passed."); + } else { + errln("Failed:" + + " Expected " + expectedCurrency + + " Received " + tempString ); + } + + formatter = NumberFormat.getPercentInstance(Locale.GERMANY); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedPercent) ) { + logln ("Bug 4071014 percentage test passed."); + } else { + errln("Failed:" + + " Expected " + expectedPercent + + " Received " + tempString ); + } + + } + /** + * Data rounding errors for Italian locale number formats + */ + public void Test4071859 () { + NumberFormat formatter; + String tempString; + /* user error : + String expectedDefault = "-5.789,987"; + String expectedCurrency = "-L. 5.789,98"; + String expectedPercent = "-578.998%"; + */ + String expectedDefault = "-5.789,988"; + String expectedCurrency = "-\u20AC 5.789,99"; + String expectedPercent = "-578.999%"; + + formatter = NumberFormat.getNumberInstance(Locale.ITALY); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedDefault)) { + logln ("Bug 4071859 default test passed."); + } else { + errln("Failed:" + + " Expected " + expectedDefault + + " Received " + tempString ); + } + + formatter = NumberFormat.getCurrencyInstance(Locale.ITALY); + tempString = formatter.format( -5789.9876 ) ; + + if (tempString.equals(expectedCurrency) ) { + logln ("Bug 4071859 currency test passed."); + } else { + errln("Failed:" + + " Expected " + expectedCurrency + + " Received " + tempString ); + } + + formatter = NumberFormat.getPercentInstance(Locale.ITALY); + tempString = formatter.format (-5789.9876); + + if (tempString.equals(expectedPercent) ) { + logln ("Bug 4071859 percentage test passed."); + } else { + errln("Failed:" + + " Expected " + expectedPercent + + " Received " + tempString ); + } + + } + + /* bug 4071859 + * Test rounding for nearest even. + */ + public void Test4093610() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat("#0.#"); + + roundingTest(df, 12.15, "12.2"); // Rounding-up. Above tie (12.150..) + roundingTest(df, 12.25, "12.2"); // No round-up. Exact + half-even rule. + roundingTest(df, 12.45, "12.4"); // No round-up. Below tie (12.449..) + roundingTest(df, 12.450000001,"12.5"); // Rounding-up. Above tie. + roundingTest(df, 12.55, "12.6"); // Rounding-up. Above tie (12.550..) + roundingTest(df, 12.650000001,"12.7"); // Rounding-up. Above tie. + roundingTest(df, 12.75, "12.8"); // Rounding-up. Exact + half-even rule. + roundingTest(df, 12.750000001,"12.8"); // Rounding-up. Above tie. + roundingTest(df, 12.85, "12.8"); // No round-up. Below tie (12.849..) + roundingTest(df, 12.850000001,"12.9"); // Rounding-up. Above tie. + roundingTest(df, 12.950000001,"13"); // Rounding-up. Above tie. + + Locale.setDefault(savedLocale); + } + + void roundingTest(DecimalFormat df, double x, String expected) + { + String out = df.format(x); + logln("" + x + " formats with 1 fractional digits to " + out); + if (!out.equals(expected)) errln("FAIL: Expected " + expected); + } + /** + * Tests the setMaximumFractionDigits limit. + */ + public void Test4098741() + { + try { + NumberFormat fmt = NumberFormat.getPercentInstance(); + fmt.setMaximumFractionDigits(20); + logln(fmt.format(.001)); + } catch (Exception foo) { + errln("Bug 4098471 failed with exception thrown : " + foo.getMessage()); + } + } + /** + * Tests illegal pattern exception. + * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated. + * Part2 has been fixed. + */ + public void Test4074454() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { + DecimalFormat fmt = new DecimalFormat("#,#00.00;-#.#"); + logln("Inconsistent negative pattern is fine."); + DecimalFormat newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces"); + String tempString = newFmt.format(3456.78); + if (!tempString.equals("3,456.78 p'ieces")) + errln("Failed! 3,456.78 p'ieces expected, but got : " + tempString); + } catch (Exception foo) { + errln("An exception was thrown for any inconsistent negative pattern."); + } + Locale.setDefault(savedLocale); + } + + /** + * Tests all different comments. + * Response to some comments : + * [1] DecimalFormat.parse API documentation is more than just one line. + * This is not a reproducable doc error in 116 source code. + * [2] See updated javadoc. + * [3] Fixed. + * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails, + * a null object will be returned. The unchanged parse position also + * reflects an error. + * NumberFormat.parse(String) : If parsing fails, an ParseException + * will be thrown. + * See updated javadoc for more details. + * [5] See updated javadoc. + * [6] See updated javadoc. + * [7] This is a correct behavior if the DateFormat object is linient. + * Otherwise, an IllegalArgumentException will be thrown when formatting + * "January 35". See GregorianCalendar class javadoc for more details. + */ + public void Test4099404() + { + try { + DecimalFormat fmt = new DecimalFormat("000.0#0"); + errln("Bug 4099404 failed applying illegal pattern \"000.0#0\""); + } catch (Exception foo) { + logln("Bug 4099404 pattern \"000.0#0\" passed"); + } + try { + DecimalFormat fmt = new DecimalFormat("0#0.000"); + errln("Bug 4099404 failed applying illegal pattern \"0#0.000\""); + } catch (Exception foo) { + logln("Bug 4099404 pattern \"0#0.000\" passed"); + } + } + /** + * DecimalFormat.applyPattern doesn't set minimum integer digits + */ + public void Test4101481() + { + DecimalFormat sdf = new DecimalFormat("#,##0"); + if (sdf.getMinimumIntegerDigits() != 1) + errln("Minimum integer digits : " + sdf.getMinimumIntegerDigits()); + } + /** + * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition(). + */ + public void Test4052223() + { + try { + DecimalFormat fmt = new DecimalFormat("#,#00.00"); + Number num = fmt.parse("abc3"); + errln("Bug 4052223 failed : can't parse string \"a\". Got " + num); + } catch (ParseException foo) { + logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset()); + } + } + /** + * API tests for API addition request A9. + */ + public void Test4061302() + { + DecimalFormatSymbols fmt = DecimalFormatSymbols.getInstance(); + String currency = fmt.getCurrencySymbol(); + String intlCurrency = fmt.getInternationalCurrencySymbol(); + char monDecSeparator = fmt.getMonetaryDecimalSeparator(); + if (currency.equals("") || + intlCurrency.equals("") || + monDecSeparator == 0) { + errln("getCurrencySymbols failed, got empty string."); + } + logln("Before set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator); + fmt.setCurrencySymbol("XYZ"); + fmt.setInternationalCurrencySymbol("ABC"); + fmt.setMonetaryDecimalSeparator('*'); + currency = fmt.getCurrencySymbol(); + intlCurrency = fmt.getInternationalCurrencySymbol(); + monDecSeparator = fmt.getMonetaryDecimalSeparator(); + if (!currency.equals("XYZ") || + !intlCurrency.equals("ABC") || + monDecSeparator != '*') { + errln("setCurrencySymbols failed."); + } + logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator); + } + /** + * API tests for API addition request A23. FieldPosition.getBeginIndex and + * FieldPosition.getEndIndex. + */ + public void Test4062486() + { + DecimalFormat fmt = new DecimalFormat("#,##0.00"); + StringBuffer formatted = new StringBuffer(); + FieldPosition field = new FieldPosition(0); + Double num = new Double(1234.5); + fmt.format(num, formatted, field); + if (field.getBeginIndex() != 0 && field.getEndIndex() != 5) + errln("Format 1234.5 failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex()); + field.setBeginIndex(7); + field.setEndIndex(4); + if (field.getBeginIndex() != 7 && field.getEndIndex() != 4) + errln("Set begin/end field indexes failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex()); + } + + /** + * DecimalFormat.parse incorrectly works with a group separator. + */ + public void Test4108738() + { + + DecimalFormat df = new DecimalFormat("#,##0.###", + DecimalFormatSymbols.getInstance(java.util.Locale.US)); + String text = "1.222,111"; + Number num = df.parse(text,new ParsePosition(0)); + if (!num.toString().equals("1.222")) + errln("\"" + text + "\" is parsed as " + num); + text = "1.222x111"; + num = df.parse(text,new ParsePosition(0)); + if (!num.toString().equals("1.222")) + errln("\"" + text + "\" is parsed as " + num); + } + + /** + * DecimalFormat.format() incorrectly formats negative doubles. + */ + public void Test4106658() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); // Corrected; see 4147706 + double d1 = -0.0; + double d2 = -0.0001; + StringBuffer buffer = new StringBuffer(); + logln("pattern: \"" + df.toPattern() + "\""); + df.format(d1, buffer, new FieldPosition(0)); + if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 + errln(d1 + " is formatted as " + buffer); + } + buffer.setLength(0); + df.format(d2, buffer, new FieldPosition(0)); + if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 + errln(d2 + " is formatted as " + buffer); + } + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat.parse returns 0 if string parameter is incorrect. + */ + public void Test4106662() + { + DecimalFormat df = new DecimalFormat(); + String text = "x"; + ParsePosition pos1 = new ParsePosition(0), pos2 = new ParsePosition(0); + + logln("pattern: \"" + df.toPattern() + "\""); + Number num = df.parse(text, pos1); + if (num != null) { + errln("Test Failed: \"" + text + "\" is parsed as " + num); + } + df = null; + df = new DecimalFormat("$###.00"); + num = df.parse("$", pos2); + if (num != null){ + errln("Test Failed: \"$\" is parsed as " + num); + } + } + + /** + * NumberFormat.parse doesn't return null + */ + public void Test4114639() + { + NumberFormat format = NumberFormat.getInstance(); + String text = "time 10:x"; + ParsePosition pos = new ParsePosition(8); + Number result = format.parse(text, pos); + if (result != null) errln("Should return null but got : " + result); // Should be null; it isn't + } + + /** + * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG. + */ + public void Test4106664() + { + DecimalFormat df = new DecimalFormat(); + long n = 1234567890123456L; + int m = 12345678; + BigInteger bigN = BigInteger.valueOf(n); + bigN = bigN.multiply(BigInteger.valueOf(m)); + df.setMultiplier(m); + df.setGroupingUsed(false); + logln("formated: " + + df.format(n, new StringBuffer(), new FieldPosition(0))); + logln("expected: " + bigN.toString()); + } + /** + * DecimalFormat.format incorrectly formats -0.0. + */ + public void Test4106667() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + df.setPositivePrefix("+"); + double d = -0.0; + logln("pattern: \"" + df.toPattern() + "\""); + StringBuffer buffer = new StringBuffer(); + df.format(d, buffer, new FieldPosition(0)); + if (!buffer.toString().equals("-0")) { // Corrected; see 4147706 + errln(d + " is formatted as " + buffer); + } + Locale.setDefault(savedLocale); + } + + /** + * DecimalFormat.setMaximumIntegerDigits() works incorrectly. + */ + public void Test4110936() + { + NumberFormat nf = NumberFormat.getInstance(); + nf.setMaximumIntegerDigits(128); + logln("setMaximumIntegerDigits(128)"); + if (nf.getMaximumIntegerDigits() != 128) + errln("getMaximumIntegerDigits() returns " + + nf.getMaximumIntegerDigits()); + } + + /** + * Locale data should use generic currency symbol + * + * 1) Make sure that all currency formats use the generic currency symbol. + * 2) Make sure we get the same results using the generic symbol or a + * hard-coded one. + */ + public void Test4122840() + { + Locale[] locales = NumberFormat.getAvailableLocales(); + + for (int i = 0; i < locales.length; i++) { + ResourceBundle rb = LocaleData.getBundle("sun.text.resources.FormatData", + locales[i]); + // + // Get the currency pattern for this locale. We have to fish it + // out of the ResourceBundle directly, since DecimalFormat.toPattern + // will return the localized symbol, not \00a4 + // + String[] numPatterns = (String[])rb.getObject("NumberPatterns"); + String pattern = numPatterns[1]; + + if (pattern.indexOf("\u00A4") == -1 ) { + errln("Currency format for " + locales[i] + + " does not contain generic currency symbol:" + + pattern ); + } + + // Create a DecimalFormat using the pattern we got and format a number + DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locales[i]); + DecimalFormat fmt1 = new DecimalFormat(pattern, symbols); + + String result1 = fmt1.format(1.111); + + // + // Now substitute in the locale's currency symbol and create another + // pattern. Replace the decimal separator with the monetary separator. + // + char decSep = symbols.getDecimalSeparator(); + char monSep = symbols.getMonetaryDecimalSeparator(); + StringBuffer buf = new StringBuffer(pattern); + for (int j = 0; j < buf.length(); j++) { + if (buf.charAt(j) == '\u00a4') { + String cur = "'" + symbols.getCurrencySymbol() + "'"; + buf.replace(j, j+1, cur); + j += cur.length() - 1; + } + } + symbols.setDecimalSeparator(monSep); + DecimalFormat fmt2 = new DecimalFormat(buf.toString(), symbols); + + String result2 = fmt2.format(1.111); + + if (!result1.equals(result2)) { + errln("Results for " + locales[i] + " differ: " + + result1 + " vs " + result2); + } + } + } + + /** + * DecimalFormat.format() delivers wrong string. + */ + public void Test4125885() + { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + double rate = 12.34; + DecimalFormat formatDec = new DecimalFormat ("000.00"); + logln("toPattern: " + formatDec.toPattern()); + String rateString= formatDec.format(rate); + if (!rateString.equals("012.34")) + errln("result : " + rateString + " expected : 012.34"); + rate = 0.1234; + formatDec = null; + formatDec = new DecimalFormat ("+000.00%;-000.00%"); + logln("toPattern: " + formatDec.toPattern()); + rateString= formatDec.format(rate); + if (!rateString.equals("+012.34%")) + errln("result : " + rateString + " expected : +012.34%"); + Locale.setDefault(savedLocale); + } + + /** + ** + * DecimalFormat produces extra zeros when formatting numbers. + */ + public void Test4134034() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat nf = new DecimalFormat("##,###,###.00"); + + String f = nf.format(9.02); + if (f.equals("9.02")) logln(f + " ok"); else errln("9.02 -> " + f + "; want 9.02"); + + f = nf.format(0); + if (f.equals(".00")) logln(f + " ok"); else errln("0 -> " + f + "; want .00"); + Locale.setDefault(savedLocale); + } + + /** + * CANNOT REPRODUCE - This bug could not be reproduced. It may be + * a duplicate of 4134034. + * + * JDK 1.1.6 Bug, did NOT occur in 1.1.5 + * Possibly related to bug 4125885. + * + * This class demonstrates a regression in version 1.1.6 + * of DecimalFormat class. + * + * 1.1.6 Results + * Value 1.2 Format #.00 Result '01.20' !!!wrong + * Value 1.2 Format 0.00 Result '001.20' !!!wrong + * Value 1.2 Format 00.00 Result '0001.20' !!!wrong + * Value 1.2 Format #0.0# Result '1.2' + * Value 1.2 Format #0.00 Result '001.20' !!!wrong + * + * 1.1.5 Results + * Value 1.2 Format #.00 Result '1.20' + * Value 1.2 Format 0.00 Result '1.20' + * Value 1.2 Format 00.00 Result '01.20' + * Value 1.2 Format #0.0# Result '1.2' + * Value 1.2 Format #0.00 Result '1.20' + */ + public void Test4134300() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + String[] DATA = { + // Pattern Expected string + "#.00", "1.20", + "0.00", "1.20", + "00.00", "01.20", + "#0.0#", "1.2", + "#0.00", "1.20", + }; + for (int i=0; i " + s); + s = f.format(-123.456); + if (!s.equals("-123.456")) + errln("Fail: Format empty pattern x -123.456 => " + s); + } + } + + /** + * BigDecimal numbers get their fractions truncated by NumberFormat. + */ + public void Test4141750() { + try { + String str = "12345.67"; + BigDecimal bd = new BigDecimal(str); + NumberFormat nf = NumberFormat.getInstance(Locale.US); + String sd = nf.format(bd); + if (!sd.endsWith("67")) { + errln("Fail: " + str + " x format -> " + sd); + } + } + catch (Exception e) { + errln(e.toString()); + e.printStackTrace(); + } + } + + /** + * DecimalFormat toPattern() doesn't quote special characters or handle + * single quotes. + */ + public void Test4145457() { + try { + DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(); + DecimalFormatSymbols sym = nf.getDecimalFormatSymbols(); + sym.setDecimalSeparator('\''); + nf.setDecimalFormatSymbols(sym); + double pi = 3.14159; + + String[] PATS = { "#.00 'num''ber'", "''#.00''" }; + + for (int i=0; i \"" + pat + '"'); + + if (val == val2 && out.equals(out2)) { + logln("Ok " + pi + " x \"" + PATS[i] + "\" -> \"" + + out + "\" -> " + val + " -> \"" + + out2 + "\" -> " + val2); + } + else { + errln("Fail " + pi + " x \"" + PATS[i] + "\" -> \"" + + out + "\" -> " + val + " -> \"" + + out2 + "\" -> " + val2); + } + } + } + catch (ParseException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + } + + /** + * DecimalFormat.applyPattern() sets minimum integer digits incorrectly. + * CANNOT REPRODUCE + * This bug is a duplicate of 4139344, which is a duplicate of 4134300 + */ + public void Test4147295() { + DecimalFormat sdf = new DecimalFormat(); + String pattern = "#,###"; + logln("Applying pattern \"" + pattern + "\""); + sdf.applyPattern(pattern); + int minIntDig = sdf.getMinimumIntegerDigits(); + if (minIntDig != 0) { + errln("Test failed"); + errln(" Minimum integer digits : " + minIntDig); + errln(" new pattern: " + sdf.toPattern()); + } else { + logln("Test passed"); + logln(" Minimum integer digits : " + minIntDig); + } + } + + /** + * DecimalFormat formats -0.0 as +0.0 + * See also older related bug 4106658, 4106667 + */ + public void Test4147706() { + DecimalFormat df = new DecimalFormat("#,##0.0##"); + df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH)); + double d1 = -0.0; + double d2 = -0.0001; + StringBuffer f1 = df.format(d1, new StringBuffer(), new FieldPosition(0)); + StringBuffer f2 = df.format(d2, new StringBuffer(), new FieldPosition(0)); + if (!f1.toString().equals("-0.0")) { + errln(d1 + " x \"" + df.toPattern() + "\" is formatted as \"" + f1 + '"'); + } + if (!f2.toString().equals("-0.0")) { + errln(d2 + " x \"" + df.toPattern() + "\" is formatted as \"" + f2 + '"'); + } + } + + /** + * NumberFormat cannot format Double.MAX_VALUE + */ + public void Test4162198() { + double dbl = Double.MAX_VALUE; + NumberFormat f = NumberFormat.getInstance(); + f.setMaximumFractionDigits(Integer.MAX_VALUE); + f.setMaximumIntegerDigits(Integer.MAX_VALUE); + String s = f.format(dbl); + logln("The number " + dbl + " formatted to " + s); + Number n = null; + try { + n = f.parse(s); + } catch (java.text.ParseException e) { + errln("Caught a ParseException:"); + e.printStackTrace(); + } + logln("The string " + s + " parsed as " + n); + if (n.doubleValue() != dbl) { + errln("Round trip failure"); + } + } + + /** + * NumberFormat does not parse negative zero. + */ + public void Test4162852() throws ParseException { + for (int i=0; i<2; ++i) { + NumberFormat f = (i == 0) ? NumberFormat.getInstance() + : NumberFormat.getPercentInstance(); + double d = -0.0; + String s = f.format(d); + double e = f.parse(s).doubleValue(); + logln("" + + d + " -> " + + '"' + s + '"' + " -> " + + e); + if (e != 0.0 || 1.0/e > 0.0) { + logln("Failed to parse negative zero"); + } + } + } + + /** + * NumberFormat truncates data + */ + public void Test4167494() throws Exception { + NumberFormat fmt = NumberFormat.getInstance(Locale.US); + + double a = Double.MAX_VALUE; + String s = fmt.format(a); + double b = fmt.parse(s).doubleValue(); + boolean match = a == b; + if (match) { + logln("" + a + " -> \"" + s + "\" -> " + b + " ok"); + } else { + errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL"); + } + + // We don't test Double.MIN_VALUE because the locale data for the US + // currently doesn't specify enough digits to display Double.MIN_VALUE. + // This is correct for now; however, we leave this here as a reminder + // in case we want to address this later. + if (false) { + a = Double.MIN_VALUE; + s = fmt.format(a); + b = fmt.parse(s).doubleValue(); + match = a == b; + if (match) { + logln("" + a + " -> \"" + s + "\" -> " + b + " ok"); + } else { + errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL"); + } + } + } + + /** + * DecimalFormat.parse() fails when ParseIntegerOnly set to true + */ + public void Test4170798() { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + DecimalFormat df = new DecimalFormat(); + df.setParseIntegerOnly(true); + Number n = df.parse("-0.0", new ParsePosition(0)); + if (!(n instanceof Long || n instanceof Integer) + || n.intValue() != 0) { + errln("FAIL: parse(\"-0.0\") returns " + + n + " (" + n.getClass().getName() + ')'); + } + Locale.setDefault(savedLocale); + } + + /** + * toPattern only puts the first grouping separator in. + */ + public void Test4176114() { + String[] DATA = { + "00", "#00", + "000", "#000", // No grouping + "#000", "#000", // No grouping + "#,##0", "#,##0", + "#,000", "#,000", + "0,000", "#0,000", + "00,000", "#00,000", + "000,000", "#,000,000", + "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported + }; + for (int i=0; i " + s + ", want " + DATA[i+1]); + } + } + } + + /** + * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2 + */ + public void Test4179818() { + String DATA[] = { + // Input Pattern Expected output + "1.2511", "#.#", "1.3", + "1.2501", "#.#", "1.3", + "0.9999", "#", "1", + }; + DecimalFormat fmt = new DecimalFormat("#", + DecimalFormatSymbols.getInstance(Locale.US)); + for (int i=0; i " + fmt.format(-1) + + ", exp ^1"); + } + if (!fmt.getNegativePrefix().equals("^")) { + errln("FAIL: (minus=^).getNegativePrefix -> " + + fmt.getNegativePrefix() + ", exp ^"); + } + sym.setMinusSign('-'); + + fmt.applyPattern("#%"); + sym.setPercent('^'); + fmt.setDecimalFormatSymbols(sym); + if (!fmt.format(0.25).equals("25^")) { + errln("FAIL: 0.25 x (percent=^) -> " + fmt.format(0.25) + + ", exp 25^"); + } + if (!fmt.getPositiveSuffix().equals("^")) { + errln("FAIL: (percent=^).getPositiveSuffix -> " + + fmt.getPositiveSuffix() + ", exp ^"); + } + sym.setPercent('%'); + + fmt.applyPattern("#\u2030"); + sym.setPerMill('^'); + fmt.setDecimalFormatSymbols(sym); + if (!fmt.format(0.25).equals("250^")) { + errln("FAIL: 0.25 x (permill=^) -> " + fmt.format(0.25) + + ", exp 250^"); + } + if (!fmt.getPositiveSuffix().equals("^")) { + errln("FAIL: (permill=^).getPositiveSuffix -> " + + fmt.getPositiveSuffix() + ", exp ^"); + } + sym.setPerMill('\u2030'); + + fmt.applyPattern("\u00A4#.00"); + sym.setCurrencySymbol("usd"); + fmt.setDecimalFormatSymbols(sym); + if (!fmt.format(12.5).equals("usd12.50")) { + errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) + + ", exp usd12.50"); + } + if (!fmt.getPositivePrefix().equals("usd")) { + errln("FAIL: (currency=usd).getPositivePrefix -> " + + fmt.getPositivePrefix() + ", exp usd"); + } + sym.setCurrencySymbol("$"); + + fmt.applyPattern("\u00A4\u00A4#.00"); + sym.setInternationalCurrencySymbol("DOL"); + fmt.setDecimalFormatSymbols(sym); + if (!fmt.format(12.5).equals("DOL12.50")) { + errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) + + ", exp DOL12.50"); + } + if (!fmt.getPositivePrefix().equals("DOL")) { + errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " + + fmt.getPositivePrefix() + ", exp DOL"); + } + sym.setInternationalCurrencySymbol("USD"); + + // Since the pattern logic has changed, make sure that patterns round + // trip properly. Test stream in/out integrity too. + Locale[] avail = NumberFormat.getAvailableLocales(); + for (int i=0; i \"" + pat + + "\" -> \"" + f2.toPattern() + '"'); + } + + // Test toLocalizedPattern/applyLocalizedPattern round trip + pat = df.toLocalizedPattern(); + f2.applyLocalizedPattern(pat); + if (!df.equals(f2)) { + errln("FAIL: " + avail[i] + " -> localized \"" + pat + + "\" -> \"" + f2.toPattern() + '"'); + } + + // Test writeObject/readObject round trip + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(df); + oos.flush(); + baos.close(); + byte[] bytes = baos.toByteArray(); + ObjectInputStream ois = + new ObjectInputStream(new ByteArrayInputStream(bytes)); + f2 = (DecimalFormat) ois.readObject(); + if (!df.equals(f2)) { + errln("FAIL: Stream in/out " + avail[i] + " -> \"" + pat + + "\" -> " + + (f2 != null ? ("\""+f2.toPattern()+'"') : "null")); + } + + } + } + } + + /** + * DecimalFormat.parse() fails for mulipliers 2^n. + */ + public void Test4216742() throws ParseException { + DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.US); + long[] DATA = { Long.MIN_VALUE, Long.MAX_VALUE, -100000000L, 100000000L}; + for (int i=0; i 0 != DATA[i] > 0) { + errln("\"" + str + "\" parse(x " + fmt.getMultiplier() + + ") => " + n); + } + } + } + } + + /** + * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction + * digits. + */ + public void Test4217661() { + Object[] DATA = { + new Double(0.001), "0", + new Double(1.001), "1", + new Double(0.006), "0.01", + new Double(1.006), "1.01", + }; + NumberFormat fmt = NumberFormat.getInstance(Locale.US); + fmt.setMaximumFractionDigits(2); + for (int i=0; i 0 && args[0].equals("-debug")) { + DEBUG = true; + String[] newargs = new String[args.length - 1]; + System.arraycopy(args, 1, newargs, 0, newargs.length); + args = newargs; + } + new NumberRoundTrip().run(args); + } + + public void TestNumberFormatRoundTrip() { + logln("Default Locale"); + localeName = "Default Locale"; + formatName = "getInstance"; + doTest(NumberFormat.getInstance()); + formatName = "getNumberInstance"; + doTest(NumberFormat.getNumberInstance()); + formatName = "getCurrencyInstance"; + doTest(NumberFormat.getCurrencyInstance()); + formatName = "getPercentInstance"; + doTest(NumberFormat.getPercentInstance()); + + Locale[] loc = NumberFormat.getAvailableLocales(); + for (int i=0; i " + escape(s)); + n = fmt.parse(s); + if (DEBUG) logln(" " + escape(s) + " P> " + n); + s2 = fmt.format(n); + if (DEBUG) logln(" " + n + " F> " + escape(s2)); + + if (STRING_COMPARE) { + if (!s.equals(s2)) { + if (fmt instanceof DecimalFormat) { + logln("Text mismatch: expected: " + s + ", got: " + s2 + " --- Try BigDecimal parsing."); + ((DecimalFormat)fmt).setParseBigDecimal(true); + n = fmt.parse(s); + if (DEBUG) logln(" " + escape(s) + " P> " + n); + s2 = fmt.format(n); + if (DEBUG) logln(" " + n + " F> " + escape(s2)); + ((DecimalFormat)fmt).setParseBigDecimal(false); + + if (!s.equals(s2)) { + err = "STRING ERROR(DecimalFormat): "; + } + } else { + err = "STRING ERROR(NumberFormat): "; + } + } + } + + if (EXACT_NUMERIC_COMPARE) { + if (value.doubleValue() != n.doubleValue()) { + err += "NUMERIC ERROR: "; + } + } else { + // Compute proportional error + double error = proportionalError(value, n); + + if (error > MAX_ERROR) { + err += "NUMERIC ERROR " + error + ": "; + } + + if (error > max_numeric_error) max_numeric_error = error; + if (error < min_numeric_error) min_numeric_error = error; + } + + String message = value + typeOf(value) + " F> " + + escape(s) + " P> " + + n + typeOf(n) + " F> " + + escape(s2); + if (err.length() > 0) { + errln("*** " + err + " with " + + formatName + " in " + localeName + + " " + message); + } else { + logln(message); + } + } catch (ParseException e) { + errln("*** " + e.toString() + " with " + + formatName + " in " + localeName); + } + } + + static String typeOf(Number n) { + if (n instanceof Long) return " Long"; + if (n instanceof Double) return " Double"; + return " Number"; + } + + static String escape(String s) { + StringBuffer buf = new StringBuffer(); + for (int i=0; i> 12)); + buf.append(Integer.toHexString((c & 0x0F00) >> 8)); + buf.append(Integer.toHexString((c & 0x00F0) >> 4)); + buf.append(Integer.toHexString(c & 0x000F)); + } + } + return buf.toString(); + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/NumberTest.java b/jdk/test/java/text/Format/NumberFormat/NumberTest.java new file mode 100644 index 00000000000..ca519bb6dab --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/NumberTest.java @@ -0,0 +1,411 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4122840 4135202 4408066 4838107 8008577 + * @summary test NumberFormat + * @library /java/text/testlib + * @modules java.base/sun.util.resources + * @compile -XDignore.symbol.file NumberTest.java + * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberTest + */ + +import java.util.*; +import java.text.*; +import sun.util.resources.LocaleData; + +public class NumberTest extends IntlTest +{ + public static void main(String[] args) throws Exception { + new NumberTest().run(args); + } + + // Test pattern handling + public void TestPatterns() + { + DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US); + String pat[] = { "#.#", "#.", ".#", "#" }; + String newpat[] = { "#0.#", "#0.", "#.0", "#" }; + String num[] = { "0", "0.", ".0", "0" }; + for (int i=0; i \"" + + fmt.toPattern() + '"'); + + for (int v=0; v " + escape(s)); + if (!s.equals(valFormat[v+ival])) { + errln("FAIL: Expected " + valFormat[v+ival] + + ", got " + s + + ", pattern=" + fmt.toPattern()); + } + + ParsePosition pos = new ParsePosition(0); + Number a = fmt.parse(s, pos); + if (pos.getIndex() == s.length()) { + logln(" Parse -> " + a); + if (a.doubleValue() != valParse[v+ival]) { + errln("FAIL: Expected " + valParse[v+ival] + + ", got " + a.doubleValue() + + ", pattern=" + fmt.toPattern()); + } + } else { + errln(" FAIL: Partial parse (" + pos.getIndex() + + " chars) -> " + a); + } + } + for (int v=0; v " + escape(s)); + if (!s.equals(lvalFormat[v+ilval])) { + errln("ERROR: Expected " + lvalFormat[v+ilval] + + ", got " + s + + ", pattern=" + fmt.toPattern()); + } + + ParsePosition pos = new ParsePosition(0); + Number a = fmt.parse(s, pos); + if (pos.getIndex() == s.length()) { + logln(" Parse -> " + a); + if (a.longValue() != lvalParse[v+ilval]) { + errln("FAIL: Expected " + lvalParse[v+ilval] + + ", got " + a + + ", pattern=" + fmt.toPattern()); + } + } else { + errln(" FAIL: Partial parse (" + pos.getIndex() + + " chars) -> " + a); + } + } + ival += val.length; + ilval += lval.length; + } + } + + // Test the handling of quotes + public void TestQuotes() + { + String pat; + DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US); + DecimalFormat fmt = new DecimalFormat(pat = "a'fo''o'b#", sym); + String s = fmt.format(123); + logln("Pattern \"" + pat + "\""); + logln(" Format 123 -> " + escape(s)); + if (!s.equals("afo'ob123")) errln("FAIL: Expected afo'ob123"); + + fmt = new DecimalFormat(pat = "a''b#", sym); + s = fmt.format(123); + logln("Pattern \"" + pat + "\""); + logln(" Format 123 -> " + escape(s)); + if (!s.equals("a'b123")) errln("FAIL: Expected a'b123"); + } + + // Test the use of the currency sign + public void TestCurrencySign() + { + DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US); + DecimalFormat fmt = new DecimalFormat("\u00A4#,##0.00;-\u00A4#,##0.00", sym); + // Can't test this properly until currency API goes public + // DecimalFormatSymbols sym = fmt.getDecimalFormatSymbols(); + + String s = fmt.format(1234.56); + logln("Pattern \"" + fmt.toPattern() + "\""); + logln(" Format " + 1234.56 + " -> " + escape(s)); + if (!s.equals("$1,234.56")) errln("FAIL: Expected $1,234.56"); + s = fmt.format(-1234.56); + logln(" Format " + -1234.56 + " -> " + escape(s)); + if (!s.equals("-$1,234.56")) errln("FAIL: Expected -$1,234.56"); + + fmt = new DecimalFormat("\u00A4\u00A4 #,##0.00;\u00A4\u00A4 -#,##0.00", sym); + s = fmt.format(1234.56); + logln("Pattern \"" + fmt.toPattern() + "\""); + logln(" Format " + 1234.56 + " -> " + escape(s)); + if (!s.equals("USD 1,234.56")) errln("FAIL: Expected USD 1,234.56"); + s = fmt.format(-1234.56); + logln(" Format " + -1234.56 + " -> " + escape(s)); + if (!s.equals("USD -1,234.56")) errln("FAIL: Expected USD -1,234.56"); + } + static String escape(String s) + { + StringBuffer buf = new StringBuffer(); + char HEX[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; + for (int i=0; i> 12]); + buf.append(HEX[(c & 0x0F00) >> 8]); + buf.append(HEX[(c & 0x00F0) >> 4]); + buf.append(HEX[c & 0x000F]); + } + } + return buf.toString(); + } + + // Test simple currency format + // Bug 4024941; this code used to throw a NumberFormat exception + public void TestCurrency() { + NumberFormat currencyFmt = + NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH); + String s = currencyFmt.format(1.50); + logln("Un pauvre ici a..........." + s); + if (!s.equals("1,50 $")) { + errln("FAIL: Expected 1,50 $; got " + s + "; "+ dumpFmt(currencyFmt)); + } + currencyFmt = NumberFormat.getCurrencyInstance(Locale.GERMANY); + s = currencyFmt.format(1.50); + logln("Un pauvre en Allemagne a.." + s); + if (!s.equals("1,50 \u20AC")) { + errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt)); + } + currencyFmt = NumberFormat.getCurrencyInstance(Locale.FRANCE); + s = currencyFmt.format(1.50); + logln("Un pauvre en France a....." + s); + if (!s.equals("1,50 \u20AC")) { + errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt)); + } + } + + String dumpFmt(NumberFormat numfmt) { + DecimalFormat fmt = (DecimalFormat)numfmt; + StringBuffer buf = new StringBuffer(); + buf.append("pattern \""); + buf.append(fmt.toPattern()); + buf.append("\", currency \""); + buf.append(fmt.getDecimalFormatSymbols().getCurrencySymbol()); + buf.append("\""); + return buf.toString(); + } + + // Test numeric parsing + // Bug 4059870 + public void TestParse() + { + String arg = "0"; + java.text.DecimalFormat format = new java.text.DecimalFormat("00"); + try { + Number n = format.parse(arg); + logln("parse(" + arg + ") = " + n); + if (n.doubleValue() != 0.0) errln("FAIL: Expected 0"); + } catch (Exception e) { errln("Exception caught: " + e); } + } + + // Test rounding + public void TestRounding487() { + NumberFormat nf = NumberFormat.getInstance(Locale.US); + roundingTest(nf, 0.00159999, 4, "0.0016"); + roundingTest(nf, 0.00995, 4, "0.01"); + roundingTest(nf, 12.7995, 3, "12.8"); + roundingTest(nf, 12.4999, 0, "12"); + roundingTest(nf, -19.5, 0, "-20"); + } + + void roundingTest(NumberFormat nf, double x, int maxFractionDigits, String expected) { + nf.setMaximumFractionDigits(maxFractionDigits); + String out = nf.format(x); + logln("" + x + " formats with " + maxFractionDigits + " fractional digits to " + out); + if (!out.equals(expected)) { + errln("FAIL: Expected " + expected + ", got " + out); + } + } + + /** + * Bug 4135202 + * DecimalFormat should recognize not only Latin digits 0-9 (\u0030-\u0039) + * but also various other ranges of Unicode digits, such as Arabic + * digits \u0660-\u0669 and Devanagari digits \u0966-\u096F, to name + * a couple. + * @see java.lang.Character#isDigit(char) + */ + public void TestUnicodeDigits() { + char[] zeros = { + 0x0030, // ISO-LATIN-1 digits ('0' through '9') + 0x0660, // Arabic-Indic digits + 0x06F0, // Extended Arabic-Indic digits + 0x0966, // Devanagari digits + 0x09E6, // Bengali digits + 0x0A66, // Gurmukhi digits + 0x0AE6, // Gujarati digits + 0x0B66, // Oriya digits + 0x0BE6, // Tamil digits + 0x0C66, // Telugu digits + 0x0CE6, // Kannada digits + 0x0D66, // Malayalam digits + 0x0E50, // Thai digits + 0x0ED0, // Lao digits + 0x0F20, // Tibetan digits + 0xFF10, // Fullwidth digits + }; + NumberFormat format = NumberFormat.getInstance(); + for (int i=0; i= 0) { + if (customNeg.indexOf(INTL_SYM) >= 0) + errln("Fail: Positive and negative patterns use different symbols"); + else + logln("Ok: " + locales[i] + + " uses currency symbol: " + genericPos + + ", " + customPos); + } + else if (customPos.indexOf(INTL_SYM) >= 0) { + if (customNeg.indexOf(SYM) >= 0) + errln("Fail: Positive and negative patterns use different symbols"); + else + logln("Ok: " + locales[i] + + " uses intl. currency symbol: " + genericPos + + ", " + customPos); + } + else { + errln("FAIL: " + locales[i] + + " contains no currency symbol (impossible!)"); + } + } + } + else logln("Skipping " + locales[i] + "; not a DecimalFormat"); + } + } + + public void TestIntegerFormat() throws ParseException { + NumberFormat format = NumberFormat.getIntegerInstance(Locale.GERMANY); + + float[] formatInput = { 12345.67f, -12345.67f, -0, 0 }; + String[] formatExpected = { "12.346", "-12.346", "0", "0" }; + + for (int i = 0; i < formatInput.length; i++) { + String result = format.format(formatInput[i]); + if (!result.equals(formatExpected[i])) { + errln("FAIL: Expected " + formatExpected[i] + ", got " + result); + } + } + + String[] parseInput = { "0", "-0", "12.345,67", "-12.345,67" }; + float[] parseExpected = { 0, 0, 12345, -12345 }; + + for (int i = 0; i < parseInput.length; i++) { + float result = ((Number) format.parse(parseInput[i])).floatValue(); + if (result != parseExpected[i]) { + errln("FAIL: Expected " + parseExpected[i] + ", got " + result); + } + } + } +} diff --git a/jdk/test/java/text/Format/NumberFormat/PositionTest.java b/jdk/test/java/text/Format/NumberFormat/PositionTest.java new file mode 100644 index 00000000000..31a5a3dbebd --- /dev/null +++ b/jdk/test/java/text/Format/NumberFormat/PositionTest.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4109023 4153060 4153061 + * @library /java/text/testlib + * @summary test ParsePosition and FieldPosition + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +import java.text.*; +import java.io.*; + +public class PositionTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new PositionTest().run(args); + } + + public void TestParsePosition() { + ParsePosition pp1 = new ParsePosition(0); + if (pp1.getIndex() == 0) { + logln("PP constructor() tested."); + }else{ + errln("*** PP getIndex or constructor() result"); + } + + { + int to = 5; + ParsePosition pp2 = new ParsePosition ( to ); + if (pp2.getIndex() == 5) { + logln("PP getIndex and constructor(TextOffset) tested."); + }else{ + errln("*** PP getIndex or constructor(TextOffset) result"); + } + pp2.setIndex( 3 ); + if (pp2.getIndex() == 3) { + logln("PP setIndex tested."); + }else{ + errln("*** PP getIndex or setIndex result"); + } + } + + ParsePosition pp2, pp3; + pp2 = new ParsePosition( 3 ); + pp3 = new ParsePosition( 5 ); + ParsePosition pp4 = new ParsePosition(5); + if (! pp2.equals(pp3)) { + logln("PP not equals tested."); + }else{ + errln("*** PP not equals fails"); + } + if (pp3.equals(pp4)) { + logln("PP equals tested."); + }else{ + errln("*** PP equals fails (" + pp3.getIndex() + " != " + pp4.getIndex() + ")"); + } + + ParsePosition pp5; + pp5 = pp4; + if (pp4.equals(pp5)) { + logln("PP operator= tested."); + }else{ + errln("*** PP operator= operator== or operator != result"); + } + + } + + public void TestFieldPosition() { + FieldPosition fp = new FieldPosition( 7 ); + + if (fp.getField() == 7) { + logln("FP constructor(int) and getField tested."); + }else{ + errln("*** FP constructor(int) or getField"); + } + + FieldPosition fph = new FieldPosition( 3 ); + if ( fph.getField() != 3) errln("*** FP getField or heap constr."); + + boolean err1 = false; + boolean err2 = false; + boolean err3 = false; +// for (long i = -50; i < 50; i++ ) { +// fp.setField( i+8 ); +// fp.setBeginIndex( i+6 ); +// fp.setEndIndex( i+7 ); +// if (fp.getField() != i+8) err1 = true; +// if (fp.getBeginIndex() != i+6) err2 = true; +// if (fp.getEndIndex() != i+7) err3 = true; +// } + if (!err1) { + logln("FP setField and getField tested."); + }else{ + errln("*** FP setField or getField"); + } + if (!err2) { + logln("FP setBeginIndex and getBeginIndex tested."); + }else{ + errln("*** FP setBeginIndex or getBeginIndex"); + } + if (!err3) { + logln("FP setEndIndex and getEndIndex tested."); + }else{ + errln("*** FP setEndIndex or getEndIndex"); + } + + logln(""); + } + + public void TestFieldPosition_example() { + //***** no error detection yet !!!!!!! + //***** this test is for compiler checks and visual verification only. + double doubleNum[] = { 123456789.0, -12345678.9, 1234567.89, -123456.789, + 12345.6789, -1234.56789, 123.456789, -12.3456789, 1.23456789}; + int dNumSize = doubleNum.length; + + DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(); + fmt.setDecimalSeparatorAlwaysShown(true); + + final int tempLen = 20; + StringBuffer temp; + + for (int i=0; iformat(doubleNum[i], buf, pos), fmtText); + StringBuffer res = fmt.format(doubleNum[i], buf, pos); + int tempOffset = (tempLen <= (tempLen - pos.getEndIndex())) ? + tempLen : (tempLen - pos.getEndIndex()); + for (int j=0; j succeeded."); + } +} diff --git a/jdk/test/java/text/Format/common/Bug6215962.java b/jdk/test/java/text/Format/common/Bug6215962.java new file mode 100644 index 00000000000..85dd5e2cebd --- /dev/null +++ b/jdk/test/java/text/Format/common/Bug6215962.java @@ -0,0 +1,161 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6215962 + * @summary Confirm that replacing Utility.arayEquals methods have with + * Arrays.equals introduces no problem. + */ +import java.text.*; +import java.util.*; + +public class Bug6215962 { + + public static void main(String[] args) { + testMessageFormat(); + testChoiceFormat(); + testDateFormatSymbols(); + } + + /** + * Test cases for MessageFormat + */ + static void testMessageFormat() { + MessageFormat mf1 = new MessageFormat("{0}", null); + MessageFormat mf2 = new MessageFormat("{0}", null); + check(mf1, mf2, true); + + mf1.setLocale(null); + check(mf1, mf2, true); + + mf1 = new MessageFormat("{0}", Locale.US); + check(mf1, mf2, false); + + mf2 = new MessageFormat("{0}", Locale.JAPAN); + check(mf1, mf2, false); + + mf1 = new MessageFormat("{0}", new Locale("ja", "JP")); + check(mf1, mf2, true); + + mf1.setLocale(null); + check(mf1, mf2, false); + + mf1 = new MessageFormat("{0}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, false); + + mf2 = new MessageFormat("{1}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, false); + + mf1 = new MessageFormat("{1}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, true); + + mf1 = new MessageFormat("{1, date}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, false); + + mf2 = new MessageFormat("{1, date}", new Locale("ja", "JP", "FOO")); + check(mf1, mf2, true); + } + + static void check(MessageFormat f1, MessageFormat f2, boolean expected) { + boolean got = f1.equals(f2); + if (got != expected) { + throw new RuntimeException("Test failed for MessageFormat.equals(). Got: " + got + ", Expected: " + expected); + } + } + + /** + * Test cases for MessageFormat + */ + static void testChoiceFormat() { + double[] limits0 = {0,1,2,3,4,5,6}; + double[] limits1 = {1,2,3,4,5,6,7}; + String[] monthNames0 = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; + String[] monthNames1 = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}; + + ChoiceFormat cf1 = new ChoiceFormat(limits1, monthNames0); + ChoiceFormat cf2 = new ChoiceFormat(limits1, monthNames0); + check(cf1, cf2, true); + + cf2 = new ChoiceFormat(limits0, monthNames0); + check(cf1, cf2, false); + + cf2 = new ChoiceFormat(limits1, monthNames1); + check(cf1, cf2, false); + } + + static void check(ChoiceFormat f1, ChoiceFormat f2, boolean expected) { + boolean got = f1.equals(f2); + if (got != expected) { + throw new RuntimeException("Test failed for ChoiceFormat.equals(). Got: " + got + ", Expected: " + expected); + } + } + + /** + * Test cases for DateFormatSymbols + */ + static void testDateFormatSymbols() { + DateFormatSymbols dfs1 = new DateFormatSymbols(); + DateFormatSymbols dfs2 = new DateFormatSymbols(); + check(dfs1, dfs2, true); + + // Becase eras, months, shortmonths, weekdays, shortweekdays, ampms are + // the same data type (String[]) and are treated in the same way, here + // I test only Months. + String[] tmp = dfs1.getMonths(); + String saved = tmp[0]; + tmp[0] = "Foo"; + dfs1.setMonths(tmp); + check(dfs1, dfs2, false); + + tmp[0] = saved; + dfs1.setMonths(tmp); + check(dfs1, dfs2, true); + + // Test LocalizedpatternChars (String) + String pattern = dfs2.getLocalPatternChars(); + dfs2.setLocalPatternChars("Bar"); + check(dfs1, dfs2, false); + + dfs2.setLocalPatternChars(pattern); + check(dfs1, dfs2, true); + + // Test TimeZone strings (String[][]) + String[][] zones = dfs1.getZoneStrings(); + saved = zones[0][1]; + zones[0][1] = "Yokohama Summer Time"; + dfs1.setZoneStrings(zones); + check(dfs1, dfs2, false); + + zones[0][1] = saved; + dfs1.setZoneStrings(zones); + check(dfs1, dfs2, true); + } + + static void check(DateFormatSymbols dfs1, DateFormatSymbols dfs2, boolean expected) { + boolean got = dfs1.equals(dfs2); + if (got != expected) { + throw new RuntimeException("Test failed for DateFormatSymbols.equals(). Got: " + got + ", Expected: " + expected); + } + } +} diff --git a/jdk/test/java/text/Format/common/ChoiceFormat.ser.txt b/jdk/test/java/text/Format/common/ChoiceFormat.ser.txt new file mode 100644 index 00000000000..4947d1936e7 --- /dev/null +++ b/jdk/test/java/text/Format/common/ChoiceFormat.ser.txt @@ -0,0 +1,37 @@ +# +# 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. +# + +# Hex dump of a serialized ChoiceFormat for Bug4769840. + +aced0005737200166a6176612e746578742e43686f696365466f726d617418e9 +c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61 +76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400 +025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3 +bf137d07e80200065a000c67726f7570696e67557365644200116d6178467261 +6374696f6e4469676974734200106d6178496e74656765724469676974734200 +116d696e4672616374696f6e4469676974734200106d696e496e746567657244 +69676974735a00107061727365496e74656765724f6e6c79787200106a617661 +2e746578742e466f726d6174fbd8bc12e90f1843020000787001032800010075 +7200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200 +0078700000000274000420666f6f74000420626172757200025b443ea68c14ab +635a1e02000078700000000200000000000000003ff0000000000000 diff --git a/jdk/test/java/text/Format/common/DateFormat.Field.ser.txt b/jdk/test/java/text/Format/common/DateFormat.Field.ser.txt new file mode 100644 index 00000000000..e78f24409e7 --- /dev/null +++ b/jdk/test/java/text/Format/common/DateFormat.Field.ser.txt @@ -0,0 +1,32 @@ +# +# 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. +# + +# Hex dump of a serialized DateFormat.Field for Bug4769840. + +aced00057372001a6a6176612e746578742e44617465466f726d617424466965 +6c646744fc81f123e71002000149000d63616c656e6461724669656c64787200 +166a6176612e746578742e466f726d6174244669656c6403d7fbbd383b0f9b02 +00007872002f6a6176612e746578742e41747472696275746564436861726163 +7465724974657261746f7224417474726962757465811e7426cd47175c020001 +4c00046e616d657400124c6a6176612f6c616e672f537472696e673b78707400 +0974696d65207a6f6e65ffffffff diff --git a/jdk/test/java/text/Format/common/FormatIteratorTest.java b/jdk/test/java/text/Format/common/FormatIteratorTest.java new file mode 100644 index 00000000000..7102f59dec2 --- /dev/null +++ b/jdk/test/java/text/Format/common/FormatIteratorTest.java @@ -0,0 +1,440 @@ +/* + * 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. + */ + +/** + * @test + * @bug 4018937 + * @library /java/text/testlib + * @build FormatIteratorTest PParser IntlTest + * @run main FormatIteratorTest + * @summary Tests the formatToCharacterIterator method of SimpleDateFormat, + * MessageFormat and DecimalFormat. + */ + +import java.io.*; +import java.lang.reflect.*; +import java.text.*; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +/** + * FormatTester creates Formats, and tests the resulting FieldPositions + * and AttributedCharacterIterator based on a file. The file is a hierarchical + * set of key/value pairs, where each value can also be an array or map. The + * top map must contain a tests entry, which will be an array consisting + * of pairs of maps. The first map specifies the Format that + * should be created, and consists of: + *

    + *   class = className
    + *   args = (arg1 arg2 ...)
    + *   valueClass = className
    + *   valueArgs = (arg1 arg2 ...)
    + * 
    + * The second map dictates what to test, and should consist of the following: + *
    + *   length = lengthOfFormattedString
    + *   text = Result of Formatting
    + *   0...lengthOfFormattedString = (arg1 arg2 ...)
    + *   limits = ( range1 range2 ...)
    + *   fieldPositions = ( fp1 fp2 ...)
    + * 
    + * lengthOfFormattedString indicate the total length of formatted + * string. text indicates the resulting string. + * 0...x where x == lengthOfFormattedString - 1 is + * an array of the attributes that should exist at the particular + * location. limits is an array of maps, where each map + * can be used to test the bounds of a set of attributes. Each map will + * consist of: + *
    + *   attributes = array of attributes
    + *   begin = start location
    + *   begin2 = second start location
    + *   end = limit location
    + *   end2 = second limit location
    + * 
    + * These are tested by iterating from begin to end in the CharacterIterator + * and doing the following at each index: + *
    + *   getRunStart() == begin
    + *   getRunStart(attributes) == begin2
    + *   getRunLimit() == end
    + *   getRunLimit(attributes) == end2
    + * 
    + * fieldPositions is used to test the results of invoking + * format with a FieldPosition. + * fieldPositions is an array of maps, where each map contains + * the following: + *
    + *   field = Integer field reference (optional)
    + *   fieldID = Object reference
    + *   begin = begin index of FieldPosition after formatting
    + *   end = end index of FieldPosition after formatting
    + * 
    + * Any lines starting with {@code '#'} are comment lines and ignored. + */ +public class FormatIteratorTest extends IntlTest { + private static HashMap attrs; + private Format format; + private Object value; + private String text; + + public static final Object ARG0_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG1_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG2_FIELD_ID = MessageFormat. + Field.ARGUMENT; + public static final Object ARG3_FIELD_ID = MessageFormat. + Field.ARGUMENT; + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + // The current tests are only appropriate for US. If tests are + // added for other locales are added, then a property should be + // added to each file (test) to be able to specify the locale. + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + new FormatIteratorTest().run(args); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + public FormatIteratorTest() { + } + + public void testDecimalFormat() { + _test(new File(System.getProperty("test.src", "."), + "decimalFormat.props")); + } + + public void testMessageFormat() { + _test(new File(System.getProperty("test.src", "."), + "messageFormat.props")); + } + + public void testDateFormat() { + _test(new File(System.getProperty("test.src", "."), + "dateFormat.props")); + } + + private void _test(File file) { + try { + attrs = new HashMap(); + logln("testing: " + file); + PParser parser = new PParser(); + Hashtable contents = parser.parse(new BufferedReader( + new FileReader(file))); + Vector test = (Vector)contents.get("tests"); + + for (int counter = 0; counter < test.size(); counter++) { + logln("creating: " + (counter / 2)); + + AttributedCharacterIterator iterator = + create((Hashtable)test.get(counter)); + + logln("verifying: " + (counter / 2)); + verify(iterator, (Hashtable)test.get(++counter)); + } + } catch (IOException ioe) { + errln("Error reading: " + ioe); + } + } + + public void verify(AttributedCharacterIterator iterator,Hashtable table) { + int length = Integer.parseInt((String)table.get("length")); + + // Verify the text + if (!getText(iterator).equals( + escapeIfNecessary((String)table.get("text")))) { + String text = getText(iterator); + + errln("text doesn't match, got: " + getText(iterator)); + } + if (iterator.getBeginIndex() != 0) { + errln("Bogus start: " + iterator.getBeginIndex()); + } + if (iterator.getEndIndex() != length) { + errln("Bogus end: " + iterator.getEndIndex()); + } + for (int counter = 0; counter < length; counter++) { + iterator.setIndex(counter); + if (!verifyAttributes(iterator.getAttributes().keySet(), + makeAttributes((Vector)table.get(Integer. + toString(counter))))) { + errln("Attributes don't match at " + counter + " expecting " + + makeAttributes((Vector)table.get(Integer.toString + (counter))) + " got " + + iterator.getAttributes().keySet()); + } + } + for (int counter = length - 1; counter >= 0; counter--) { + iterator.setIndex(counter); + if (!verifyAttributes(iterator.getAttributes().keySet(), + makeAttributes((Vector)table.get(Integer. + toString(counter))))) { + errln("Attributes don't match at " + counter + " expecting " + + makeAttributes((Vector)table.get(Integer.toString + (counter))) + " got " + + iterator.getAttributes().keySet()); + } + } + verifyLimits(iterator, table); + + text = escapeIfNecessary((String)table.get("text")); + Vector fps = (Vector)table.get("fieldPositions"); + + if (fps != null) { + for (int counter = 0; counter < fps.size(); counter++) { + verifyFieldPosition(counter, (Hashtable)fps.get(counter)); + } + } + } + + private void verifyLimits(AttributedCharacterIterator iterator, + Hashtable table) { + Vector limits = (Vector)table.get("limits"); + + if (limits != null) { + for (int counter = 0; counter < limits.size(); counter++) { + verifyLimit(iterator, (Hashtable)limits.get(counter)); + } + } + } + + private void verifyLimit(AttributedCharacterIterator iterator, + Hashtable table) { + int begin = Integer.parseInt((String)table.get("begin")); + int end = Integer.parseInt((String)table.get("end")); + Set attrs = makeAttributes((Vector)table.get("attributes")); + String begin2S = (String)table.get("begin2"); + int begin2 = (begin2S != null) ? Integer.parseInt(begin2S) : begin; + String end2S = (String)table.get("end2"); + int end2 = (end2S != null) ? Integer.parseInt(end2S) : end; + + for (int counter = begin; counter < end; counter++) { + iterator.setIndex(counter); + if (iterator.getRunStart() != begin) { + errln("Begin doesn't match want " + begin + " got " + + iterator.getRunStart() + " at " + counter + " attrs " + + attrs); + } + if (iterator.getRunStart(attrs) != begin2) { + errln("Begin2 doesn't match want " + begin2 + " got " + + iterator.getRunStart(attrs) + " at " + counter + + " attrs " + attrs); + } + if (iterator.getRunLimit() != end) { + errln("End doesn't match want " + end + " got " + + iterator.getRunLimit() + " at " + counter + " attrs " + + attrs); + } + if (iterator.getRunLimit(attrs) != end2) { + errln("End2 doesn't match want " + end2 + " got " + + iterator.getRunLimit(attrs) + " at " + counter + + " attrs " + attrs); + } + } + } + + private boolean verifyAttributes(Set a, Set b) { + boolean aEmpty = (a.size() == 0); + boolean bEmpty = (b.size() == 0); + + if (aEmpty && bEmpty) { + return true; + } + else if (aEmpty || bEmpty) { + return false; + } + return a.equals(b); + } + + private String getText(AttributedCharacterIterator iterator) { + StringBuffer buffer = new StringBuffer(); + + for (int counter = 0; counter < iterator.getEndIndex(); counter++) { + buffer.append(iterator.setIndex(counter)); + } + return buffer.toString(); + } + + private void verifyFieldPosition(int index, Hashtable table) { + Object o = table.get("field"); + int begin = Integer.parseInt((String)table.get("begin")); + int end = Integer.parseInt((String)table.get("end")); + + if (o != null) { + FieldPosition fp = new FieldPosition(((Integer) + lookupField((String)o)).intValue()); + + verifyFieldPosition(fp, begin, end, index); + } + o = table.get("fieldID"); + if (o != null) { + FieldPosition fp = new FieldPosition((Format.Field) + lookupField((String)o)); + verifyFieldPosition(fp, begin, end, index); + } + } + + private void verifyFieldPosition(FieldPosition fp, int begin, int end, + int index) { + StringBuffer buffer = new StringBuffer(); + + format.format(value, buffer, fp); + if (fp.getBeginIndex() != begin) { + errln("bogus begin want " + begin + " got " + fp.getBeginIndex() + + " for " + fp + " at " + index); + } + if (fp.getEndIndex() != end) { + errln("bogus end want " + end + " got " + fp.getEndIndex() + + " for " + fp + " at " + index); + } + if (!buffer.toString().equals(text)) { + errln("Text does not match, want !" + buffer.toString() + + "! got !" + text + "!"); + } + } + + public AttributedCharacterIterator create(Hashtable table) { + format = (Format)createInstance((String)table.get("class"), + ((Vector)table.get("args")).toArray()); + value = createInstance((String)table.get("valueClass"), + ((Vector)table.get("valueArgs")).toArray()); + + logln("Created format: " + format + " value " + value); + AttributedCharacterIterator aci = format. + formatToCharacterIterator(value); + + logln("Obtained Iterator: " + aci); + return aci; + } + + public Format.Field makeAttribute(String name) { + return (Format.Field)lookupField(name); + } + + private Object createInstance(String className, Object[] args) { + if (className.equals("java.lang.reflect.Array")) { + for (int counter = 0; counter < args.length; counter++) { + if (args[counter] instanceof Vector) { + Vector v = (Vector)args[counter]; + + args[counter] = createInstance((String)v.get(0), + ((Vector)v.get(1)).toArray()); + } + } + return args; + } + for (int counter = 0; counter < args.length; counter++) { + args[counter] = escapeIfNecessary((String)args[counter]); + } + try { + if (className.equals("java.util.concurrent.atomic.AtomicInteger")) { + return new AtomicInteger(Integer.valueOf((String)args[0])); + } else if (className.equals("java.util.concurrent.atomic.AtomicLong")) { + return new AtomicLong(Long.valueOf((String)args[0])); + } else { + Class klass = lookupClass(className); + Constructor cons = klass.getConstructor( + new Class[] { String.class }); + Object value = cons.newInstance(args); + + return value; + } + } catch (Throwable th) { + errln("Error creating instance " + th); + return null; + } + } + + private Class lookupClass(String name) throws ClassNotFoundException { + try { + Class klass = Class.forName(name); + + return klass; + } catch (ClassNotFoundException e1) {} + + try { + Class klass = Class.forName("java.lang." + name); + + return klass; + } catch (ClassNotFoundException e1) {} + + Class klass = Class.forName("java.text." + name); + + return klass; + } + + private Object lookupField(String name) { + Throwable error = null; + + try { + int dotIndex = name.indexOf('.'); + Class klass = lookupClass(name.substring(0, dotIndex)); + String fieldName = name.substring(dotIndex + 1); + Field[] fields = klass.getFields(); + + for (int counter = fields.length - 1; counter >= 0; counter--) { + if (fields[counter].getName().equals(fieldName)) { + return fields[counter].get(null); + } + } + } catch (Throwable th) { + error = th; + } + errln("Could not lookup field " + name + " " + error); + return null; + } + + protected String escapeIfNecessary(String string) { + if (string != null) { + int index; + + if ((index = string.indexOf("\\u")) != -1) { + StringBuffer sb = new StringBuffer(string.substring(0, index)); + + sb.append((char)Integer.parseInt( + string.substring(index + 2, index + 6), 16)); + sb.append(string.substring(index + 6)); + string = sb.toString(); + } + } + return string; + } + + public Set makeAttributes(Vector names) { + HashSet set = new HashSet(Math.max(1, names.size())); + + for (int counter = 0; counter < names.size(); counter++) { + set.add(makeAttribute((String)names.get(counter))); + } + return set; + } +} diff --git a/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt b/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt new file mode 100644 index 00000000000..5428b76680c --- /dev/null +++ b/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt @@ -0,0 +1,32 @@ +# +# 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. +# + +# Hex dump of a serialized MessageFormat.Field for Bug4769840. + +aced00057372001d6a6176612e746578742e4d657373616765466f726d617424 +4669656c646da23d2c7b46bfaa020000787200166a6176612e746578742e466f +726d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e7465 +78742e417474726962757465644368617261637465724974657261746f722441 +7474726962757465811e7426cd47175c0200014c00046e616d657400124c6a61 +76612f6c616e672f537472696e673b78707400166d6573736167652061726775 +6d656e74206669656c64 diff --git a/jdk/test/javax/xml/bind/xjc/8032884/compile-schema.sh b/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt similarity index 65% rename from jdk/test/javax/xml/bind/xjc/8032884/compile-schema.sh rename to jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt index 8051abf438a..12851638adf 100644 --- a/jdk/test/javax/xml/bind/xjc/8032884/compile-schema.sh +++ b/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt @@ -1,7 +1,5 @@ -#! /bin/sh - # -# Copyright (c) 2014, 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,17 +21,11 @@ # questions. # -# +# Hex dump of a serialized NumberFormat.Field for Bug4769840. -if [ "x$TESTJAVA" = x ]; then - TESTJAVA=$1; shift - TESTCLASSES=. -fi - -echo "cleaning generated files ..." -rm -rfv ${TESTSRC}/generated - -echo "compiling [optional-property-schema.xsd] schema ..." -$TESTJAVA/bin/xjc -p generated -d ${TESTSRC} ${TESTSRC}/optional-property-schema.xsd - -echo "Schema compiled. Verification of generated files can be done now." +aced00057372001c6a6176612e746578742e4e756d626572466f726d61742446 +69656c646802a038193ff37a020000787200166a6176612e746578742e466f72 +6d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e746578 +742e417474726962757465644368617261637465724974657261746f72244174 +74726962757465811e7426cd47175c0200014c00046e616d657400124c6a6176 +612f6c616e672f537472696e673b7870740007696e7465676572 diff --git a/jdk/test/java/text/Format/common/PParser.java b/jdk/test/java/text/Format/common/PParser.java new file mode 100644 index 00000000000..6ada76b1059 --- /dev/null +++ b/jdk/test/java/text/Format/common/PParser.java @@ -0,0 +1,274 @@ +/* + * 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 java.io.*; +import java.util.*; + +/* + * assignment : key = value; + * key : string + * value : string | array | dict + * nValue : , value + * array : ( value nValue ) + * nAssignment: , assignment|value + * dict : { assignment* } + * string : "*" or anything but a ,(){}= + * + * special characters: ,(){}= + */ + +public class PParser { + protected static final int OPEN_PAIR = 1; + protected static final int CLOSE_PAIR = 2; + protected static final int OPEN_ARRAY = 3; + protected static final int CLOSE_ARRAY = 4; + protected static final int MORE = 5; + protected static final int EQUAL = 6; + protected static final int STRING = 7; + protected static final int WS = 8; + + protected Reader reader; + protected boolean bufferedToken; + protected StringBuffer stringBuffer = new StringBuffer(); + protected int lastChar; + protected int lastToken; + protected int lineNumber; + protected int column; + + public PParser() { + } + + public Hashtable parse(Reader r) throws IOException { + this.reader = r; + bufferedToken = false; + lineNumber = 0; + column = 0; + if (getToken() != OPEN_PAIR) { + error("No initial open"); + } + return parsePair(); + } + + protected Object parseValue(int lookAhead) throws IOException { + int token; + + if (lookAhead == -1) { + token = getToken(); + } else { + token = lookAhead; + } + switch (token) { + case STRING: + return stringBuffer.toString(); + case OPEN_ARRAY: + return parseArray(); + case OPEN_PAIR: + return parsePair(); + default: + error("Expecting value"); + } + return null; + } + + protected Object parseArray() throws IOException { + Vector array = new Vector(); + int token; + + while ((token = getToken()) != CLOSE_ARRAY) { + if (token == MORE) { + token = getToken(); + } + if (token != CLOSE_ARRAY) { + array.addElement(parseValue(token)); + } + } + return array; + } + + protected Hashtable parsePair() throws IOException { + Hashtable ht = new Hashtable(11); + int token; + + while ((token = getToken()) != CLOSE_PAIR) { + if (token != STRING) { + error("Pair expecting string got"); + } + String key = stringBuffer.toString(); + + if (getToken() != EQUAL) { + error("Expecting = "); + } + + Object value = parseValue(-1); + ht.put(key, value); + } + return ht; + } + + protected void ungetToken() { + if (bufferedToken) { + error("Can not buffer more than one token"); + } + bufferedToken = true; + } + + protected int getToken() throws IOException { + int token = getToken(false, false); + + return token; + } + + protected int getToken(boolean wantsWS, boolean inString) + throws IOException { + if (bufferedToken) { + bufferedToken = false; + if (lastToken != WS || wantsWS) { + return lastToken; + } + } + while ((lastChar = reader.read()) != -1) { + // If a line starts with '#', skip the line. + if (column == 0 && lastChar == '#') { + while ((lastChar = reader.read()) != -1 + && lastChar != '\n') { + } + if (lastChar == -1) { + break; + } + } + + column++; + switch(lastChar) { + case '\n': + lineNumber++; + column = 0; + case ' ': + case '\r': + case '\t': + if (wantsWS) { + lastToken = WS; + return WS; + } + break; + case ',': + lastToken = MORE; + return MORE; + case '(': + lastToken = OPEN_ARRAY; + return OPEN_ARRAY; + case ')': + lastToken = CLOSE_ARRAY; + return CLOSE_ARRAY; + case '{': + lastToken = OPEN_PAIR; + return OPEN_PAIR; + case '}': + lastToken = CLOSE_PAIR; + return CLOSE_PAIR; + case '=': + lastToken = EQUAL; + return EQUAL; + case '"': + lastToken = STRING; + if (!inString) { + stringBuffer.setLength(0); + while (true) { + getToken(true, true); + if (lastChar == '"') { + lastToken = STRING; + return STRING; + } + stringBuffer.append((char)lastChar); + } + } + return STRING; + default: + lastToken = STRING; + if (!inString) { + stringBuffer.setLength(0); + stringBuffer.append((char)lastChar); + while (getToken(true, true) == STRING) { + if (lastChar == '"') { + error("Unexpected quote"); + } + stringBuffer.append((char)lastChar); + } + ungetToken(); + } + return STRING; + } + } + return -1; + } + + protected void error(String errorString) { + throw new RuntimeException(errorString + " at line " + lineNumber + " column " + column); + } + + public static void dump(Object o) { + if (o instanceof String) { + System.out.print(o); + } else if(o instanceof Vector) { + Enumeration e = ((Vector)o).elements(); + + dump(" ("); + while (e.hasMoreElements()) { + dump(e.nextElement()); + dump(" -- "); + } + dump(" )"); + } else { + Hashtable ht = (Hashtable)o; + Enumeration e = ht.keys(); + + dump(" {"); + while (e.hasMoreElements()) { + Object key = e.nextElement(); + + dump(key); + dump(" = "); + dump(ht.get(key)); + dump(";"); + } + dump(" }"); + } + } + + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("need filename"); + } else { + try { + FileReader fr = new FileReader(args[0]); + PParser parser = new PParser(); + Hashtable ht = parser.parse(fr); + + dump(ht); + System.out.println(); + } + catch (IOException ioe) { + System.out.println("Couldn't parse: " + ioe); + } + } + } +} diff --git a/jdk/test/java/text/Format/common/dateFormat.props b/jdk/test/java/text/Format/common/dateFormat.props new file mode 100644 index 00000000000..22bb9a44d78 --- /dev/null +++ b/jdk/test/java/text/Format/common/dateFormat.props @@ -0,0 +1,333 @@ +# +# 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. +# + +# Test data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.SimpleDateFormat + args = ("M/dd/yy") + valueClass = java.util.Date + valueArgs = ("7/10/71") + } + { + length = 7 + text = "7/10/71" + 0 = (DateFormat$Field.MONTH) + 1 = () + 2 = (DateFormat$Field.DAY_OF_MONTH) + 3 = (DateFormat$Field.DAY_OF_MONTH) + 4 = () + 5 = (DateFormat$Field.YEAR) + 6 = (DateFormat$Field.YEAR) + limits = ( { attributes = (DateFormat$Field.MONTH) + begin = 0 end = 1} + { attributes = () + begin = 1 begin2 = 0 end = 2 end2 = 7} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 5 end2 = 7} + { attributes = (DateFormat$Field.YEAR) + begin = 5 end = 7} + ) + fieldPositions = + ( + { + field = DateFormat.MONTH_FIELD + fieldID = DateFormat$Field.MONTH + begin = 0 end = 1 + } + { + field = DateFormat.DATE_FIELD + fieldID = DateFormat$Field.DAY_OF_MONTH + begin = 2 end = 4 + } + { + field = DateFormat.YEAR_FIELD + fieldID = DateFormat$Field.YEAR + begin = 5 end = 7 + } + ) + } + + { + class = java.text.SimpleDateFormat + args = ("EEEEEEE MMMMMMMMMMMMM yyyy GG") + valueClass = java.util.Date + valueArgs = ("12/10/2020") + } + { + length = 25 + text = "Thursday December 2020 AD" + 0 = (DateFormat$Field.DAY_OF_WEEK) + 1 = (DateFormat$Field.DAY_OF_WEEK) + 2 = (DateFormat$Field.DAY_OF_WEEK) + 3 = (DateFormat$Field.DAY_OF_WEEK) + 4 = (DateFormat$Field.DAY_OF_WEEK) + 5 = (DateFormat$Field.DAY_OF_WEEK) + 6 = (DateFormat$Field.DAY_OF_WEEK) + 7 = (DateFormat$Field.DAY_OF_WEEK) + 8 = () + 9 = (DateFormat$Field.MONTH) + 10 = (DateFormat$Field.MONTH) + 11 = (DateFormat$Field.MONTH) + 12 = (DateFormat$Field.MONTH) + 13 = (DateFormat$Field.MONTH) + 14 = (DateFormat$Field.MONTH) + 15 = (DateFormat$Field.MONTH) + 16 = (DateFormat$Field.MONTH) + 17 = () + 18 = (DateFormat$Field.YEAR) + 19 = (DateFormat$Field.YEAR) + 20 = (DateFormat$Field.YEAR) + 21 = (DateFormat$Field.YEAR) + 22 = () + 23 = (DateFormat$Field.ERA) + 24 = (DateFormat$Field.ERA) + limits = ( { attributes = (DateFormat$Field.DAY_OF_WEEK) + begin = 0 end = 8} + { attributes = () + begin = 8 begin2 = 0 end = 9 end2 = 25} + { attributes = (DateFormat$Field.MONTH) + begin = 9 end = 17} + { attributes = () + begin = 17 begin2 = 0 end = 18 end2 = 25} + { attributes = (DateFormat$Field.YEAR) + begin = 18 end = 22} + { attributes = () + begin = 22 begin2 = 0 end = 23 end2 = 25} + { attributes = (DateFormat$Field.ERA) + begin = 23 end = 25} + ) + fieldPositions = + ( + { + field = DateFormat.DAY_OF_WEEK_FIELD + fieldID = DateFormat$Field.DAY_OF_WEEK + begin = 0 end = 8 + } + { + field = DateFormat.MONTH_FIELD + fieldID = DateFormat$Field.MONTH + begin = 9 end = 17 + } + { + field = DateFormat.YEAR_FIELD + fieldID = DateFormat$Field.YEAR + begin = 18 end = 22 + } + { + field = DateFormat.ERA_FIELD + fieldID = DateFormat$Field.ERA + begin = 23 end = 25 + } + ) + } + + { + class = java.text.SimpleDateFormat + args = ("h HH:mm:ss:SSS aa") + valueClass = java.util.Date + valueArgs = ("1/1/2000 2:52:12 PM") + } + { + length = 17 + text = "2 14:52:12:000 PM" + 0 = (DateFormat$Field.HOUR1) + 1 = () + 2 = (DateFormat$Field.HOUR_OF_DAY0) + 3 = (DateFormat$Field.HOUR_OF_DAY0) + 4 = () + 5 = (DateFormat$Field.MINUTE) + 6 = (DateFormat$Field.MINUTE) + 7 = () + 8 = (DateFormat$Field.SECOND) + 9 = (DateFormat$Field.SECOND) + 10 = () + 11 = (DateFormat$Field.MILLISECOND) + 12 = (DateFormat$Field.MILLISECOND) + 13 = (DateFormat$Field.MILLISECOND) + 14 = () + 15 = (DateFormat$Field.AM_PM) + 16 = (DateFormat$Field.AM_PM) + limits = ( { attributes = (DateFormat$Field.HOUR1) + begin = 0 end = 1} + { attributes = () + begin = 1 begin2 = 0 end = 2 end2 = 17} + { attributes = (DateFormat$Field.HOUR_OF_DAY0) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 5 end2 = 17} + { attributes = (DateFormat$Field.MINUTE) + begin = 5 end = 7} + { attributes = () + begin = 7 begin2 = 0 end = 8 end2 = 17} + { attributes = (DateFormat$Field.SECOND) + begin = 8 end = 10} + { attributes = () + begin = 10 begin2 = 0 end = 11 end2 = 17} + { attributes = (DateFormat$Field.MILLISECOND) + begin = 11 end = 14} + { attributes = () + begin = 14 begin2 = 0 end = 15 end2 = 17} + { attributes = (DateFormat$Field.AM_PM) + begin = 15 end = 17} + ) + fieldPositions = + ( + { + field = DateFormat.HOUR1_FIELD + fieldID = DateFormat$Field.HOUR1 + begin = 0 end = 1 + } + { + field = DateFormat.HOUR_OF_DAY0_FIELD + fieldID = DateFormat$Field.HOUR_OF_DAY0 + begin = 2 end = 4 + } + { + field = DateFormat.MINUTE_FIELD + fieldID = DateFormat$Field.MINUTE + begin = 5 end = 7 + } + { + field = DateFormat.SECOND_FIELD + fieldID = DateFormat$Field.SECOND + begin = 8 end = 10 + } + { + field = DateFormat.MILLISECOND_FIELD + fieldID = DateFormat$Field.MILLISECOND + begin = 11 end = 14 + } + { + field = DateFormat.AM_PM_FIELD + fieldID = DateFormat$Field.AM_PM + begin = 15 end = 17 + } + ) + } + + + { + class = java.text.SimpleDateFormat + args = ("kk KK DDD FF ww WW zz") + valueClass = java.util.Date + valueArgs = ("4/26/2031 2:02:52 AM") + } + { + length = 22 + text = "02 02 116 04 17 04 PDT" + 0 = (DateFormat$Field.HOUR_OF_DAY1) + 1 = (DateFormat$Field.HOUR_OF_DAY1) + 2 = () + 3 = (DateFormat$Field.HOUR0) + 4 = (DateFormat$Field.HOUR0) + 5 = () + 6 = (DateFormat$Field.DAY_OF_YEAR) + 7 = (DateFormat$Field.DAY_OF_YEAR) + 8 = (DateFormat$Field.DAY_OF_YEAR) + 9 = () + 10 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + 11 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + 12 = () + 13 = (DateFormat$Field.WEEK_OF_YEAR) + 14 = (DateFormat$Field.WEEK_OF_YEAR) + 15 = () + 16 = (DateFormat$Field.WEEK_OF_MONTH) + 17 = (DateFormat$Field.WEEK_OF_MONTH) + 18 = () + 19 = (DateFormat$Field.TIME_ZONE) + 20 = (DateFormat$Field.TIME_ZONE) + 21 = (DateFormat$Field.TIME_ZONE) + limits = ( { attributes = (DateFormat$Field.HOUR_OF_DAY1) + begin = 0 end = 2} + { attributes = () + begin = 2 begin2 = 0 end = 3 end2 = 22} + { attributes = (DateFormat$Field.HOUR0) + begin = 3 end = 5} + { attributes = () + begin = 5 begin2 = 0 end = 6 end2 = 22} + { attributes = (DateFormat$Field.DAY_OF_YEAR) + begin = 6 end = 9} + { attributes = () + begin = 9 begin2 = 0 end = 10 end2 = 22} + { attributes = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH) + begin = 10 end = 12} + { attributes = () + begin = 12 begin2 = 0 end = 13 end2 = 22} + { attributes = (DateFormat$Field.WEEK_OF_YEAR) + begin = 13 end = 15} + { attributes = () + begin = 15 begin2 = 0 end = 16 end2 = 22} + { attributes = (DateFormat$Field.WEEK_OF_MONTH) + begin = 16 end = 18} + { attributes = () + begin = 18 begin2 = 0 end = 19 end2 = 22} + { attributes = (DateFormat$Field.TIME_ZONE) + begin = 19 end = 22} + ) + fieldPositions = + ( + { + field = DateFormat.HOUR_OF_DAY1_FIELD + fieldID = DateFormat$Field.HOUR_OF_DAY1 + begin = 0 end = 2 + } + { + field = DateFormat.HOUR0_FIELD + fieldID = DateFormat$Field.HOUR0 + begin = 3 end = 5 + } + { + field = DateFormat.DAY_OF_YEAR_FIELD + fieldID = DateFormat$Field.DAY_OF_YEAR + begin = 6 end = 9 + } + { + field = DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD + fieldID = DateFormat$Field.DAY_OF_WEEK_IN_MONTH + begin = 10 end = 12 + } + { + field = DateFormat.WEEK_OF_YEAR_FIELD + fieldID = DateFormat$Field.WEEK_OF_YEAR + begin = 13 end = 15 + } + { + field = DateFormat.WEEK_OF_MONTH_FIELD + fieldID = DateFormat$Field.WEEK_OF_MONTH + begin = 16 end = 18 + } + { + field = DateFormat.TIMEZONE_FIELD + fieldID = DateFormat$Field.TIME_ZONE + begin = 19 end = 22 + } + ) + } + ) +} diff --git a/jdk/test/java/text/Format/common/decimalFormat.props b/jdk/test/java/text/Format/common/decimalFormat.props new file mode 100644 index 00000000000..e6d9adc7974 --- /dev/null +++ b/jdk/test/java/text/Format/common/decimalFormat.props @@ -0,0 +1,1280 @@ +# +# 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. +# + +# Test data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Integer + valueArgs = ("1234567") + } + { + length = 9 + text = "1,234,567" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 9} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 9 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###.##") + valueClass = java.lang.Float + valueArgs = ("567.78") + } + { + length = 6 + text = "567.78" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 4 = (NumberFormat$Field.FRACTION) + 5 = (NumberFormat$Field.FRACTION) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 3 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.FRACTION) + begin = 4 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 3 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 3 end = 4 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 4 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("0.#E00") + valueClass = java.lang.Float + valueArgs = ("1200") + } + { + length = 6 + text = "1.2E03" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 2 = (NumberFormat$Field.FRACTION) + 3 = (NumberFormat$Field.EXPONENT_SYMBOL) + 4 = (NumberFormat$Field.EXPONENT) + 5 = (NumberFormat$Field.EXPONENT) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.FRACTION) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.EXPONENT_SYMBOL) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.EXPONENT) + begin = 4 end = 6} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 1 end = 2 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 2 end = 3 + } + { + fieldID = NumberFormat$Field.EXPONENT_SYMBOL + begin = 3 end = 4 + } + { + fieldID = NumberFormat$Field.EXPONENT + begin = 4 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("0.#E00") + valueClass = java.lang.Float + valueArgs = ("-.0012") + } + { + length = 8 + text = "-1.2E-03" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 3 = (NumberFormat$Field.FRACTION) + 4 = (NumberFormat$Field.EXPONENT_SYMBOL) + 5 = (NumberFormat$Field.EXPONENT_SIGN) + 6 = (NumberFormat$Field.EXPONENT) + 7 = (NumberFormat$Field.EXPONENT) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.FRACTION) + begin = 3 end = 4} + { attributes = (NumberFormat$Field.EXPONENT_SYMBOL) + begin = 4 end = 5} + { attributes = (NumberFormat$Field.EXPONENT_SIGN) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.EXPONENT) + begin = 6 end = 8} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 2 end = 3 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 3 end = 4 + } + { + fieldID = NumberFormat$Field.EXPONENT_SYMBOL + begin = 4 end = 5 + } + { + fieldID = NumberFormat$Field.EXPONENT_SIGN + begin = 5 end = 6 + } + { + fieldID = NumberFormat$Field.EXPONENT + begin = 6 end = 8 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###;(#,###)") + valueClass = java.lang.Integer + valueArgs = ("-1234") + } + { + length = 7 + text = "(1,234)" + 0 = () + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = () + limits = ( { attributes = () + begin = 0 end = 1 end2 = 7 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = () + begin = 6 begin2 = 0 end = 7} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 6 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###;-#,###") + valueClass = java.lang.Integer + valueArgs = ("-134") + } + { + length = 4 + text = "-134" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 4 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("+#,###") + valueClass = java.lang.Integer + valueArgs = ("134") + } + { + length = 4 + text = "+134" + 0 = () + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + limits = ( { attributes = (NumberFormat$Field.SIGN) + begin = 0 end2 = 4 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 4 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("##.0#%") + valueClass = java.lang.Float + valueArgs = (".1234") + } + { + length = 6 + text = "12.34%" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 3 = (NumberFormat$Field.FRACTION) + 4 = (NumberFormat$Field.FRACTION) + 5 = (NumberFormat$Field.PERCENT) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 2 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 2 end = 3 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 3 end = 5 } + { attributes = (NumberFormat$Field.PERCENT) + begin = 5 end = 6 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 2 end = 3 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 3 end = 5 + } + { + fieldID = NumberFormat$Field.PERCENT + begin = 5 end = 6 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,##.#\u2030") + valueClass = java.lang.Float + valueArgs = (".1234") + } + { + length = 7 + text = "1,23.4\u2030" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.GROUPING_SEPARATOR + NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 5 = (NumberFormat$Field.FRACTION) + 6 = (NumberFormat$Field.PERMILLE) + limits = ( { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 4 } + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 4 end = 5 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 5 end = 6 } + { attributes = (NumberFormat$Field.PERMILLE) + begin = 6 end = 7 } + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 4 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 4 end = 5 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 5 end = 6 + } + { + fieldID = NumberFormat$Field.PERMILLE + begin = 6 end = 7 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("\u00A40,000.00") + valueClass = java.lang.Float + valueArgs = ("12.51") + } + { + length = 9 + text = "$0,012.51" + 0 = (NumberFormat$Field.CURRENCY) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.GROUPING_SEPARATOR + NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 7 = (NumberFormat$Field.FRACTION) + 8 = (NumberFormat$Field.FRACTION) + limits = ( { attributes = (NumberFormat$Field.CURRENCY) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 6 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 3 begin2 = 1 end = 6 } + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 6 end = 7 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 7 end = 9 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.CURRENCY + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 6 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 6 end = 7 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 7 end = 9 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.math.BigInteger + valueArgs = ("-12345678901234567890123456789012345") + } + { + length = 47 + text = "-12,345,678,901,234,567,890,123,456,789,012,345" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + 26 = (NumberFormat$Field.INTEGER) + 27 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 28 = (NumberFormat$Field.INTEGER) + 29 = (NumberFormat$Field.INTEGER) + 30 = (NumberFormat$Field.INTEGER) + 31 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 32 = (NumberFormat$Field.INTEGER) + 33 = (NumberFormat$Field.INTEGER) + 34 = (NumberFormat$Field.INTEGER) + 35 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 36 = (NumberFormat$Field.INTEGER) + 37 = (NumberFormat$Field.INTEGER) + 38 = (NumberFormat$Field.INTEGER) + 39 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 40 = (NumberFormat$Field.INTEGER) + 41 = (NumberFormat$Field.INTEGER) + 42 = (NumberFormat$Field.INTEGER) + 43 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 44 = (NumberFormat$Field.INTEGER) + 45 = (NumberFormat$Field.INTEGER) + 46 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 3 end2 = 47 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 3 end = 4 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 4 begin2 = 1 end = 7 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 7 end = 8 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 8 begin2 = 1 end = 11 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 11 end = 12 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 12 begin2 = 1 end = 15 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 15 end = 16 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 16 begin2 = 1 end = 19 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 20 begin2 = 1 end = 23 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 23 end = 24 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 24 begin2 = 1 end = 27 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 27 end = 28 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 28 begin2 = 1 end = 31 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 31 end = 32 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 32 begin2 = 1 end = 35 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 35 end = 36 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 36 begin2 = 1 end = 39 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 39 end = 40 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 40 begin2 = 1 end = 43 end2 = 47} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 43 begin2 = 43 end = 44 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 44 begin2 = 1 end = 47} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 47 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###.#####################") + valueClass = java.math.BigDecimal + valueArgs = ("-123456789012345678901234567890.12345678901234567890") + } + { + length = 60 + text = "-123,456,789,012,345,678,901,234,567,890.1234567890123456789" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 25 = (NumberFormat$Field.INTEGER) + 26 = (NumberFormat$Field.INTEGER) + 27 = (NumberFormat$Field.INTEGER) + 28 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 29 = (NumberFormat$Field.INTEGER) + 30 = (NumberFormat$Field.INTEGER) + 31 = (NumberFormat$Field.INTEGER) + 32 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 33 = (NumberFormat$Field.INTEGER) + 34 = (NumberFormat$Field.INTEGER) + 35 = (NumberFormat$Field.INTEGER) + 36 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR) + 37 = (NumberFormat$Field.INTEGER) + 38 = (NumberFormat$Field.INTEGER) + 39 = (NumberFormat$Field.INTEGER) + 40 = (NumberFormat$Field.DECIMAL_SEPARATOR) + 41 = (NumberFormat$Field.FRACTION) + 42 = (NumberFormat$Field.FRACTION) + 43 = (NumberFormat$Field.FRACTION) + 44 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 45 = (NumberFormat$Field.FRACTION) + 46 = (NumberFormat$Field.FRACTION) + 47 = (NumberFormat$Field.FRACTION) + 48 = (NumberFormat$Field.FRACTION) + 49 = (NumberFormat$Field.FRACTION) + 50 = (NumberFormat$Field.FRACTION) + 51 = (NumberFormat$Field.FRACTION) + 52 = (NumberFormat$Field.FRACTION) + 53 = (NumberFormat$Field.FRACTION) + 54 = (NumberFormat$Field.FRACTION) + 55 = (NumberFormat$Field.FRACTION) + 56 = (NumberFormat$Field.FRACTION) + 57 = (NumberFormat$Field.FRACTION) + 58 = (NumberFormat$Field.FRACTION) + 59 = (NumberFormat$Field.FRACTION) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 4 end2 = 40 } + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 4 end = 5 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 5 begin2 = 1 end = 8 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 8 end = 9 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 9 begin2 = 1 end = 12 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 12 end = 13 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 13 begin2 = 1 end = 16 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 16 end = 17 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 17 begin2 = 1 end = 20 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 20 end = 21 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 21 begin2 = 1 end = 24 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 24 end = 25 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 25 begin2 = 1 end = 28 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 28 end = 29 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 29 begin2 = 1 end = 32 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 32 end = 33 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 33 begin2 = 1 end = 36 end2 = 40} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 36 end = 37 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 37 begin2 = 1 end = 40 end2 = 40} + { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR) + begin = 40 end = 41 } + { attributes = (NumberFormat$Field.FRACTION) + begin = 41 begin2 = 41 end = 60 } + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + fieldID = NumberFormat$Field.DECIMAL_SEPARATOR + begin = 40 end = 41 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 40 + } + { + field = NumberFormat.FRACTION_FIELD + fieldID = NumberFormat$Field.FRACTION + begin = 41 end = 60 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Long + valueArgs = ("9223372036854775807") + } + { + length = 25 + text = "9,223,372,036,854,775,807" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 25} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 25 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicLong + valueArgs = ("9223372036854775807") + } + { + length = 25 + text = "9,223,372,036,854,775,807" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 14 = (NumberFormat$Field.INTEGER) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 18 = (NumberFormat$Field.INTEGER) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 22 = (NumberFormat$Field.INTEGER) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 25} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 13 end = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 17 end = 18} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 21 end = 22} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 25 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.lang.Long + valueArgs = ("-9223372036854775808") + } + { + length = 26 + text = "-9,223,372,036,854,775,808" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 26} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 26 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicLong + valueArgs = ("-9223372036854775808") + } + { + length = 26 + text = "-9,223,372,036,854,775,808" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + 14 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 15 = (NumberFormat$Field.INTEGER) + 16 = (NumberFormat$Field.INTEGER) + 17 = (NumberFormat$Field.INTEGER) + 18 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 19 = (NumberFormat$Field.INTEGER) + 20 = (NumberFormat$Field.INTEGER) + 21 = (NumberFormat$Field.INTEGER) + 22 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 23 = (NumberFormat$Field.INTEGER) + 24 = (NumberFormat$Field.INTEGER) + 25 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 26} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 14 end = 15} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 18 end = 19} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 22 end = 23} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 26 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicInteger + valueArgs = ("2147483647") + } + { + length = 13 + text = "2,147,483,647" + 0 = (NumberFormat$Field.INTEGER) + 1 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 2 = (NumberFormat$Field.INTEGER) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 6 = (NumberFormat$Field.INTEGER) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 10 = (NumberFormat$Field.INTEGER) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.INTEGER) + begin = 0 end = 1 end2 = 13} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 1 end = 2} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 5 end = 6} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 9 end = 10} + ) + fieldPositions = + ( + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 0 end = 13 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 1 end = 2 + } + ) + } + + { + class = java.text.DecimalFormat + args = ("#,###") + valueClass = java.util.concurrent.atomic.AtomicInteger + valueArgs = ("-2147483648") + } + { + length = 14 + text = "-2,147,483,648" + 0 = (NumberFormat$Field.SIGN) + 1 = (NumberFormat$Field.INTEGER) + 2 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 3 = (NumberFormat$Field.INTEGER) + 4 = (NumberFormat$Field.INTEGER) + 5 = (NumberFormat$Field.INTEGER) + 6 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 7 = (NumberFormat$Field.INTEGER) + 8 = (NumberFormat$Field.INTEGER) + 9 = (NumberFormat$Field.INTEGER) + 10 = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 11 = (NumberFormat$Field.INTEGER) + 12 = (NumberFormat$Field.INTEGER) + 13 = (NumberFormat$Field.INTEGER) + limits = ( + { attributes = (NumberFormat$Field.SIGN) + begin = 0 end = 1 } + { attributes = (NumberFormat$Field.INTEGER) + begin = 1 end = 2 end2 = 14} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 2 end = 3} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 6 end = 7} + { attributes = (NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 10 end = 11} + ) + fieldPositions = + ( + { + fieldID = NumberFormat$Field.SIGN + begin = 0 end = 1 + } + { + field = NumberFormat.INTEGER_FIELD + fieldID = NumberFormat$Field.INTEGER + begin = 1 end = 14 + } + { + fieldID = NumberFormat$Field.GROUPING_SEPARATOR + begin = 2 end = 3 + } + ) + } + ) +} diff --git a/jdk/test/java/text/Format/common/messageFormat.props b/jdk/test/java/text/Format/common/messageFormat.props new file mode 100644 index 00000000000..c8aaeecfd32 --- /dev/null +++ b/jdk/test/java/text/Format/common/messageFormat.props @@ -0,0 +1,520 @@ +# +# 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. +# + +# Test data for FormatIteratorTest + +{ + tests = + ( + { + class = java.text.MessageFormat + args = ("0={0} 1={1}") + valueClass = java.lang.reflect.Array + valueArgs = ("zero" "one") + } + { + length = 12 + text = "0=zero 1=one" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = (MessageFormat$Field.ARGUMENT) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = () + 7 = () + 8 = () + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT) + 11 = (MessageFormat$Field.ARGUMENT) + limits = ( { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 6} + { attributes = () + begin = 0 begin2 = 0 end = 2 end2 = 12} + { attributes = () + begin = 6 begin2 = 0 end = 9 end2 = 12} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 9 end = 12} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 6 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0} 1={1} 0={0}") + valueClass = java.lang.reflect.Array + valueArgs = ("ze" "on") + } + { + length = 14 + text = "0=ze 1=on 0=ze" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = () + 5 = () + 6 = () + 7 = (MessageFormat$Field.ARGUMENT) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = () + 10 = () + 11 = () + 12 = (MessageFormat$Field.ARGUMENT) + 13 = (MessageFormat$Field.ARGUMENT) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 4} + { attributes = () + begin = 4 begin2 = 0 end = 7 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 7 end = 9} + { attributes = () + begin = 9 begin2 = 0 end = 12 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 12 end = 14} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 4 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("5/23/2001")) (Integer ("20122"))) + } + { + length = 23 + text = "0=May 23, 2001 1=20,122" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 17 end = 19 end2 = 23} + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 17 end = 19 end2 = 23} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 20 begin2 = 17 end = 23} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("1/22/2003")) (java.math.BigInteger ("12345678901234567890123456789012345"))) + } + { + length = 63 + text = "0=Jan 22, 2003 1=12,345,678,901,234,567,890,123,456,789,012,345" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 48 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 49 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 50 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 51 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 52 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 53 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 54 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 55 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 56 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 57 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 58 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 59 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 60 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 61 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 62 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 63} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 63} + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 17 end = 19 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 19 end = 20 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 20 begin2 = 17 end = 23 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 23 end = 24 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 24 begin2 = 17 end = 27 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 27 end = 28 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 28 begin2 = 17 end = 31 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 31 end = 32 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 32 begin2 = 17 end = 35 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 35 end = 36 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 36 begin2 = 17 end = 39 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 39 end = 40 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 40 begin2 = 17 end = 43 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 43 end = 44 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 44 begin2 = 17 end = 47 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 47 end = 48 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 48 begin2 = 17 end = 51 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 51 end = 52 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 52 begin2 = 17 end = 55 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 55 end = 56 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 56 begin2 = 17 end = 59 end2 = 63} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 59 end = 60 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 60 begin2 = 17 end = 63} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,date} 1={1,number}") + valueClass = java.lang.reflect.Array + valueArgs = ((java.util.Date ("1/26/2003")) (java.math.BigDecimal ("-12345678901234567890.1239"))) + } + { + length = 48 + text = "0=Jan 26, 2003 1=-12,345,678,901,234,567,890.124" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH) + 5 = (MessageFormat$Field.ARGUMENT) + 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH) + 8 = (MessageFormat$Field.ARGUMENT) + 9 = (MessageFormat$Field.ARGUMENT) + 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR) + 14 = () + 15 = () + 16 = () + 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.SIGN) + 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER + NumberFormat$Field.GROUPING_SEPARATOR) + 41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER) + 44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.DECIMAL_SEPARATOR) + 45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + 46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + 47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION) + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 48} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5 end2 = 14} + { attributes = (MessageFormat$Field.ARGUMENT + DateFormat$Field.MONTH) + begin = 2 end = 5} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 5 begin2 = 2 end = 6 end2 = 14} + { attributes = (DateFormat$Field.DAY_OF_MONTH) + begin = 6 end = 8} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 8 begin2 = 2 end = 10 end2 = 14} + { attributes = () + begin = 14 begin2 = 0 end = 17 end2 = 48} + + { attributes = (NumberFormat$Field.SIGN) + begin = 17 end = 18 } + { attributes = (MessageFormat$Field.ARGUMENT + NumberFormat$Field.INTEGER) + begin = 18 end = 20 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 20 end = 21 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 21 begin2 = 18 end = 24 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 24 end = 25 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 25 begin2 = 18 end = 28 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 28 end = 29 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 29 begin2 = 18 end = 32 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 32 end = 33 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 33 begin2 = 18 end = 36 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 36 end = 37 } + + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 37 begin2 = 18 end = 40 end2 = 44} + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 40 end = 41 } + { attributes = (NumberFormat$Field.INTEGER + MessageFormat$Field.ARGUMENT) + begin = 41 begin2 = 18 end = 44 end2 = 44} + + { attributes = (NumberFormat$Field.GROUPING_SEPARATOR) + begin = 44 begin2 = 41 end = 45 end2 = 48} + + { attributes = (NumberFormat$Field.FRACTION + MessageFormat$Field.ARGUMENT) + begin = 45 end = 48} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 14 + } + ) + } + + { + class = java.text.MessageFormat + args = ("0={0,choice,-1#neg| 0#zero | 1#more}xx") + valueClass = java.lang.reflect.Array + valueArgs = ((Integer ("-11"))) + } + { + length = 7 + text = "0=negxx" + 0 = () + 1 = () + 2 = (MessageFormat$Field.ARGUMENT) + 3 = (MessageFormat$Field.ARGUMENT) + 4 = (MessageFormat$Field.ARGUMENT) + 5 = () + 6 = () + limits = ( + { attributes = () + begin = 0 end = 2 end2 = 7} + { attributes = (MessageFormat$Field.ARGUMENT) + begin = 2 end = 5} + { attributes = () + begin = 5 begin2 = 0 end = 7} + ) + fieldPositions = + ( + { + fieldID = MessageFormat$Field.ARGUMENT + begin = 2 end = 5 + } + ) + } + ) +} + diff --git a/jdk/test/java/text/testlib/HexDumpReader.java b/jdk/test/java/text/testlib/HexDumpReader.java new file mode 100644 index 00000000000..31a820d04d4 --- /dev/null +++ b/jdk/test/java/text/testlib/HexDumpReader.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/** + * HexDumpReader provides utility methods to read a hex dump text file + * and convert to an InputStream. The format supported by the methods + * can be generated by the following command. + * + * $ od -vw -t x1 foo | sed -r -e 's/^[0-9]+ ?//' -e 's/ //g' -e '/^$/d' + */ +public class HexDumpReader { + public static InputStream getStreamFromHexDump(String fileName) { + return getStreamFromHexDump(new File(System.getProperty("test.src", "."), + fileName)); + } + + public static InputStream getStreamFromHexDump(File hexFile) { + ByteArrayBuilder bab = new ByteArrayBuilder(); + int lineNo = 0; + try (BufferedReader reader + = new BufferedReader(new InputStreamReader(new FileInputStream(hexFile), + "us-ascii"))) { + String line; + while ((line = reader.readLine()) != null) { + lineNo++; + line = line.trim(); + // Skip blank and comment lines. + if (line.length() == 0) { + continue; + } + int x = line.indexOf('#'); + if (x == 0) { + continue; + } + if (x > 0) { + line = line.substring(0, x).trim(); + } + int len = line.length(); + for (int i = 0; i < len; i += 2) { + bab.put((byte)Integer.parseInt(line, i, i + 2, 16)); + } + } + } catch (Exception e) { + throw new RuntimeException(hexFile.getName() + ":error:" + lineNo + ": " + e, e); + } + return new ByteArrayInputStream(bab.toArray()); + } + + + private static class ByteArrayBuilder { + private static final int BUFFER_SIZE = 4096; + + private int size; + private List bytes; + private byte[] current; + private int offset; + + ByteArrayBuilder() { + bytes = new ArrayList<>(); + current = new byte[BUFFER_SIZE]; + } + + void put(byte b) { + if (offset == BUFFER_SIZE) { + bytes.add(current); + current = new byte[BUFFER_SIZE]; + offset = 0; + } + current[offset++] = b; + size++; + } + + byte[] toArray() { + byte[] buf = new byte[size]; + int ptr = 0; + for (byte[] ba : bytes) { + System.arraycopy(ba, 0, buf, ptr, ba.length); + ptr += ba.length; + } + System.arraycopy(current, 0, buf, ptr, offset); + assert ptr + offset == size; + return buf; + } + } + +} diff --git a/jdk/test/java/text/testlib/IntlTest.java b/jdk/test/java/text/testlib/IntlTest.java new file mode 100644 index 00000000000..d8ae8572f30 --- /dev/null +++ b/jdk/test/java/text/testlib/IntlTest.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * IntlTest is a base class for tests that can be run conveniently from + * the command line as well as under the Java test harness. + *

    + * Sub-classes implement a set of public void methods named "Test*" or + * "test*" with no arguments. Each of these methods performs some + * test. Test methods should indicate errors by calling either err() or + * errln(). This will increment the errorCount field and may optionally + * print a message to the log. Debugging information may also be added to + * the log via the log and logln methods. These methods will add their + * arguments to the log only if the test is being run in verbose mode. + */ +public abstract class IntlTest { + + //------------------------------------------------------------------------ + // Everything below here is boilerplate code that makes it possible + // to add a new test by simply adding a method to an existing class. + //------------------------------------------------------------------------ + + protected IntlTest() { + // Populate testMethods with all the test methods. + Method[] methods = getClass().getDeclaredMethods(); + for (Method method : methods) { + if (Modifier.isPublic(method.getModifiers()) + && method.getReturnType() == void.class + && method.getParameterCount() == 0) { + String name = method.getName(); + if (name.length() > 4) { + if (name.startsWith("Test") || name.startsWith("test")) { + testMethods.put(name, method); + } + } + } + } + } + + protected void run(String[] args) throws Exception + { + // Set up the log and reference streams. We use PrintWriters in order to + // take advantage of character conversion. The JavaEsc converter will + // convert Unicode outside the ASCII range to Java's \\uxxxx notation. + log = new PrintWriter(System.out, true); + + // Parse the test arguments. They can be either the flag + // "-verbose" or names of test methods. Create a list of + // tests to be run. + List testsToRun = new ArrayList<>(args.length); + for (String arg : args) { + switch (arg) { + case "-verbose": + verbose = true; + break; + case "-prompt": + prompt = true; + break; + case "-nothrow": + nothrow = true; + break; + default: + Method m = testMethods.get(arg); + if (m == null) { + System.out.println("Method " + arg + ": not found"); + usage(); + return; + } + testsToRun.add(m); + break; + } + } + + // If no test method names were given explicitly, run them all. + if (testsToRun.isEmpty()) { + testsToRun.addAll(testMethods.values()); + } + + System.out.println(getClass().getName() + " {"); + indentLevel++; + + // Run the list of tests given in the test arguments + for (Method testMethod : testsToRun) { + int oldCount = errorCount; + + writeTestName(testMethod.getName()); + + try { + testMethod.invoke(this, new Object[0]); + } catch (IllegalAccessException e) { + errln("Can't acces test method " + testMethod.getName()); + } catch (InvocationTargetException e) { + errln("Uncaught exception thrown in test method " + + testMethod.getName()); + e.getTargetException().printStackTrace(this.log); + } + writeTestResult(errorCount - oldCount); + } + indentLevel--; + writeTestResult(errorCount); + + if (prompt) { + System.out.println("Hit RETURN to exit..."); + try { + System.in.read(); + } catch (IOException e) { + System.out.println("Exception: " + e.toString() + e.getMessage()); + } + } + if (nothrow) { + System.exit(errorCount); + } + } + + /** + * Adds the given message to the log if we are in verbose mode. + */ + protected void log(String message) { + logImpl(message, false); + } + + protected void logln(String message) { + logImpl(message, true); + } + + protected void logln() { + logImpl(null, true); + } + + private void logImpl(String message, boolean newline) { + if (verbose) { + if (message != null) { + indent(indentLevel + 1); + log.print(message); + } + if (newline) { + log.println(); + } + } + } + + protected void err(String message) { + errImpl(message, false); + } + + protected void errln(String message) { + errImpl(message, true); + } + + private void errImpl(String message, boolean newline) { + errorCount++; + indent(indentLevel + 1); + log.print(message); + if (newline) { + log.println(); + } + log.flush(); + + if (!nothrow) { + throw new RuntimeException(message); + } + } + + protected int getErrorCount() { + return errorCount; + } + + protected void writeTestName(String testName) { + indent(indentLevel); + log.print(testName); + log.flush(); + needLineFeed = true; + } + + protected void writeTestResult(int count) { + if (!needLineFeed) { + indent(indentLevel); + log.print("}"); + } + needLineFeed = false; + + if (count != 0) { + log.println(" FAILED"); + } else { + log.println(" Passed"); + } + } + + /* + * Returns a spece-delimited hex String. + */ + protected static String toHexString(String s) { + StringBuilder sb = new StringBuilder(" "); + + for (int i = 0; i < s.length(); i++) { + sb.append(Integer.toHexString(s.charAt(i))); + sb.append(' '); + } + + return sb.toString(); + } + + private void indent(int distance) { + if (needLineFeed) { + log.println(" {"); + needLineFeed = false; + } + log.print(SPACES.substring(0, distance * 2)); + } + + /** + * Print a usage message for this test class. + */ + void usage() { + System.out.println(getClass().getName() + + ": [-verbose] [-nothrow] [-prompt] [test names]"); + + System.out.println(" Available test names:"); + for (String methodName : testMethods.keySet()) { + System.out.println("\t" + methodName); + } + } + + private boolean prompt; + private boolean nothrow; + protected boolean verbose; + + private PrintWriter log; + private int indentLevel; + private boolean needLineFeed; + private int errorCount; + + private final Map testMethods = new LinkedHashMap<>(); + + private static final String SPACES = " "; +} diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java b/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java index d1092d15ee6..c86805f9bfe 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java +++ b/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java @@ -442,28 +442,44 @@ public class TCKIsoFields { } //----------------------------------------------------------------------- - // range refinedby + // rangeRefinedBy //----------------------------------------------------------------------- @DataProvider(name="isofields") Object[][] data_isofields() { return new Object[][] { - {IsoFields.DAY_OF_QUARTER}, - {IsoFields.QUARTER_OF_YEAR}, - {IsoFields.WEEK_OF_WEEK_BASED_YEAR}, - {IsoFields.WEEK_BASED_YEAR}, + {IsoFields.DAY_OF_QUARTER, 49, ValueRange.of(1, 91)}, + {IsoFields.QUARTER_OF_YEAR, 2, ValueRange.of(1, 4)}, + {IsoFields.WEEK_OF_WEEK_BASED_YEAR, 20, ValueRange.of(1, 52)}, + {IsoFields.WEEK_BASED_YEAR, 2016, ValueRange.of(LocalDate.MIN.getYear(), + LocalDate.MAX.getYear())}, }; } @Test(dataProvider = "isofields") - public void test_isofields_rangerefinedby(TemporalField field) { - field.rangeRefinedBy(LocalDate.now()); + public void test_isofields_rangerefinedby(TemporalField field, int value, ValueRange valueRange) { + LocalDate date = LocalDate.of(2016, 5, 19); + assertEquals(field.rangeRefinedBy(date), valueRange); } @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class) - public void test_nonisofields_rangerefinedby(TemporalField field) { + public void test_nonisofields_rangerefinedby(TemporalField field, int value, ValueRange valueRange) { field.rangeRefinedBy(ThaiBuddhistDate.now()); } + //----------------------------------------------------------------------- + // getFrom + //----------------------------------------------------------------------- + @Test(dataProvider = "isofields") + public void test_isofields_getFrom(TemporalField field, int value, ValueRange valueRange) { + LocalDate date = LocalDate.of(2016, 5, 19); + assertEquals(field.getFrom(date), value); + } + + @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class) + public void test_nonisofields_getFrom(TemporalField field, int value, ValueRange valueRange) { + field.getFrom(ThaiBuddhistDate.now()); + } + //----------------------------------------------------------------------- public void test_loop() { // loop round at least one 400 year cycle, including before 1970 diff --git a/jdk/test/java/util/Calendar/BuddhistCalendarTest.java b/jdk/test/java/util/Calendar/BuddhistCalendarTest.java new file mode 100644 index 00000000000..8d6a5fc3466 --- /dev/null +++ b/jdk/test/java/util/Calendar/BuddhistCalendarTest.java @@ -0,0 +1,243 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4817812 4847186 4956227 4956479 + * @summary Confirm that BuddhistCalendar's add(), roll() and toString() work correctly with Buddhist Era years. + */ + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Locale; +import static java.util.Calendar.*; + +public class BuddhistCalendarTest { + + private static final Locale THAI_LOCALE = new Locale("th", "TH"); + + public static void main(String[] args) { + testAddRoll(); + testToString(); + testException(); + testLeastMax(); + } + + /** + * 4817812 + */ + static void testAddRoll() { + Calendar cal; + int base, year; + + /* + * Test: BuddhistCalendar.add(YEAR) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.add(YEAR, 1); + year = cal.get(YEAR); + check(year, base+1, "add(+YEAR)"); + + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.add(YEAR, -3); + year = cal.get(YEAR); + check(year, base-3, "add(-YEAR)"); + + /* + * Test BuddhistCalendar.add(MONTH) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(MONTH, DECEMBER); + cal.add(MONTH, 2); + year = cal.get(YEAR); + check(year, base+1, "add(+MONTH)"); + + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(MONTH, FEBRUARY); + cal.add(MONTH, -4); + year = cal.get(YEAR); + check(year, base-1, "add(-MONTH)"); + + /* + * Test BuddhistCalendar.roll(YEAR) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.roll(YEAR, 2); + year = cal.get(YEAR); + check(year, base+2, "roll(+YEAR)"); + + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.roll(YEAR, -4); + year = cal.get(YEAR); + check(year, base-4, "roll(-YEAR)"); + + /* + * Test BuddhistCalendar.roll(WEEK_OF_YEAR) + */ + cal = getBuddhistCalendar(); + cal.set(YEAR, 2543); // A.D.2000 + cal.set(MONTH, DECEMBER); + cal.set(DATE, 31); + base = cal.get(YEAR); + check(base, 2543, "roll(+WEEK_OF_YEAR)"); + cal.roll(WEEK_OF_YEAR, 10); + year = cal.get(YEAR); + check(year, base, "roll(+WEEK_OF_YEAR)"); + + cal = getBuddhistCalendar(); + cal.set(YEAR, 2543); // A.D.2000 + cal.set(MONTH, JANUARY); + cal.set(DATE, 1); + base = cal.get(YEAR); + check(base, 2543, "roll(+WEEK_OF_YEAR)"); + cal.roll(WEEK_OF_YEAR, -10); + year = cal.get(YEAR); + check(year, base, "roll(-WEEK_OF_YEAR)"); + + /* + * Test Calendar.set(year, month, date) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(3001, APRIL, 10); + year = cal.get(YEAR); + check(year, 3001, "set(year, month, date)"); + + /* + * Test Calendar.set(year, month, date, hour, minute) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(3020, MAY, 20, 9, 10); + year = cal.get(YEAR); + check(year, 3020, "set(year, month, date, hour, minute)"); + + /* + * Test Calendar.set(year, month, date, hour, minute, second) + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + cal.set(3120, MAY, 20, 9, 10, 52); + year = cal.get(YEAR); + check(year, 3120, "set(year, month, date, hour, minute, second)"); + + /* + * Test BuddhistCalendar.getActualMaximum(YEAR); + * set(YEAR)/get(YEAR) in this method doesn't affect the real + * YEAR value because a clone is used with set()&get(). + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + int limit = cal.getActualMaximum(YEAR); + year = cal.get(YEAR); + check(year, base, "BuddhistCalendar.getActualMaximum(YEAR)"); + + /* + * Test BuddhistCalendar.getActualMinimum(YEAR); + * This doesn't call set(YEAR) nor get(YEAR), though. + */ + cal = getBuddhistCalendar(); + base = cal.get(YEAR); + limit = cal.getActualMinimum(YEAR); + year = cal.get(YEAR); + check(year, base, "BuddhistCalendar.getActualMinimum(YEAR)"); + } + + /** + * 4847186: BuddhistCalendar: toString() returns Gregorian year + */ + static void testToString() { + Calendar cal = getBuddhistCalendar(); + int year = cal.get(YEAR); + String s = cal.toString(); + String y = s.replaceAll(".+,YEAR=(\\d+),.+", "$1"); + if (Integer.parseInt(y) != year) { + throw new RuntimeException("toString(): wrong year value: got " + y + + ", expected " + year); + } + } + + /** + * 4956479: BuddhistCalendar methods may return wrong values after exception + */ + static void testException() { + Calendar cal = getBuddhistCalendar(); + int year = cal.get(YEAR); + boolean exceptionOccurred = false; + try { + cal.add(100, +1); // cause exception + } catch (Exception e) { + exceptionOccurred = true; + } + if (!exceptionOccurred) { + throw new RuntimeException("testException: test case failed: no exception thrown"); + } + int year2 = cal.get(YEAR); + if (year2 != year) { + throw new RuntimeException("wrong year value after exception: got " + year2 + + ", expected " + year); + } + } + + /** + * 4956227: getLeastMaximum(WEEK_OF_MONTH) return diff. val. for Greg. and Buddhist Calendar + */ + static void testLeastMax() { + Calendar bc = getBuddhistCalendar(); + // Specify THAI_LOCALE to get the same params for WEEK + // calculations (6904680). + Calendar gc = new GregorianCalendar(THAI_LOCALE); + for (int f = 0; f < Calendar.FIELD_COUNT; f++) { + if (f == ERA || f == YEAR) { + continue; + } + int bn = bc.getLeastMaximum(f); + int gn = gc.getLeastMaximum(f); + if (bn != gn) { + throw new RuntimeException("inconsistent Least Max value for " + Koyomi.getFieldName(f) + + ": Buddhist=" + bn + + ": Gregorian=" + gn); + } + } + } + + /** + * @return a BuddhistCalendar + */ + static Calendar getBuddhistCalendar() { + return Calendar.getInstance(THAI_LOCALE); + } + + static void check(int got, int expected, String s) { + if (got != expected) { + throw new RuntimeException("Failed: " + + s + ": got:" + got + ", expected:" + expected); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug4302966.java b/jdk/test/java/util/Calendar/Bug4302966.java new file mode 100644 index 00000000000..6c3b9c3d60e --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug4302966.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4302966 + * @summary In Czech Republic first day of week is Monday not Sunday + */ + +import java.util.Calendar; +import java.util.Locale; + +public class Bug4302966 { + + public static void main(String[] args) { + Calendar czechCalendar = Calendar.getInstance(new Locale("cs")); + int firstDayOfWeek = czechCalendar.getFirstDayOfWeek(); + if (firstDayOfWeek != Calendar.MONDAY) { + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug4766302.java b/jdk/test/java/util/Calendar/Bug4766302.java new file mode 100644 index 00000000000..42df92b7e16 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug4766302.java @@ -0,0 +1,51 @@ +/* + * 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 4766302 + * @summary Make sure that computeTime call doesn't reset the isTimeSet value. + */ + +import java.util.GregorianCalendar; + +public class Bug4766302 { + + static class MyCalendar extends GregorianCalendar { + boolean isTimeStillSet() { + return isTimeSet; + } + + protected void computeTime() { + super.computeTime(); + } + } + + public static void main(String[] args) { + MyCalendar cal = new MyCalendar(); + cal.computeTime(); + if (!cal.isTimeStillSet()) { + throw new RuntimeException("computeTime() call reset isTimeSet."); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug4851640.java b/jdk/test/java/util/Calendar/Bug4851640.java new file mode 100644 index 00000000000..4f5add37679 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug4851640.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4851640 + * @summary Make sure not to set UNSET fields to COMPUTED after time calculation. + */ + +import java.util.GregorianCalendar; +import static java.util.Calendar.*; + +public class Bug4851640 { + + public static void main(String args[]) { + GregorianCalendar cal = new GregorianCalendar(); + cal.clear(); + cal.set(YEAR, 2003); + long t = cal.getTime().getTime(); + + // For the time calculation, the MONTH and DAY_OF_MONTH fields + // (with the default values) have been used for determining + // the date. However, both the MONTH and DAY_OF_MONTH fields + // should be kept UNSET after the time calculation. + if (cal.isSet(MONTH) || cal.isSet(DAY_OF_MONTH)) { + throw new RuntimeException("After getTime(): MONTH field=" + cal.isSet(MONTH) + + ", DAY_OF_MONTH field=" + cal.isSet(DAY_OF_MONTH)); + } + + // After calling get() for any field, all field values are + // recalculated and their field states are set to + // COMPUTED. isSet() must return true. + int y = cal.get(YEAR); + if (!(cal.isSet(MONTH) && cal.isSet(DAY_OF_MONTH))) { + throw new RuntimeException("After get(): MONTH field=" + cal.isSet(MONTH) + + ", DAY_OF_MONTH field=" + cal.isSet(DAY_OF_MONTH)); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug4958050.java b/jdk/test/java/util/Calendar/Bug4958050.java new file mode 100644 index 00000000000..dfd627cda6f --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug4958050.java @@ -0,0 +1,255 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4958050 + * @summary Make sure that add() and roll() handle time zone offset changes (both raw and DST) correctly. + */ + +import java.util.Locale; +import java.util.TimeZone; +import static java.util.Calendar.*; + +public class Bug4958050 { + static int errorCount = 0; + + public static void main(String[] args) { + // All the test cases depend on historical GMT offset changes + // of Asia/Novosibirsk. + Koyomi cal = new Koyomi(TimeZone.getTimeZone("Asia/Novosibirsk"), Locale.US); + System.out.println("Time zone = " + cal.getTimeZone().getID()); + + // Test the week fields + int[] weekFields = { WEEK_OF_YEAR, WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH }; + for (int i = 0; i < weekFields.length; i++) { + int field = weekFields[i]; + // add() + cal.clear(); + cal.set(1919, DECEMBER, 14-7, 23, 50, 00); + cal.add(weekFields[i], +1); + if (!cal.checkDate(1919, DECEMBER, 14)) { + error("1919/12/07: add("+cal.getFieldName(weekFields[i])+", +1)\n" + + cal.getMessage()+" " + cal.toDateTimeString()); + } + cal.clear(); + cal.set(1930, JUNE, 21-7); + cal.add(weekFields[i], +1); + if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { + error("1930/6/14: add("+cal.getFieldName(weekFields[i])+", +1)\n" + + cal.getMessage()+" " + cal.toDateTimeString()); + } + + // roll() + cal.clear(); + cal.set(1919, DECEMBER, 14-7, 23, 50, 00); + cal.roll(weekFields[i], +1); + if (!cal.checkDate(1919, DECEMBER, 14)) { + error("1919/12/07: roll("+cal.getFieldName(weekFields[i])+", +1)\n" + + cal.getMessage()+" " + cal.toDateTimeString()); + } + cal.clear(); + cal.set(1930, JUNE, 21-7); + cal.roll(weekFields[i], +1); + if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { + error("1930/6/14: roll("+cal.getFieldName(weekFields[i])+", +1)\n" + + cal.getMessage()+" " + cal.toDateTimeString()); + } + } + + // Test the day fields + int[] dayFields = { DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK }; + for (int i = 0; i < dayFields.length; i++) { + int field = dayFields[i]; + // add() + cal.clear(); + cal.set(1919, DECEMBER, 14-1, 23, 50, 00); + cal.add(field, +1); + if (!cal.checkDate(1919, DECEMBER, 14)) { + error("1919/12/13: add("+cal.getFieldName(field)+", +1)\n" + + cal.getMessage()+" " + cal.toDateTimeString()); + } + cal.clear(); + cal.set(1919, DECEMBER, 14, 00, 00, 00); + cal.add(field, -1); + if (!cal.checkDate(1919, DECEMBER, 13)) { + error("1919/12/14: add("+cal.getFieldName(field)+", -1)\n" + + cal.getMessage()+" " + cal.toDateTimeString()); + } + cal.clear(); + cal.set(1930, JUNE, 21-1); + cal.add(field, +1); + if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { + error("1930/6/20: add("+cal.getFieldName(field)+", +1)\n" + + cal.getMessage() + cal.toDateTimeString()); + } + cal.clear(); + cal.set(1930, JUNE, 21, 01, 00, 00); + cal.add(field, -1); + if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) { + error("1930/6/21: add("+cal.getFieldName(field)+", -1)\n" + + cal.getMessage()+" " + cal.toDateTimeString()); + } + + // roll() + cal.clear(); + cal.set(1930, JUNE, 21-1); + int amount = +1; + if (field == DAY_OF_WEEK) { + amount += 700; + } + cal.roll(field, amount); + if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { + error("1930/6/20: roll("+cal.getFieldName(field)+", +"+amount+")\n" + + cal.getMessage() + " " + cal.toDateTimeString()); + } + cal.clear(); + cal.set(1930, JUNE, 21, 01, 00, 00); + amount = -1; + if (field == DAY_OF_WEEK) { + amount -= 700; + } + cal.roll(field, amount); + if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) { + error("1930/6/21: roll("+cal.getFieldName(field)+", "+amount+")\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + } + + // Test the AM_PM field + // add() + cal.clear(); + cal.set(1919, DECEMBER, 14-1, 23, 50, 00); + cal.add(AM_PM, +1); + if (!cal.checkDate(1919, DECEMBER, 14) + || !cal.checkFieldValue(AM_PM, AM)) { + error("1919/12/13: add(AM_PM, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + cal.set(1930, JUNE, 21-1, 12, 00, 00); + cal.add(AM_PM, +1); + if (!cal.checkDate(1930, JUNE, 21) + || !cal.checkFieldValue(AM_PM, AM)) { + error("1930/6/20: add(AM_PM, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + cal.set(1930, JUNE, 21-2, 12, 00, 00); + cal.add(AM_PM, +3); + if (!cal.checkDate(1930, JUNE, 21) + || !cal.checkFieldValue(AM_PM, AM)) { + error("1930/6/10: add(AM_PM, +3)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + cal.set(1919, DECEMBER, 14, 11, 50, 00); + cal.add(AM_PM, -1); + if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23, 50, 00, 000) + || !cal.checkFieldValue(AM_PM, PM)) { + error("1919/12/14 11:50:00: add(AM_PM, -1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + cal.set(1930, JUNE, 21, 01, 00, 00); + cal.add(AM_PM, -1); + if (!cal.checkDateTime(1930, JUNE, 21-1, 01+12, 00, 00, 000) + || !cal.checkFieldValue(AM_PM, PM)) { + error("1930/6/20: add(AM_PM, -1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + cal.set(1930, JUNE, 21, 01, 00, 00); + cal.add(AM_PM, -3); + if (!cal.checkDateTime(1930, JUNE, 21-2, 01+12, 00, 00, 000) + || !cal.checkFieldValue(AM_PM, PM)) { + error("1930/6/10: add(AM_PM, -3)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + // roll() (should NOT change the date) + cal.clear(); + cal.set(1919, DECEMBER, 14-1, 23, 50, 00); + cal.roll(AM_PM, +1); + if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23-12, 50, 00, 000) + || !cal.checkFieldValue(AM_PM, AM)) { + error("1919/12/13: roll(AM_PM, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + cal.set(1930, JUNE, 21-1, 12, 00, 00); + cal.roll(AM_PM, +1); + if (!cal.checkDateTime(1930, JUNE, 21-1, 12-12, 00, 00, 000) + || !cal.checkFieldValue(AM_PM, AM)) { + error("1930/6/20: roll(AM_PM, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + cal.clear(); + cal.set(1930, JUNE, 21-2, 12, 00, 00); + cal.roll(AM_PM, +3); + if (!cal.checkDateTime(1930, JUNE, 21-2, 12-12, 00, 00, 000) + || !cal.checkFieldValue(AM_PM, AM)) { + error("1930/6/10: roll(AM_PM, +3)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + // Test the HOUR_OF_DAY field + // add() + cal.clear(); + cal.set(1930, JUNE, 20, 23, 00, 00); + cal.add(HOUR_OF_DAY, +1); + if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) { + error("1930/6/20 23:00:00: add(HOUR_OF_DAY, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + // roll() (should NOT change the date) + cal.clear(); + cal.set(1930, JUNE, 20, 23, 00, 00); + cal.roll(HOUR_OF_DAY, +1); + if (!cal.checkDateTime(1930, JUNE, 20, 00, 00, 00, 000)) { + error("1930/6/20 23:00:00: roll(HOUR_OF_DAY, +1)\n" + + cal.getMessage()+" "+cal.toDateTimeString()); + } + + checkErrors(); + } + + static void error(String s) { + System.out.println(s); + errorCount++; + } + + static void checkErrors() { + if (errorCount > 0) { + throw new RuntimeException("Failed: " + errorCount + " error(s)"); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug5078053.java b/jdk/test/java/util/Calendar/Bug5078053.java new file mode 100644 index 00000000000..c6bb25bcf82 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug5078053.java @@ -0,0 +1,100 @@ +/* + * 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 5078053 + * @summary Make sure that Calendar.complete() normalizes stamp[] to + * COMPUTED. This can be observed through add() and roll(). + */ + +import java.util.TimeZone; +import static java.util.Calendar.*; + +public class Bug5078053 { + static int errorCount = 0; + + public static void main(String[] args) { + TimeZone defaultTz = TimeZone.getDefault(); + + try { + TimeZone tz = TimeZone.getTimeZone("Australia/Adelaide"); + TimeZone.setDefault(tz); + Koyomi cal = new Koyomi(); + cal.setFirstDayOfWeek(2); + cal.setMinimalDaysInFirstWeek(4); + + // test roll() + cal.clear(); + // 2002-01-01T00:00:00 in Australia/Adelaide + cal.setTimeInMillis(1009805400000L); + System.out.println(cal.getTime()); + // The following set calls shouldn't affect roll() and add() + cal.set(DAY_OF_WEEK, cal.get(DAY_OF_WEEK)); + cal.set(WEEK_OF_YEAR, cal.get(WEEK_OF_YEAR)); + cal.getTime(); + cal.roll(MONTH, +1); + System.out.println("roll: " + cal.getTime()); + if (!cal.checkDate(2002, FEBRUARY, 1)) { + error("roll(MONTH, +1): " + cal.getMessage()); + } + cal.roll(MONTH, -1); + if (!cal.checkDate(2002, JANUARY, 1)) { + error("roll(MONTH, -1): " + cal.getMessage()); + } + + // test add() + cal.clear(); + // 2002-01-01T00:00:00+0930 in Australia/Adelaide + cal.setTimeInMillis(1009805400000L); + cal.set(DAY_OF_WEEK, cal.get(DAY_OF_WEEK)); + cal.set(WEEK_OF_YEAR, cal.get(WEEK_OF_YEAR)); + cal.getTime(); + cal.add(MONTH, +1); + System.out.println(" add: " + cal.getTime()); + if (!cal.checkDate(2002, FEBRUARY, 1)) { + error("add(MONTH, +1): " + cal.getMessage()); + } + cal.add(MONTH, -1); + if (!cal.checkDate(2002, JANUARY, 1)) { + error("add(MONTH, -1): " + cal.getMessage()); + } + } + finally { + TimeZone.setDefault(defaultTz); + } + + checkErrors(); + } + + static void error(String s) { + System.out.println(s); + errorCount++; + } + + static void checkErrors() { + if (errorCount > 0) { + throw new RuntimeException("Failed: " + errorCount + " error(s)"); + } + } +} diff --git a/jdk/test/java/util/Calendar/Bug6178071.java b/jdk/test/java/util/Calendar/Bug6178071.java new file mode 100644 index 00000000000..8d361c76bcb --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug6178071.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6178071 6440854 + * @summary Make sure that setting HOUR right after a construction works + * as expected. + */ + +import java.util.GregorianCalendar; +import static java.util.Calendar.*; + +public class Bug6178071 { + public static void main(String[] args) { + GregorianCalendar cal = new GregorianCalendar(2004, JANUARY, 1); + cal.set(HOUR, 1); + if (cal.get(HOUR_OF_DAY) != 1 || + cal.get(HOUR) != 1 || cal.get(AM_PM) != AM) { + throw new RuntimeException("Unexpected hour of day: " + cal.getTime()); + } + + // Test case for 6440854 + GregorianCalendar gc = new GregorianCalendar(2006,5,16); + gc.setLenient(false); + gc.set(HOUR_OF_DAY, 10); + // The following line shouldn't throw an IllegalArgumentException. + gc.get(YEAR); + } +} diff --git a/jdk/test/java/util/Calendar/Bug6234795.java b/jdk/test/java/util/Calendar/Bug6234795.java new file mode 100644 index 00000000000..d1b2bc55c01 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug6234795.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6234795 + * @summary Rolling of HOUR or HOUR_OF_SET must set the other hour field. + */ + +import java.util.GregorianCalendar; +import static java.util.Calendar.AM; +import static java.util.Calendar.AM_PM; +import static java.util.Calendar.HOUR; +import static java.util.Calendar.HOUR_OF_DAY; +import static java.util.Calendar.SEPTEMBER; +import java.util.Locale; +import java.util.TimeZone; + +public class Bug6234795 { + public static void main(String[] args) { + testRoll(HOUR); + testRoll(HOUR_OF_DAY); + } + + static void testRoll(int field) { + GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.US); + cal.clear(); + cal.set(2005, SEPTEMBER, 12); + + int otherField = (field == HOUR) ? HOUR_OF_DAY : HOUR; + int unit = (field == HOUR) ? 12 : 24; + int h; + for (h = 0; h <= 72; h++) { + int hour = cal.get(otherField); + int expected = h % 12; + if (hour != expected) { + throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY") + + "+: h=" + h + ", got " + hour + + ", expected " + expected); + } + if (field == HOUR_OF_DAY) { + int ampm = cal.get(AM_PM); + expected = (h % unit) / 12; + if (ampm != expected) { + throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY") + + "+: h=" + h + ", got " + + toString(ampm) + + ", expected " + toString(expected)); + } + } + cal.roll(field, +1); + } + for (; h >= 0; h--) { + int hour = cal.get(otherField); + int expected = h % 12; + if (hour != expected) { + throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY") + + "-: h=" + h + ", got " + hour + + ", expected " + expected); + } + if (field == HOUR_OF_DAY) { + int ampm = cal.get(AM_PM); + expected = (h % unit) / 12; + if (ampm != expected) { + throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY") + + "-: h=" + h + ", got " + toString(ampm) + + ", expected " + toString(expected)); + } + } + cal.roll(field, -1); + } + } + + static String toString(int ampm) { + return ampm == AM ? "AM" : "PM"; + } +} diff --git a/jdk/test/java/util/Calendar/Bug6448234.java b/jdk/test/java/util/Calendar/Bug6448234.java new file mode 100644 index 00000000000..16cf0fca1c4 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug6448234.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6448234 + * @summary Make sure indexing of DAY_OF_WEEK is correct in JapaneseImperialCalendar.getDisplayName. + */ + +import java.util.Calendar; +import java.util.Locale; +import static java.util.Calendar.*; + +public class Bug6448234 { + public static void main(String[] args) { + Calendar jcal = Calendar.getInstance(new Locale("ja", "JP", "JP")); + Calendar gcal = Calendar.getInstance(Locale.US); + + for (int i = SUNDAY; i <= SATURDAY; i++) { + jcal.set(DAY_OF_WEEK, i); + gcal.set(DAY_OF_WEEK, i); + + // Test LONG + String j = jcal.getDisplayName(DAY_OF_WEEK, LONG, Locale.US); + String g = gcal.getDisplayName(DAY_OF_WEEK, LONG, Locale.US); + if (!j.equals(g)) { + throw new RuntimeException("Got " + j + ", expected " + g); + } + + // Test SHORT + j = jcal.getDisplayName(DAY_OF_WEEK, SHORT, Locale.US); + g = gcal.getDisplayName(DAY_OF_WEEK, SHORT, Locale.US); + if (!j.equals(g)) { + throw new RuntimeException("Got " + j + ", expected " + g); + } + } + } +} diff --git a/jdk/test/java/util/Calendar/CalendarLimitTest.java b/jdk/test/java/util/Calendar/CalendarLimitTest.java new file mode 100644 index 00000000000..69dcbb5efcf --- /dev/null +++ b/jdk/test/java/util/Calendar/CalendarLimitTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4033662 + * @library /java/text/testlib + * @summary test for limit on Calendar + * @run main CalendarLimitTest -verbose + */ + +import java.util.*; +import java.text.*; + +/** + * This test verifies the behavior of Calendar around the very earliest limits + * which it can handle. It also verifies the behavior for large values of millis. + * + * Note: There used to be a limit, due to a bug, for early times. There is + * currently no limit. + * + * March 17, 1998: Added code to make sure big + dates are big + AD years, and + * big - dates are big + BC years. + */ +public class CalendarLimitTest extends IntlTest +{ + // This number determined empirically; this is the old limit, + // which we test for to make sure it isn't there anymore. + static final long EARLIEST_SUPPORTED_MILLIS = -210993120000000L; + + static final int EPOCH_JULIAN_DAY = 2440588; // Jaunary 1, 1970 (Gregorian) + static final int JAN_1_1_JULIAN_DAY = 1721426; // January 1, year 1 (Gregorian) + + // Useful millisecond constants + static final int ONE_SECOND = 1000; + static final int ONE_MINUTE = 60*ONE_SECOND; + static final int ONE_HOUR = 60*ONE_MINUTE; + static final int ONE_DAY = 24*ONE_HOUR; + static final int ONE_WEEK = 7*ONE_DAY; + static final long ONE_YEAR = (long)(365.2425 * ONE_DAY); + + static long ORIGIN; // This is the *approximate* point at which BC switches to AD + + public static void main(String argv[]) throws Exception { + new CalendarLimitTest().run(argv); + } + + /** + * Converts Julian day to time as milliseconds. + * @param julian the given Julian day number. + * @return time as milliseconds. + */ + private static final long julianDayToMillis(long julian) { + return (julian - EPOCH_JULIAN_DAY) * ONE_DAY; + } + + /** + * Verify that the given time is processed without problem. + * @return the adjust year, with 0 = 1 BC, -1 = 2 BC, etc. + */ + int test(long millis, Calendar cal, DateFormat fmt) + { + Exception exception = null; + String theDate = ""; + try { + Date d= new Date(millis); + cal.setTime(d); + theDate = fmt.format(d); + } + catch (IllegalArgumentException e) { + exception = e; + } + String s = "0x" + Long.toHexString(millis) + " " + theDate; + + int era=cal.get(Calendar.ERA), year=cal.get(Calendar.YEAR), + dom=cal.get(Calendar.DATE), mon=cal.get(Calendar.MONTH); + + cal.clear(); + cal.set(year, mon, dom); + cal.set(Calendar.ERA, era); + Date rt = cal.getTime(); + + boolean ok = true; + if (exception != null) { + errln("FAIL: Exception " + s); + ok = false; + } + if (((millis >= ORIGIN) && (era != GregorianCalendar.AD)) || + ((millis < ORIGIN) && (era != GregorianCalendar.BC)) || + (year < 1)) { + errln("FAIL: Bad year/era " + s); + ok = false; + } + if (dom<1 || dom>31) { + errln("FAIL: Bad DOM " + s); + ok = false; + } + if (Math.abs(millis - rt.getTime()) > ONE_DAY) { + errln("FAIL: RT fail " + s + " -> 0x" + + Long.toHexString(rt.getTime()) + " " + + fmt.format(rt)); + ok = false; + } + if (ok) logln(s); + if (era==GregorianCalendar.BC) year = 1-year; + return year; + } + + public void TestCalendarLimit() + { + ORIGIN = julianDayToMillis(JAN_1_1_JULIAN_DAY); + + Calendar cal = Calendar.getInstance(); + // You must set the time zone to GMT+0 or the edge cases like + // Long.MIN_VALUE, Long.MAX_VALUE, and right around the threshold + // won't work, since before converting to fields the calendar code + // will add the offset for the zone. + cal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca")); + + DateFormat dateFormat = DateFormat.getDateInstance(); + dateFormat.setCalendar(cal); // Make sure you do this -- same reason as above + ((SimpleDateFormat)dateFormat).applyPattern("MMM d, yyyy G"); + + // Don't expect any failure for positive longs + int lastYear=0; + boolean first=true; + for (long m = Long.MAX_VALUE; m > 0; m >>= 1) + { + int y = test(m, cal, dateFormat); + if (!first && y > lastYear) + errln("FAIL: Years should be decreasing " + lastYear + " " + y); + first = false; + lastYear = y; + } + + // Expect failures for negative millis below threshold + first = true; + for (long m = Long.MIN_VALUE; m < 0; m /= 2) // Don't use m >>= 1 + { + int y = test(m, cal, dateFormat); + if (!first && y < lastYear) + errln("FAIL: Years should be increasing " + lastYear + " " + y); + first = false; + lastYear = y; + } + + // Test right around the threshold + test(EARLIEST_SUPPORTED_MILLIS, cal, dateFormat); + test(EARLIEST_SUPPORTED_MILLIS-1, cal, dateFormat); + + // Test a date that should work + test(Long.MIN_VALUE + ONE_DAY, cal, dateFormat); + + // Try hours in the earliest day or two + // JUST FOR DEBUGGING: + if (false) { + ((SimpleDateFormat)dateFormat).applyPattern("H:mm MMM d, yyyy G"); + for (int dom=2; dom<=3; ++dom) { + for (int h=0; h<24; ++h) { + cal.clear(); + cal.set(Calendar.ERA, GregorianCalendar.BC); + cal.set(292269055, Calendar.DECEMBER, dom, h, 0); + Date d = cal.getTime(); + cal.setTime(d); + logln("" + h + ":00 Dec "+dom+", 292269055 BC -> " + + Long.toHexString(d.getTime()) + " -> " + + dateFormat.format(cal.getTime())); + } + } + // Other way + long t = 0x80000000018c5c00L; // Dec 3, 292269055 BC + while (t<0) { + cal.setTime(new Date(t)); + logln("0x" + Long.toHexString(t) + " -> " + + dateFormat.format(cal.getTime())); + t -= ONE_HOUR; + } + } + } +} + +//eof diff --git a/jdk/test/java/util/Calendar/CalendarRegression.java b/jdk/test/java/util/Calendar/CalendarRegression.java new file mode 100644 index 00000000000..baae13f14fd --- /dev/null +++ b/jdk/test/java/util/Calendar/CalendarRegression.java @@ -0,0 +1,2496 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4031502 4035301 4040996 4051765 4059654 4061476 4070502 4071197 4071385 + * 4073929 4083167 4086724 4092362 4095407 4096231 4096539 4100311 4103271 + * 4106136 4108764 4114578 4118384 4125881 4125892 4136399 4141665 4142933 + * 4145158 4145983 4147269 4149677 4162587 4165343 4166109 4167060 4173516 + * 4174361 4177484 4197699 4209071 4288792 4328747 4413980 4546637 4623997 + * 4685354 4655637 4683492 4080631 4080631 4167995 4340146 4639407 + * 4652815 4652830 4740554 4936355 4738710 4633646 4846659 4822110 4960642 + * 4973919 4980088 4965624 5013094 5006864 8152077 + * @library /java/text/testlib + */ + +import java.lang.reflect.*; +import java.io.*; +import java.util.*; +import java.text.*; + +public class CalendarRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new CalendarRegression().run(args); + } + + /* + Synopsis: java.sql.Timestamp constructor works wrong on Windows 95 + + ==== Here is the test ==== + public static void main (String args[]) { + java.sql.Timestamp t= new java.sql.Timestamp(0,15,5,5,8,13,123456700); + logln("expected=1901-04-05 05:08:13.1234567"); + logln(" result="+t); + } + + ==== Here is the output of the test on Solaris or NT ==== + expected=1901-04-05 05:08:13.1234567 + result=1901-04-05 05:08:13.1234567 + + ==== Here is the output of the test on Windows95 ==== + expected=1901-04-05 05:08:13.1234567 + result=1901-04-05 06:08:13.1234567 + */ + + public void Test4031502() { + // This bug actually occurs on Windows NT as well, and doesn't + // require the host zone to be set; it can be set in Java. + String[] ids = TimeZone.getAvailableIDs(); + boolean bad = false; + for (int i=0; i + * @param date The date to start from + */ + public static Date getAssociatedDate(Date d) { + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(d); + //cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH + // cal.getTime(); // <--- REMOVE THIS TO SEE BUG + while (true) { + int wd = cal.get(Calendar.DAY_OF_WEEK); + if (wd == Calendar.SATURDAY || wd == Calendar.SUNDAY) { + cal.add(Calendar.DATE, 1); + // cal.getTime(); + } + else + break; + } + return cal.getTime(); + } + + public void Test4071197() { + dowTest(false); + dowTest(true); + } + + void dowTest(boolean lenient) { + GregorianCalendar cal = new GregorianCalendar(); + cal.set(1997, Calendar.AUGUST, 12); // Wednesday + // cal.getTime(); // Force update + cal.setLenient(lenient); + cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996 + int dow = cal.get(Calendar.DAY_OF_WEEK); + int min = cal.getMinimum(Calendar.DAY_OF_WEEK); + int max = cal.getMaximum(Calendar.DAY_OF_WEEK); + logln(cal.getTime().toString()); + if (min != Calendar.SUNDAY || max != Calendar.SATURDAY) + errln("FAIL: Min/max bad"); + if (dow < min || dow > max) + errln("FAIL: Day of week " + dow + " out of range"); + if (dow != Calendar.SUNDAY) + errln("FAIL: Day of week should be SUNDAY Got " + dow); + } + + public void Test4071385() { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(98, Calendar.JUNE, 24)); + cal.set(Calendar.MONTH, Calendar.NOVEMBER); // change a field + logln(cal.getTime().toString()); + if (!cal.getTime().equals(new Date(98, Calendar.NOVEMBER, 24))) + errln("Fail"); + } + + public void Test4073929() { + GregorianCalendar foo1 = new GregorianCalendar(1997, 8, 27); + foo1.add(Calendar.DAY_OF_MONTH, +1); + int testyear = foo1.get(Calendar.YEAR); + int testmonth = foo1.get(Calendar.MONTH); + int testday = foo1.get(Calendar.DAY_OF_MONTH); + if (testyear != 1997 || + testmonth != 8 || + testday != 28) + errln("Fail: Calendar not initialized"); + } + + public void Test4083167() { + TimeZone saveZone = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + Date firstDate = new Date(); + Calendar cal = new GregorianCalendar(); + cal.setTime(firstDate); + long firstMillisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L + + cal.get(Calendar.MINUTE) * 60000L + + cal.get(Calendar.SECOND) * 1000L + + cal.get(Calendar.MILLISECOND); + + logln("Current time: " + firstDate.toString()); + + for (int validity=0; validity<30; validity++) { + Date lastDate = new Date(firstDate.getTime() + + (long)validity*1000*24*60*60); + cal.setTime(lastDate); + long millisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L + + cal.get(Calendar.MINUTE) * 60000L + + cal.get(Calendar.SECOND) * 1000L + + cal.get(Calendar.MILLISECOND); + if (firstMillisInDay != millisInDay) { + errln("Day has shifted " + lastDate); + } + } + } + finally { + TimeZone.setDefault(saveZone); + } + } + + public void Test4086724() { + SimpleDateFormat date; + TimeZone saveZone = TimeZone.getDefault(); + Locale saveLocale = Locale.getDefault(); + + String summerTime = "British Summer Time"; + String standardTime = "Greenwich Mean Time"; + try { + Locale.setDefault(Locale.UK); + TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); + date = new SimpleDateFormat("zzzz"); + + Calendar cal=Calendar.getInstance(); + cal.set(1997,Calendar.SEPTEMBER,30); + Date now=cal.getTime(); + String formattedDate = date.format(now); + if (!formattedDate.equals(summerTime)) { + errln("Wrong display name \"" + formattedDate + + "\" for <" + now + ">"); + } + int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + if (weekOfYear != 40) { + errln("Wrong week-of-year " + weekOfYear + + " for <" + now + ">"); + } + + cal.set(1996,Calendar.DECEMBER,31); + now=cal.getTime(); + formattedDate = date.format(now); + if (!formattedDate.equals(standardTime)) { + errln("Wrong display name \"" + formattedDate + + "\" for <" + now + ">"); + } + weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + if (weekOfYear != 1) { + errln("Wrong week-of-year " + weekOfYear + + " for <" + now + ">"); + } + + cal.set(1997,Calendar.JANUARY,1); + now=cal.getTime(); + formattedDate = date.format(now); + if (!formattedDate.equals(standardTime)) { + errln("Wrong display name \"" + formattedDate + + "\" for <" + now + ">"); + } + weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + if (weekOfYear != 1) { + errln("Wrong week-of-year " + weekOfYear + + " for <" + now + ">"); + } + + cal.set(1997,Calendar.JANUARY,8); + now=cal.getTime(); + formattedDate = date.format(now); + if (!formattedDate.equals(standardTime)) { + errln("Wrong display name \"" + formattedDate + + "\" for <" + now + ">"); + } + weekOfYear = cal.get(Calendar.WEEK_OF_YEAR); + if (weekOfYear != 2) { + errln("Wrong week-of-year " + weekOfYear + + " for <" + now + ">"); + } + + } + finally { + Locale.setDefault(saveLocale); + TimeZone.setDefault(saveZone); + } + } + + public void Test4092362() { + GregorianCalendar cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40); + /*cal1.set( Calendar.YEAR, 1997 ); + cal1.set( Calendar.MONTH, 10 ); + cal1.set( Calendar.DATE, 11 ); + cal1.set( Calendar.HOUR, 10 ); + cal1.set( Calendar.MINUTE, 20 ); + cal1.set( Calendar.SECOND, 40 ); */ + + logln( " Cal1 = " + cal1.getTime().getTime() ); + logln( " Cal1 time in ms = " + cal1.get(Calendar.MILLISECOND) ); + for( int k = 0; k < 100 ; k++ ); + + GregorianCalendar cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40); + /*cal2.set( Calendar.YEAR, 1997 ); + cal2.set( Calendar.MONTH, 10 ); + cal2.set( Calendar.DATE, 11 ); + cal2.set( Calendar.HOUR, 10 ); + cal2.set( Calendar.MINUTE, 20 ); + cal2.set( Calendar.SECOND, 40 ); */ + + logln( " Cal2 = " + cal2.getTime().getTime() ); + logln( " Cal2 time in ms = " + cal2.get(Calendar.MILLISECOND) ); + if( !cal1.equals( cal2 ) ) + errln("Fail: Milliseconds randomized"); + } + + public void Test4095407() { + GregorianCalendar a = new GregorianCalendar(1997,Calendar.NOVEMBER, 13); + int dow = a.get(Calendar.DAY_OF_WEEK); + if (dow != Calendar.THURSDAY) + errln("Fail: Want THURSDAY Got " + dow); + } + + public void Test4096231() { + TimeZone GMT = TimeZone.getTimeZone("GMT"); + TimeZone PST = TimeZone.getTimeZone("PST"); + int sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997; + + Calendar cal1 = new GregorianCalendar(PST); + cal1.setTime(new Date(880698639000L)); + int p; + logln("PST 1 is: " + (p=cal1.get(cal1.HOUR_OF_DAY))); + cal1.setTimeZone(GMT); + // Issue 1: Changing the timezone doesn't change the + // represented time. + int h1,h2; + logln("GMT 1 is: " + (h1=cal1.get(cal1.HOUR_OF_DAY))); + cal1.setTime(new Date(880698639000L)); + logln("GMT 2 is: " + (h2=cal1.get(cal1.HOUR_OF_DAY))); + // Note: This test had a bug in it. It wanted h1!=h2, when + // what was meant was h1!=p. Fixed this concurrent with fix + // to 4177484. + if (p == h1 || h1 != h2) + errln("Fail: Hour same in different zones"); + + Calendar cal2 = new GregorianCalendar(GMT); + Calendar cal3 = new GregorianCalendar(PST); + cal2.set(Calendar.MILLISECOND, 0); + cal3.set(Calendar.MILLISECOND, 0); + + cal2.set(cal1.get(cal1.YEAR), + cal1.get(cal1.MONTH), + cal1.get(cal1.DAY_OF_MONTH), + cal1.get(cal1.HOUR_OF_DAY), + cal1.get(cal1.MINUTE), + cal1.get(cal1.SECOND)); + + long t1,t2,t3,t4; + logln("RGMT 1 is: " + (t1=cal2.getTime().getTime())); + cal3.set(year, month, day, hr, min, sec); + logln("RPST 1 is: " + (t2=cal3.getTime().getTime())); + cal3.setTimeZone(GMT); + logln("RGMT 2 is: " + (t3=cal3.getTime().getTime())); + cal3.set(cal1.get(cal1.YEAR), + cal1.get(cal1.MONTH), + cal1.get(cal1.DAY_OF_MONTH), + cal1.get(cal1.HOUR_OF_DAY), + cal1.get(cal1.MINUTE), + cal1.get(cal1.SECOND)); + // Issue 2: Calendar continues to use the timezone in its + // constructor for set() conversions, regardless + // of calls to setTimeZone() + logln("RGMT 3 is: " + (t4=cal3.getTime().getTime())); + if (t1 == t2 || + t1 != t4 || + t2 != t3) + errln("Fail: Calendar zone behavior faulty"); + } + + public void Test4096539() { + int[] y = {31,28,31,30,31,30,31,31,30,31,30,31}; + + for (int x=0;x<12;x++) { + GregorianCalendar gc = new + GregorianCalendar(1997,x,y[x]); + int m1,m2; + log((m1=gc.get(Calendar.MONTH)+1)+"/"+ + gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)+ + " + 1mo = "); + + gc.add(Calendar.MONTH, 1); + logln((m2=gc.get(Calendar.MONTH)+1)+"/"+ + gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR) + ); + int m = (m1 % 12) + 1; + if (m2 != m) + errln("Fail: Want " + m + " Got " + m2); + } + + } + + public void Test4100311() { + GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance(); + cal.set(Calendar.YEAR, 1997); + cal.set(Calendar.DAY_OF_YEAR, 1); + Date d = cal.getTime(); // Should be Jan 1 + logln(d.toString()); + if (cal.get(Calendar.DAY_OF_YEAR) != 1) + errln("Fail: DAY_OF_YEAR not set"); + } + + public void Test4103271() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + SimpleDateFormat sdf = new SimpleDateFormat(); + int numYears=40, startYear=1997, numDays=15; + String output, testDesc; + GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance(); + testCal.clear(); + sdf.setCalendar(testCal); + sdf.applyPattern("d MMM yyyy"); + boolean fail = false; + for (int firstDay=1; firstDay<=2; firstDay++) { + for (int minDays=1; minDays<=7; minDays++) { + testCal.setMinimalDaysInFirstWeek(minDays); + testCal.setFirstDayOfWeek(firstDay); + testDesc = ("Test" + String.valueOf(firstDay) + String.valueOf(minDays)); + logln(testDesc + " => 1st day of week=" + + String.valueOf(firstDay) + + ", minimum days in first week=" + + String.valueOf(minDays)); + for (int j=startYear; j<=startYear+numYears; j++) { + testCal.set(j,11,25); + for(int i=0; i 53) { + Date d = testCal.getTime(); + calWOY = String.valueOf(actWOY); + output = testDesc + " - " + sdf.format(d) + "\t"; + output = output + "\t" + calWOY; + logln(output); + fail = true; + } + } + } + } + } + + int[] DATA = { + 3, 52, 52, 52, 52, 52, 52, 52, + 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, + 4, 52, 52, 52, 52, 52, 52, 52, + 53, 53, 53, 53, 53, 53, 53, + 1, 1, 1, 1, 1, 1, 1, + }; + testCal.setFirstDayOfWeek(Calendar.SUNDAY); + for (int j=0; j " + testCal.getTime()); + if (!after.equals(testCal.getTime())) { + logln("\tFAIL\n\t\texp: " + after); + fail = true; + } else + logln(" OK"); + + testCal.setTime(after); + if (ADDROLL[i] == ADD) + testCal.add(Calendar.WEEK_OF_YEAR, -amount); + else + testCal.roll(Calendar.WEEK_OF_YEAR, -amount); + log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") + + (-amount) + ") " + after + + "\n\t\t => " + testCal.getTime()); + if (!before.equals(testCal.getTime())) { + logln("\tFAIL\n\t\texp: " + before); + fail = true; + } + else logln("\tOK"); + } + + if (fail) { + errln("Fail: Week of year misbehaving"); + } + } + + public void Test4106136() { + Locale saveLocale = Locale.getDefault(); + try { + Locale[] locales = { Locale.CHINESE, Locale.CHINA }; + for (int i=0; i maxYear) { + errln("Failed for "+DATES[i].getTime()+" ms: year=" + + year + ", maxYear=" + maxYear); + } + } + } + + /** + * This is a bug in the validation code of GregorianCalendar. As reported, + * the bug seems worse than it really is, due to a bug in the way the bug + * report test was written. In reality the bug is restricted to the DAY_OF_YEAR + * field. - liu 6/29/98 + */ + public void Test4147269() { + final String[] fieldName = { + "ERA", + "YEAR", + "MONTH", + "WEEK_OF_YEAR", + "WEEK_OF_MONTH", + "DAY_OF_MONTH", + "DAY_OF_YEAR", + "DAY_OF_WEEK", + "DAY_OF_WEEK_IN_MONTH", + "AM_PM", + "HOUR", + "HOUR_OF_DAY", + "MINUTE", + "SECOND", + "MILLISECOND", + "ZONE_OFFSET", + "DST_OFFSET" + }; + GregorianCalendar calendar = new GregorianCalendar(); + calendar.setLenient(false); + Date date = new Date(1996-1900, Calendar.JANUARY, 3); // Arbitrary date + for (int field = 0; field < Calendar.FIELD_COUNT; field++) { + calendar.setTime(date); + // Note: In the bug report, getActualMaximum() was called instead + // of getMaximum() -- this was an error. The validation code doesn't + // use getActualMaximum(), since that's too costly. + int max = calendar.getMaximum(field); + int value = max+1; + calendar.set(field, value); + try { + calendar.getTime(); // Force time computation + // We expect an exception to be thrown. If we fall through + // to the next line, then we have a bug. + errln("Test failed with field " + fieldName[field] + + ", date before: " + date + + ", date after: " + calendar.getTime() + + ", value: " + value + " (max = " + max +")"); + } catch (IllegalArgumentException e) {} + } + } + + /** + * Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE) + * doesn't behave as a pure Julian calendar. + * CANNOT REPRODUCE THIS BUG + */ + public void Test4149677() { + TimeZone[] zones = { TimeZone.getTimeZone("GMT"), + TimeZone.getTimeZone("PST"), + TimeZone.getTimeZone("EAT") }; + for (int i=0; i0) logln("---"); + + cal.clear(); + cal.set(1998, Calendar.APRIL, 5, i, 0); + d = cal.getTime(); + String s0 = d.toString(); + logln("0 " + i + ": " + s0); + + cal.clear(); + cal.set(1998, Calendar.APRIL, 4, i+24, 0); + d = cal.getTime(); + String sPlus = d.toString(); + logln("+ " + i + ": " + sPlus); + + cal.clear(); + cal.set(1998, Calendar.APRIL, 6, i-24, 0); + d = cal.getTime(); + String sMinus = d.toString(); + logln("- " + i + ": " + sMinus); + + if (!s0.equals(sPlus) || !s0.equals(sMinus)) { + errln("Fail: All three lines must match"); + } + } + } + finally { + TimeZone.setDefault(savedTz); + } + } + + /** + * Adding 12 months behaves differently from adding 1 year + */ + public void Test4165343() { + GregorianCalendar calendar = new GregorianCalendar(1996, Calendar.FEBRUARY, 29); + Date start = calendar.getTime(); + logln("init date: " + start); + calendar.add(Calendar.MONTH, 12); + Date date1 = calendar.getTime(); + logln("after adding 12 months: " + date1); + calendar.setTime(start); + calendar.add(Calendar.YEAR, 1); + Date date2 = calendar.getTime(); + logln("after adding one year : " + date2); + if (date1.equals(date2)) { + logln("Test passed"); + } else { + errln("Test failed"); + } + } + + /** + * GregorianCalendar.getActualMaximum() does not account for first day of week. + */ + public void Test4166109() { + /* Test month: + * + * March 1998 + * Su Mo Tu We Th Fr Sa + * 1 2 3 4 5 6 7 + * 8 9 10 11 12 13 14 + * 15 16 17 18 19 20 21 + * 22 23 24 25 26 27 28 + * 29 30 31 + */ + boolean passed = true; + int field = Calendar.WEEK_OF_MONTH; + + GregorianCalendar calendar = new GregorianCalendar(Locale.US); + calendar.set(1998, Calendar.MARCH, 1); + calendar.setMinimalDaysInFirstWeek(1); + logln("Date: " + calendar.getTime()); + + int firstInMonth = calendar.get(Calendar.DAY_OF_MONTH); + + for (int firstInWeek = Calendar.SUNDAY; firstInWeek <= Calendar.SATURDAY; firstInWeek++) { + calendar.setFirstDayOfWeek(firstInWeek); + int returned = calendar.getActualMaximum(field); + int expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7; + + logln("First day of week = " + firstInWeek + + " getActualMaximum(WEEK_OF_MONTH) = " + returned + + " expected = " + expected + + ((returned == expected) ? " ok" : " FAIL")); + + if (returned != expected) { + passed = false; + } + } + if (!passed) { + errln("Test failed"); + } + } + + /** + * Calendar.getActualMaximum(YEAR) works wrong. + * + * Note: Before 1.5, this test case assumed that + * setGregorianChange didn't change object's date. But it was + * changed. See 4928615. + */ + public void Test4167060() { + int field = Calendar.YEAR; + DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy G", + Locale.US); + + int[][] dates = { + // year, month, day of month + { 100, Calendar.NOVEMBER, 1 }, + { -99 /*100BC*/, Calendar.JANUARY, 1 }, + { 1996, Calendar.FEBRUARY, 29 }}; + + String[] id = { "Hybrid", "Gregorian", "Julian" }; + + for (int k=0; k<3; ++k) { + logln("--- " + id[k] + " ---"); + + for (int j = 0; j < dates.length; ++j) { + GregorianCalendar calendar = new GregorianCalendar(); + if (k == 1) { + calendar.setGregorianChange(new Date(Long.MIN_VALUE)); + } else if (k == 2) { + calendar.setGregorianChange(new Date(Long.MAX_VALUE)); + } + calendar.set(dates[j][0], dates[j][1], dates[j][2]); + format.setCalendar((Calendar)calendar.clone()); + + Date dateBefore = calendar.getTime(); + + int maxYear = calendar.getActualMaximum(field); + logln("maxYear: " + maxYear + " for " + format.format(calendar.getTime())); + logln("date before: " + format.format(dateBefore)); + + int years[] = {2000, maxYear-1, maxYear, maxYear+1}; + + for (int i = 0; i < years.length; i++) { + boolean valid = years[i] <= maxYear; + calendar.set(field, years[i]); + Date dateAfter = calendar.getTime(); + int newYear = calendar.get(field); + calendar.setTime(dateBefore); // restore calendar for next use + + logln(" Year " + years[i] + (valid? " ok " : " bad") + + " => " + format.format(dateAfter)); + if (valid && newYear != years[i]) { + errln(" FAIL: " + newYear + " should be valid; date, month and time shouldn't change"); + } else if (!valid && newYear == years[i]) { + errln(" FAIL: " + newYear + " should be invalid"); + } + } + } + } + } + + /** + * Calendar.roll broken + * This bug relies on the TimeZone bug 4173604 to also be fixed. + */ + public void Test4173516() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + int fieldsList[][] = { + { 1997, Calendar.FEBRUARY, 1, 10, 45, 15, 900 }, + { 1999, Calendar.DECEMBER, 22, 23, 59, 59, 999 }, + // test case for 4960642 with default cutover + { 1582, Calendar.OCTOBER, 4, 23, 59, 59, 999 }, + }; + String[] fieldNames = { + "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", + "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", + "AM_PM", "HOUR", "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", + "ZONE_OFFSET", "DST_OFFSET" + }; + + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + int limit = 40; + + try { + GregorianCalendar cal = new GregorianCalendar(); + + cal.setTime(new Date(0)); + cal.roll(Calendar.HOUR, 0x7F000000); + cal.roll(Calendar.HOUR, -0x7F000000); + if (cal.getTime().getTime() != 0) { + errln("Hour rolling broken. expected 0, got "+cal.getTime().getTime()); + } + + for (int op=0; op<2; ++op) { + logln("Testing GregorianCalendar " + (op==0 ? "add" : "roll")); + + for (int field=0; field < Calendar.FIELD_COUNT; ++field) { + if (field != Calendar.ZONE_OFFSET && + field != Calendar.DST_OFFSET) { + for (int j=0; j " + + cal.get(Calendar.YEAR) + + "/" + (cal.get(Calendar.MONTH) + 1) + + "/" + cal.get(Calendar.DATE) + + " " + cal.get(Calendar.HOUR_OF_DAY) + + ":" + cal.get(Calendar.MINUTE) + + ":" + cal.get(Calendar.SECOND) + + "." + cal.get(Calendar.MILLISECOND) + + " d=" + delta); + } + } + } + } + } + } + } + finally { + Locale.setDefault(savedLocale); + } + } + + public void Test4174361() { + GregorianCalendar calendar = new GregorianCalendar(1996, 1, 29); + + calendar.add(Calendar.MONTH, 10); + Date date1 = calendar.getTime(); + int d1 = calendar.get(Calendar.DAY_OF_MONTH); + + calendar = new GregorianCalendar(1996, 1, 29); + calendar.add(Calendar.MONTH, 11); + Date date2 = calendar.getTime(); + int d2 = calendar.get(Calendar.DAY_OF_MONTH); + + if (d1 != d2) { + errln("adding months to Feb 29 broken"); + } + } + + /** + * Calendar does not update field values when setTimeZone is called. + */ + public void Test4177484() { + TimeZone PST = TimeZone.getTimeZone("PST"); + TimeZone EST = TimeZone.getTimeZone("EST"); + + Calendar cal = Calendar.getInstance(PST, Locale.US); + cal.clear(); + cal.set(1999, 3, 21, 15, 5, 0); // Arbitrary + int h1 = cal.get(Calendar.HOUR_OF_DAY); + cal.setTimeZone(EST); + int h2 = cal.get(Calendar.HOUR_OF_DAY); + if (h1 == h2) { + errln("FAIL: Fields not updated after setTimeZone"); + } + + // getTime() must NOT change when time zone is changed. + // getTime() returns zone-independent time in ms. + cal.clear(); + cal.setTimeZone(PST); + cal.set(Calendar.HOUR_OF_DAY, 10); + Date pst10 = cal.getTime(); + cal.setTimeZone(EST); + Date est10 = cal.getTime(); + if (!pst10.equals(est10)) { + errln("FAIL: setTimeZone changed time"); + } + } + + /** + * Week of year is wrong at the start and end of the year. + */ + public void Test4197699() { + GregorianCalendar cal = new GregorianCalendar(); + cal.setFirstDayOfWeek(Calendar.MONDAY); + cal.setMinimalDaysInFirstWeek(4); + DateFormat fmt = new SimpleDateFormat("E dd MMM yyyy 'DOY='D 'WOY='w"); + fmt.setCalendar(cal); + + int[] DATA = { + 2000, Calendar.JANUARY, 1, 52, + 2001, Calendar.DECEMBER, 31, 1, + }; + + for (int i=0; i " + actual + + ", want " + DATA[i+1]); + } + } + } + + public void Test4288792() throws Exception + { + TimeZone savedTZ = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + GregorianCalendar cal = new GregorianCalendar(); + try { + for (int i = 1900; i < 2100; i++) { + for (int j1 = 1; j1 <= 7; j1++) { + // Loop for MinimalDaysInFirstWeek: 1..7 + for (int j = Calendar.SUNDAY; j <= Calendar.SATURDAY; j++) { + // Loop for FirstDayOfWeek: SUNDAY..SATURDAY + cal.clear(); + cal.setMinimalDaysInFirstWeek(j1); + cal.setFirstDayOfWeek(j); + cal.set(Calendar.YEAR, i); + int maxWeek = cal.getActualMaximum(Calendar.WEEK_OF_YEAR); + cal.set(Calendar.WEEK_OF_YEAR, maxWeek); + cal.set(Calendar.DAY_OF_WEEK, j); + + for (int k = 1; k < 7; k++) { + cal.add(Calendar.DATE, 1); + int WOY = cal.get(Calendar.WEEK_OF_YEAR); + if (WOY != maxWeek) { + errln(cal.getTime() + ",got=" + WOY + + ",expected=" + maxWeek + + ",min=" + j1 + ",first=" + j); + } + } + + cal.add(Calendar.DATE, 1); + int WOY = cal.get(Calendar.WEEK_OF_YEAR); + if (WOY != 1) { + errln(cal.getTime() + ",got=" + WOY + + ",expected=1,min=" + j1 + ",first" + j); + } + } + } + } + } + finally { + TimeZone.setDefault(savedTZ); + } + } + + public void Test4328747() throws Exception { + Calendar c = (Calendar)Calendar.getInstance(Locale.US); + c.clear(); + c.set(1966,0,1); // 1 jan 1966 + + // serialize + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream s = new ObjectOutputStream(out); + s.writeObject(c); + s.flush(); + + // deserialize + ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); + Calendar result = (Calendar)t.readObject(); + + // let recalculate fields with the same UTC time + result.setTime(result.getTime()); + // Bug gives 1965 11 19 + if ((result.get(c.YEAR) != 1966) || (result.get(c.MONTH) != 0) + || (result.get(c.DATE) != 1)) { + errln("deserialized Calendar returned wrong date field(s): " + + result.get(c.YEAR) + "/" + result.get(c.MONTH) + "/" + result.get(c.DATE) + + ", expected 1966/0/1"); + } + } + + /** + * Test whether Calendar can be serialized/deserialized correctly + * even if invalid/customized TimeZone is used. + */ + public void Test4413980() { + TimeZone savedTimeZone = TimeZone.getDefault(); + try { + boolean pass = true; + String[] IDs = new String[] {"Undefined", "PST", "US/Pacific", + "GMT+3:00", "GMT-01:30"}; + for (int i = 0; i < IDs.length; i++) { + TimeZone tz = TimeZone.getTimeZone(IDs[i]); + TimeZone.setDefault(tz); + + Calendar c = (Calendar)Calendar.getInstance(); + + // serialize + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream s = new ObjectOutputStream(out); + s.writeObject(c); + s.flush(); + + // deserialize + ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); + + if (!c.equals(t.readObject())) { + pass = false; + logln("Calendar instance which uses TimeZone <" + + IDs[i] + "> is incorrectly serialized/deserialized."); + } else { + logln("Calendar instance which uses TimeZone <" + + IDs[i] + "> is correctly serialized/deserialized."); + } + } + if (!pass) { + errln("Fail: Calendar serialization/equality bug"); + } + } + catch (IOException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + catch (ClassNotFoundException e) { + errln("Fail: " + e); + e.printStackTrace(); + } + finally { + TimeZone.setDefault(savedTimeZone); + } + } + + /** + * 4546637: Incorrect WEEK_OF_MONTH after changing First Day Of Week + */ + public void Test4546637() { + GregorianCalendar day = new GregorianCalendar (2001, Calendar.NOVEMBER, 04); + day.setMinimalDaysInFirstWeek(1); + int wom = day.get(Calendar.WEEK_OF_MONTH); + + day.setFirstDayOfWeek(Calendar.MONDAY); + if (day.get(Calendar.WEEK_OF_MONTH) != 1) { + errln("Fail: 2001/11/4 must be the first week of the month."); + } + } + + /** + * 4623997: GregorianCalendar returns bad WEEK_OF_YEAR + */ + public void Test4623997() { + GregorianCalendar cal = new GregorianCalendar(2000, GregorianCalendar.JANUARY, 1); + + int dow = cal.get(GregorianCalendar.DAY_OF_WEEK); + + cal.setFirstDayOfWeek(GregorianCalendar.MONDAY); + cal.setMinimalDaysInFirstWeek(4); + + if (cal.get(GregorianCalendar.WEEK_OF_YEAR) != 52) { + errln("Fail: 2000/1/1 must be the 52nd week of the year."); + } + } + + /** + * 4685354: Handling of Calendar fields setting state is broken + * + *

    Need to use SimpleDateFormat to test because a call to + * get(int) changes internal states of a Calendar. + */ + public void Test4685354() { + if (Locale.getDefault().equals(new Locale("hi", "IN"))) { + return; + } + + Calendar calendar = Calendar.getInstance(Locale.US); + DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US); + String expected = "1999/12/31"; + Date t; + String s; + + try { + calendar.setTime(df.parse(expected)); + } catch (Exception e) { + throw new RuntimeException("Unexpected parse exception", e); + } + + t = calendar.getTime(); + calendar.set(Calendar.DAY_OF_MONTH, 33); + t = calendar.getTime(); + calendar.set(Calendar.DAY_OF_MONTH, 0); + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("DAY_OF_MONTH w/o ZONE_OFFSET: expected: " + expected + ", got: " + s); + } + + // The same thing must work with ZONE_OFFSET set + try { + calendar.setTime(df.parse(expected)); + } catch (Exception e) { + throw new RuntimeException("Unexpected parse exception", e); + } + t = calendar.getTime(); + calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET)); + calendar.set(Calendar.DAY_OF_MONTH, 33); + t = calendar.getTime(); + calendar.set(Calendar.DAY_OF_MONTH, 0); + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("DAY_OF_MONTH: expected: " + expected + ", got: " + s); + } + + expected = "1999/12/24"; // 0th week of 2000 + calendar.clear(); + Date initialDate = null; + try { + initialDate = df.parse(expected); + calendar.setTime(initialDate); + } catch (Exception e) { + throw new RuntimeException("Unexpected parse exception", e); + } + t = calendar.getTime(); + calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET)); + // jump to the next year + calendar.set(Calendar.WEEK_OF_YEAR, 100); + t = calendar.getTime(); + calendar.set(Calendar.WEEK_OF_YEAR, 0); + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("WEEK_OF_YEAR: expected: " + expected + ", got: " + s); + } + // change the state back + calendar.clear(); + calendar.setTime(initialDate); + calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET)); + // jump to next month + calendar.set(Calendar.WEEK_OF_MONTH, 7); + t = calendar.getTime(); + calendar.set(Calendar.WEEK_OF_MONTH, 0); + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("WEEK_OF_MONTH: expected: " + expected + ", got: " + s); + } + + // Make sure the time fields work correctly. + calendar.clear(); + df = new SimpleDateFormat("HH:mm:ss"); + TimeZone tz = TimeZone.getTimeZone("GMT"); + df.setTimeZone(tz); + calendar.setTimeZone(tz); + expected = "22:59:59"; + try { + calendar.setTime(df.parse(expected)); + } catch (Exception e) { + throw new RuntimeException("Unexpected parse exception", e); + } + t = calendar.getTime(); + // time should be 22:59:59. + calendar.set(Calendar.MINUTE, 61); + // time should be 23:01:59. + t = calendar.getTime(); + calendar.set(Calendar.MINUTE, -1); + // time should be back to 22:59:59. + s = df.format(calendar.getTime()); + if (!expected.equals(s)) { + errln("MINUTE: expected: " + expected + ", got: " + s); + } + } + + /** + * 4655637: Calendar.set() for DAY_OF_WEEK does not return the right value + * + *

    Need to use SimpleDateFormat to test because a call to + * get(int) changes internal states of a Calendar. + */ + public void Test4655637() { + // Skip this test case if it's Thai locale + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(1029814211523L)); + cal.set(Calendar.YEAR, 2001); + Date t = cal.getTime(); + cal.set(Calendar.MONTH, Calendar.JANUARY); + t = cal.getTime(); + + cal.set(Calendar.DAY_OF_MONTH, 8); + t = cal.getTime(); + + cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US); + String expected = "2001/01/08"; + String s = df.format(cal.getTime()); + if (!expected.equals(s)) { + errln("expected: " + expected + ", got: " + s); + } + } + + /** + * 4683492: Invalid value for MONTH in GregorianCalendar causes exception in getTime(). + * + *

    Need to use SimpleDateFormat to test because a call to + * get(int) changes internal states of a Calendar. + * + *

    This test case throws ArrayIndexOutOfBoundsException without the fix. + */ + public void Test4683492() { + Calendar cal = new GregorianCalendar(2002, 3, 29, 10, 0, 0); + cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY); + cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1); + cal.set(Calendar.MONTH, 12); + DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US); + String expected = "2003/01/31"; + String s = df.format(cal.getTime()); + if (!expected.equals(s)) { + errln("expected: " + expected + ", got: " + s); + } + } + + /** + * 4080631: Calendar.hashCode is amazingly bad + */ + public void Test4080631() { + Calendar cal = Calendar.getInstance(); + int h1 = cal.hashCode(); + cal.add(cal.SECOND, +1); + int h2 = cal.hashCode(); + Calendar cal2 = (Calendar) cal.clone(); + cal.add(cal.MILLISECOND, +1); + int h3 = cal.hashCode(); + logln("hash code: h1="+h1+", h2="+h2+", h3="+h3); + if (h1 == h2 || h1 == h3 || h2 == h3) { + errln("hash code is poor: hashCode="+h1); + } + h2 = cal2.hashCode(); + cal.add(cal.MILLISECOND, -1); + int h4 = cal.hashCode(); + logln("hash code: h2="+h2+", h4="+h4); + if (cal.equals(cal2) && h2 != h4) { + errln("broken hash code: h2="+h2+", h4="+h4); + } + int x = cal.getFirstDayOfWeek() + 3; + if (x > cal.SATURDAY) { + x -= 7; + } + cal.setFirstDayOfWeek(x); + int h5 = cal.hashCode(); + logln("hash code: h4="+h4+", h5="+h5); + if (h4 == h5) { + errln("has code is poor with first day of week param: hashCode="+h4); + } + } + + /** + * 4125161: RFE: GregorianCalendar needs more era names (BCE and CE) + */ + /* + public void Test4125161() throws Exception { + Class gc = GregorianCalendar.class; + Field f; + int mod; + f = gc.getDeclaredField("BCE"); + mod = f.getModifiers(); + if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) { + errln("BCE: wrong modifiers: " + mod); + } + f = gc.getDeclaredField("CE"); + mod = f.getModifiers(); + if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) { + errln("CE: wrong modifiers: " + mod); + } + if (GregorianCalendar.BCE != GregorianCalendar.BC + || GregorianCalendar.CE != GregorianCalendar.AD) { + errln("Wrong BCE and/or CE values"); + } + } + */ + + /** + * 4167995: GregorianCalendar.setGregorianChange() not to spec + */ + public void Test4167995() { + Koyomi gc = new Koyomi(TimeZone.getTimeZone("GMT")); + logln("Hybrid: min date"); + gc.setTime(new Date(Long.MIN_VALUE)); + if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY) + || !gc.checkFieldValue(gc.ERA, gc.BC)) { + errln(gc.getMessage()); + } + logln("Hybrid: max date"); + gc.setTime(new Date(Long.MAX_VALUE)); + if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY) + || !gc.checkFieldValue(gc.ERA, gc.AD)) { + errln(gc.getMessage()); + } + + gc.setGregorianChange(new Date(Long.MIN_VALUE)); + logln("Gregorian: min date"); + gc.setTime(new Date(Long.MIN_VALUE)); + if (!gc.checkDate(292275056, gc.MAY, 16, gc.SUNDAY) + || !gc.checkFieldValue(gc.ERA, gc.BC)) { + errln(gc.getMessage()); + } + logln("Gregorian: max date"); + gc.setTime(new Date(Long.MAX_VALUE)); + if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY) + || !gc.checkFieldValue(gc.ERA, gc.AD)) { + errln(gc.getMessage()); + } + + gc.setGregorianChange(new Date(Long.MAX_VALUE)); + logln("Julian: min date"); + gc.setTime(new Date(Long.MIN_VALUE)); + if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY) + || !gc.checkFieldValue(gc.ERA, gc.BC)) { + errln(gc.getMessage()); + } + logln("Julian: max date"); + gc.setTime(new Date(Long.MAX_VALUE)); + if (!gc.checkDate(292272993, gc.JANUARY, 4, gc.SUNDAY) + || !gc.checkFieldValue(gc.ERA, gc.AD)) { + errln(gc.getMessage()); + } + } + + /** + * 4340146: Calendar.equals modifies state + */ + public void Test4340146() { + Koyomi cal = new Koyomi(); + cal.clear(); + cal.set(2003, cal.OCTOBER, 32); + cal.equals(new Koyomi()); + if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) { + errln(cal.getMessage()); + } + new Koyomi().equals(cal); + if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) { + errln(cal.getMessage()); + } + } + + /** + * 4639407: GregorianCalendar doesn't work in non-lenient due to timezone bounds checking + */ + public void Test4639407() { + // The following operations in non-lenient mode shouldn't + // throw IllegalArgumentException. + Koyomi cal = new Koyomi(TimeZone.getTimeZone("Pacific/Kiritimati")); + cal.setLenient(false); + cal.set(2003, cal.OCTOBER, 10); + cal.getTime(); + cal.setTimeZone(TimeZone.getTimeZone("Pacific/Tongatapu")); + cal.set(2003, cal.OCTOBER, 10); + cal.getTime(); + } + + /** + * 4652815: rolling week-of-year back hundreds of weeks changes year + */ + public void Test4652815() { + Koyomi cal = new Koyomi(Locale.US); + testRoll(cal, 2003, cal.SEPTEMBER, 29); + testRoll(cal, 2003, cal.DECEMBER, 24); + testRoll(cal, 1582, cal.DECEMBER, 19); + testRoll(cal, 1582, cal.DECEMBER, 20); + } + + private void testRoll(Koyomi cal, int year, int month, int dayOfMonth) { + cal.clear(); + cal.set(year, month, dayOfMonth); + cal.getTime(); // normalize fields + logln("Roll backwards from " + cal.toDateString()); + for (int i = 0; i < 1000; i++) { + cal.roll(cal.WEEK_OF_YEAR, -i); + if (!cal.checkFieldValue(cal.YEAR, year)) { + errln(cal.getMessage()); + } + } + logln("Roll forewards from " + cal.toDateString()); + for (int i = 0; i < 1000; i++) { + cal.roll(cal.WEEK_OF_YEAR, +i); + if (!cal.checkFieldValue(cal.YEAR, year)) { + errln(cal.getMessage()); + } + } + } + + /** + * 4652830: GregorianCalendar roll behaves unexpectedly for dates in BC era + */ + public void Test4652830() { + Koyomi cal = new Koyomi(Locale.US); + cal.clear(); + logln("BCE 9-2-28 (leap year) roll DAY_OF_MONTH++ twice"); + cal.set(cal.ERA, cal.BC); + cal.set(9, cal.FEBRUARY, 28); + if (cal.getActualMaximum(cal.DAY_OF_YEAR) != 366) { + errln(" wrong actual max of DAY_OF_YEAR: got " + + cal.getActualMaximum(cal.DAY_OF_YEAR) + " expected " + 366); + } + cal.roll(cal.DAY_OF_MONTH, +1); + if (!cal.checkFieldValue(cal.ERA, cal.BC) + || !cal.checkDate(9, cal.FEBRUARY, 29)) { + errln(cal.getMessage()); + } + cal.roll(cal.DAY_OF_MONTH, +1); + if (!cal.checkFieldValue(cal.ERA, cal.BC) + || !cal.checkDate(9, cal.FEBRUARY, 1)) { + errln(cal.getMessage()); + } + } + + /** + * 4740554: GregorianCalendar.getActualMaximum is inconsistent with normalization + */ + public void Test4740554() { + logln("1999/(Feb+12)/1 should be normalized to 2000/Feb/1 for getActualMaximum"); + Koyomi cal = new Koyomi(Locale.US); + cal.clear(); + cal.set(1999, cal.FEBRUARY + 12, 1); + if (!cal.checkActualMaximum(cal.DAY_OF_YEAR, 366)) { + errln(cal.getMessage()); + } + if (!cal.checkActualMaximum(cal.DAY_OF_MONTH, 29)) { + errln(cal.getMessage()); + } + } + + /** + * 4936355: GregorianCalendar causes overflow/underflow with time of day calculation + */ + public void Test4936355() { + Koyomi cal = new Koyomi(TimeZone.getTimeZone("GMT")); + cal.clear(); + cal.set(1970, cal.JANUARY, 1); + checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MAX_VALUE, + (long)Integer.MAX_VALUE * 60 * 60 * 1000); + + cal.clear(); + cal.set(1970, cal.JANUARY, 1); + checkTimeCalculation(cal, cal.HOUR, Integer.MAX_VALUE, + (long)Integer.MAX_VALUE * 60 * 60 * 1000); + + cal.clear(); + cal.set(1970, cal.JANUARY, 1); + checkTimeCalculation(cal, cal.MINUTE, Integer.MAX_VALUE, + (long)Integer.MAX_VALUE * 60 * 1000); + + cal.clear(); + // Make sure to use Gregorian dates (before and after the + // set() call) for testing + cal.set(250000, cal.JANUARY, 1); + checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MIN_VALUE, + (long)Integer.MIN_VALUE * 60 * 60 * 1000); + + cal.clear(); + cal.set(250000, cal.JANUARY, 1); + checkTimeCalculation(cal, cal.HOUR, Integer.MIN_VALUE, + (long)Integer.MIN_VALUE * 60 * 60 * 1000); + + cal.clear(); + cal.set(250000, cal.JANUARY, 1); + checkTimeCalculation(cal, cal.MINUTE, Integer.MIN_VALUE, + (long)Integer.MIN_VALUE * 60 * 1000); + } + + private void checkTimeCalculation(Koyomi cal, int field, int value, long expectedDelta) { + long time = cal.getTimeInMillis(); + cal.set(field, value); + long time2 = cal.getTimeInMillis(); + if ((time + expectedDelta) != time2) { + String s = value == Integer.MAX_VALUE ? "Integer.MAX_VALUE" : "Integer.MIN_VALUE"; + errln("set(" + Koyomi.getFieldName(field) + ", " + s + ") failed." + " got " + time2 + + ", expected " + (time+expectedDelta)); + } + } + + /** + * 4722650: Calendar.equals can throw an exception in non-lenient + * (piggy-back tests for compareTo() which is new in 1.5) + */ + public void Test4722650() { + Calendar cal1 = new GregorianCalendar(); + cal1.clear(); + Calendar cal2 = new GregorianCalendar(); + cal2.clear(); + cal2.setLenient(false); + + cal1.set(2003, Calendar.OCTOBER, 31); + cal2.set(2003, Calendar.OCTOBER, 31); + try { + if (cal1.equals(cal2)) { + errln("lenient and non-lenient shouldn't be equal. (2003/10/31)"); + } + if (cal1.compareTo(cal2) != 0) { + errln("cal1 and cal2 should represent the same time. (2003/10/31)"); + } + } catch (IllegalArgumentException e) { + errln("equals threw IllegalArugumentException with non-lenient"); + } + + cal1.set(2003, Calendar.OCTOBER, 32); + cal2.set(2003, Calendar.OCTOBER, 32); + try { + if (cal1.equals(cal2)) { + errln("lenient and non-lenient shouldn't be equal. (2003/10/32)"); + } + if (cal1.compareTo(cal2) != 0) { + errln("cal1 and cal2 should represent the same time. (2003/10/32)"); + } + } catch (IllegalArgumentException e) { + errln("equals threw IllegalArugumentException with non-lenient"); + } + + cal1 = Calendar.getInstance(new Locale("th", "TH")); + cal1.setTimeInMillis(0L); + cal2 = Calendar.getInstance(Locale.US); + cal2.setTimeInMillis(0L); + if (cal1.equals(cal2)) { + errln("Buddhist.equals(Gregorian) shouldn't be true. (millis=0)"); + } + if (cal1.compareTo(cal2) != 0) { + errln("cal1 (Buddhist) and cal2 (Gregorian) should represent the same time. (millis=0)"); + } + } + + /** + * 4738710: API: Calendar comparison methods should be improved + */ + public void Test4738710() { + Calendar cal0 = new GregorianCalendar(2003, Calendar.SEPTEMBER, 30); + Comparable cal1 = new GregorianCalendar(2003, Calendar.OCTOBER, 1); + Calendar cal2 = new GregorianCalendar(2003, Calendar.OCTOBER, 2); + if (!(cal1.compareTo(cal0) > 0)) { + errln("!(cal1 > cal0)"); + } + if (!(cal1.compareTo(cal2) < 0)) { + errln("!(cal1 < cal2)"); + } + if (cal1.compareTo(new GregorianCalendar(2003, Calendar.OCTOBER, 1)) != 0) { + errln("cal1 != new GregorianCalendar(2003, Calendar.OCTOBER, 1)"); + } + + if (cal0.after(cal2)) { + errln("cal0 shouldn't be after cal2"); + } + if (cal2.before(cal0)) { + errln("cal2 shouldn't be before cal0"); + } + + if (cal0.after(new Integer(0))) { + errln("cal0.after() returned true with an Integer."); + } + if (cal0.before(new Integer(0))) { + errln("cal0.before() returned true with an Integer."); + } + if (cal0.after(null)) { + errln("cal0.after() returned true with null."); + } + if (cal0.before(null)) { + errln("cal0.before() returned true with null."); + } + } + + /** + * 4633646: Setting WEEK_OF_MONTH to 1 results in incorrect date + */ + public void Test4633646() { + Koyomi cal = new Koyomi(Locale.US); + cal.setTime(new Date(2002-1900, 1-1, 28)); + sub4633646(cal); + + cal.setLenient(false); + cal.setTime(new Date(2002-1900, 1-1, 28)); + sub4633646(cal); + + cal = new Koyomi(Locale.US); + cal.clear(); + cal.set(2002, cal.JANUARY, 28); + sub4633646(cal); + + cal.clear(); + cal.setLenient(false); + cal.set(2002, cal.JANUARY, 28); + sub4633646(cal); + } + + void sub4633646(Koyomi cal) { + cal.getTime(); + cal.set(cal.WEEK_OF_MONTH, 1); + if (cal.isLenient()) { + if (!cal.checkDate(2001, cal.DECEMBER, 31)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(cal.WEEK_OF_MONTH, 6)) { + errln(cal.getMessage()); + } + } else { + try { + Date d = cal.getTime(); + errln("didn't throw IllegalArgumentException in non-lenient"); + } catch (IllegalArgumentException e) { + } + } + } + + /** + * 4846659: Calendar: Both set() and roll() don't work for AM_PM time field + * (Partially fixed only roll as of 1.5) + */ + public void Test4846659() { + Koyomi cal = new Koyomi(); + cal.clear(); + cal.set(2003, cal.OCTOBER, 31, 10, 30, 30); + cal.getTime(); + // Test roll() + cal.roll(cal.AM_PM, +1); // should turn to PM + if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) { + errln("roll: AM_PM didn't change to PM"); + } + + cal.clear(); + cal.set(2003, cal.OCTOBER, 31, 10, 30, 30); + cal.getTime(); + // Test set() + cal.set(cal.AM_PM, cal.PM); // should turn to PM + if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) { + errln("set: AM_PM didn't change to PM"); + } + + cal.clear(); + cal.set(2003, cal.OCTOBER, 31, 10, 30, 30); + cal.getTime(); + cal.set(cal.AM_PM, cal.PM); + cal.set(cal.HOUR, 9); + if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 9+12)) { + errln("set: both AM_PM and HOUT didn't change to PM"); + } + } + + /** + * 4822110: GregorianCalendar.get() returns an incorrect date after setFirstDayOfWeek() + */ + public void Test4822110() { + Koyomi cal = new Koyomi(Locale.US); + // June 2003 + // S M Tu W Th F S + // 1 2 3 4 5 6 7 + // 8 9 10 11 12 13 14 + // 15 16 17 18 19 20 21 + // 22 23 24 25 26 27 28 + // 29 30 + cal.clear(); + // 6/1 to 6/7 should be the 1st week of June. + cal.set(2003, cal.JUNE, 2); + cal.getTime(); // Let cal calculate time. + cal.setFirstDayOfWeek(cal.MONDAY); + // Now 6/2 to 6/8 should be the 2nd week of June. Sunday of + // that week is 6/8. + logln("1: " +cal.get(cal.WEEK_OF_MONTH)+", "+cal.get(cal.DAY_OF_MONTH)); + cal.set(cal.DAY_OF_WEEK, cal.SUNDAY); + logln("1st Sunday of June 2003 with FirstDayOfWeek=MONDAY"); + if (!cal.checkDate(2003, cal.JUNE, 8)) { + errln(cal.getMessage()); + } + } + + /** + * 4973919: Inconsistent GregorianCalendar hashCode before and after serialization + */ + public void Test4966499() throws Exception { + GregorianCalendar date1 = new GregorianCalendar(2004, Calendar.JANUARY, 7); + + // Serialize date1 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(date1); + + byte[] buffer = baos.toByteArray(); + + // Deserialize it + ByteArrayInputStream bais = new ByteArrayInputStream(buffer); + ObjectInputStream ois = new ObjectInputStream(bais); + GregorianCalendar date2 = (GregorianCalendar)ois.readObject(); + + if (!date1.equals(date2)) { + errln("date1.equals(date2) != true"); + } + if (date1.hashCode() != date2.hashCode()) { + errln("inconsistent hashCode() value (before=0x" + +Integer.toHexString(date1.hashCode())+ + ", after=0x"+Integer.toHexString(date2.hashCode())+")"); + } + } + + /** + * 4980088: GregorianCalendar.getActualMaximum doesn't throw exception + */ + public void Test4980088() { + GregorianCalendar cal = new GregorianCalendar(); + try { + int x = cal.getMaximum(100); + errln("getMaximum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getMaximum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getLeastMaximum(100); + errln("getLeastMaximum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getLeastMaximum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getActualMaximum(100); + errln("getActualMaximum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getActualMaximum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getMinimum(100); + errln("getMinimum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getMinimum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getGreatestMinimum(100); + errln("getGreatestMinimum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getGreatestMinimum: " + e.getClass().getName() + ": " + e.getMessage()); + } + + try { + int x = cal.getActualMinimum(100); + errln("getActualMinimum(100) didn't throw an exception."); + } catch (IndexOutOfBoundsException e) { + logln("getActualMinimum: " + e.getClass().getName() + ": " + e.getMessage()); + } + } + + /** + * 4965624: GregorianCalendar.isLeapYear(1000) returns incorrect value + */ + public void Test4965624() { + // 5013094: This test case needs to use "GMT" to specify + // Gregorian cutover dates. + TimeZone savedZone = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + try { + Map data = new HashMap(); + data.put(getGregorianDate(999, Calendar.OCTOBER, 1), Boolean.FALSE); + data.put(getGregorianDate(1000, Calendar.JANUARY, 1), Boolean.FALSE); + data.put(getGregorianDate(1000, Calendar.FEBRUARY, 1), Boolean.FALSE); + data.put(getGregorianDate(1000, Calendar.FEBRUARY, 28), Boolean.FALSE); + data.put(getGregorianDate(1000, Calendar.MARCH, 1), Boolean.TRUE); + data.put(getGregorianDate(1001, Calendar.JANUARY, 1), Boolean.TRUE); + data.put(getGregorianDate(1001, Calendar.JANUARY, 6), Boolean.TRUE); + data.put(getGregorianDate(1001, Calendar.MARCH, 1), Boolean.TRUE); + + Iterator itr = data.keySet().iterator(); + while (itr.hasNext()) { + Date d = itr.next(); + boolean expected = data.get(d).booleanValue(); + GregorianCalendar cal = new GregorianCalendar(); + cal.setGregorianChange(d); + if (cal.isLeapYear(1000) != expected) { + errln("isLeapYear(1000) returned " + cal.isLeapYear(1000) + + " with cutover date (Julian) " + d); + } + } + } + finally { + TimeZone.setDefault(savedZone); + } + } + + // Note that we can't use Date to produce Gregorian calendar dates + // before the default cutover date. + static Date getGregorianDate(int year, int month, int dayOfMonth) { + GregorianCalendar g = new GregorianCalendar(); + // Make g a pure Gregorian calendar + g.setGregorianChange(new Date(Long.MIN_VALUE)); + g.clear(); + g.set(year, month, dayOfMonth); + return g.getTime(); + } + + /** + * 5006864: Define the minimum value of DAY_OF_WEEK_IN_MONTH as 1 + */ + public void Test5006864() { + GregorianCalendar cal = new GregorianCalendar(); + int min = cal.getMinimum(cal.DAY_OF_WEEK_IN_MONTH); + if (min != 1) { + errln("GregorianCalendar.getMinimum(DAY_OF_WEEK_IN_MONTH) returned " + + min + ", expected 1."); + } + min = cal.getGreatestMinimum(cal.DAY_OF_WEEK_IN_MONTH); + if (min != 1) { + errln("GregorianCalendar.getGreatestMinimum(DAY_OF_WEEK_IN_MONTH) returned " + + min + ", expected 1."); + } + } +} diff --git a/jdk/test/java/util/Calendar/CalendarTest.java b/jdk/test/java/util/Calendar/CalendarTest.java new file mode 100644 index 00000000000..d8320295a6d --- /dev/null +++ b/jdk/test/java/util/Calendar/CalendarTest.java @@ -0,0 +1,1102 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4064654 4374886 4984320 4984574 4944795 + * @library /java/text/testlib + * @summary test for Calendar + * @key randomness + */ + +import java.util.*; +import java.text.*; +import java.io.*; + +public class CalendarTest extends IntlTest { + static final int ONE_DAY = 24*60*60*1000; + static final int EPOCH_JULIAN = 2440588; + + public static void main(String argv[]) throws Exception { + new CalendarTest().run(argv); + } + + /** + * Test the behavior of the GregorianCalendar around the changeover. + */ + public void TestGregorianChangeover() { + TimeZone savedZone = TimeZone.getDefault(); + /* + Changeover -7 days: 1582/9/28 dow=6 + Changeover -6 days: 1582/9/29 dow=7 + Changeover -5 days: 1582/9/30 dow=1 + Changeover -4 days: 1582/10/1 dow=2 + Changeover -3 days: 1582/10/2 dow=3 + Changeover -2 days: 1582/10/3 dow=4 + Changeover -1 days: 1582/10/4 dow=5 + Changeover +0 days: 1582/10/15 dow=6 + Changeover +1 days: 1582/10/16 dow=7 + Changeover +2 days: 1582/10/17 dow=1 + Changeover +3 days: 1582/10/18 dow=2 + Changeover +4 days: 1582/10/19 dow=3 + Changeover +5 days: 1582/10/20 dow=4 + Changeover +6 days: 1582/10/21 dow=5 + Changeover +7 days: 1582/10/22 dow=6 + */ + int MON[] = { 9, 9, 9,10,10,10,10, 10, 10, 10, 10, 10, 10, 10, 10 }; + int DOM[] = { 28, 29, 30, 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22 }; + int DOW[] = { 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6 }; + // ^ <-Changeover Fri Oct 15 1582 + + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Date co = new Date(1582-1900, Calendar.OCTOBER, 15); + GregorianCalendar cal = new GregorianCalendar(); + int j = 0; + for (int i = -7; i <= 7; ++i, ++j) { + Date d = new Date(co.getTime() + i*ONE_DAY); + cal.setTime(d); + int y = cal.get(Calendar.YEAR); + int mon = cal.get(Calendar.MONTH)+1-Calendar.JANUARY; + int dom = cal.get(Calendar.DATE); + int dow = cal.get(Calendar.DAY_OF_WEEK); + + logln("Changeover " + (i>=0?"+":"") + i + + " days: " + y + "/" + mon + "/" + dom + " dow=" + dow); + if (y != 1582 || mon != MON[j] || dom != DOM[j] || dow != DOW[j]) { + errln(" Fail: Above line is wrong"); + } + } + } + finally { + TimeZone.setDefault(savedZone); + } + } + + /** + * Test the mapping between millis and fields. For the purposes + * of this test, we don't care about timezones and week data + * (first day of week, minimal days in first week). + */ + public void TestMapping() { + TimeZone saveZone = TimeZone.getDefault(); + int[] DATA = { + // Julian# Year Month DOM JULIAN:Year, Month, DOM + 2440588, 1970, Calendar.JANUARY, 1, 1969, Calendar.DECEMBER, 19, + 2415080, 1900, Calendar.MARCH, 1, 1900, Calendar.FEBRUARY, 17, + 2451604, 2000, Calendar.FEBRUARY, 29, 2000, Calendar.FEBRUARY, 16, + 2452269, 2001, Calendar.DECEMBER, 25, 2001, Calendar.DECEMBER, 12, + 2416526, 1904, Calendar.FEBRUARY, 15, 1904, Calendar.FEBRUARY, 2, + 2416656, 1904, Calendar.JUNE, 24, 1904, Calendar.JUNE, 11, + 1721426, 1, Calendar.JANUARY, 1, 1, Calendar.JANUARY, 3, + 2000000, 763, Calendar.SEPTEMBER, 18, 763, Calendar.SEPTEMBER, 14, + 4000000, 6239, Calendar.JULY, 12, 6239, Calendar.MAY, 28, + 8000000, 17191, Calendar.FEBRUARY, 26, 17190, Calendar.OCTOBER, 22, + 10000000, 22666, Calendar.DECEMBER, 20, 22666, Calendar.JULY, 5, + }; + + try { + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + Date PURE_GREGORIAN = new Date(Long.MIN_VALUE); + Date PURE_JULIAN = new Date(Long.MAX_VALUE); + GregorianCalendar cal = new GregorianCalendar(); + for (int i = 0; i < DATA.length; i += 7) { + int julian = DATA[i]; + int year = DATA[i+1]; + int month = DATA[i+2]; + int dom = DATA[i+3]; + int year2, month2, dom2; + long millis = ((long)julian - EPOCH_JULIAN) * ONE_DAY; + String s; + + // Test Gregorian computation + cal.setGregorianChange(PURE_GREGORIAN); + cal.clear(); + cal.set(year, month, dom); + long calMillis = cal.getTime().getTime(); + long delta = calMillis - millis; + cal.setTime(new Date(millis)); + year2 = cal.get(Calendar.YEAR); + month2 = cal.get(Calendar.MONTH); + dom2 = cal.get(Calendar.DAY_OF_MONTH); + s = "G " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom + + " => " + calMillis + + " (" + ((float)delta/ONE_DAY) + " day delta) => " + + year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2; + if (delta != 0 || year != year2 || month != month2 || + dom != dom2) { + errln(s + " FAIL"); + } else { + logln(s); + } + + // Test Julian computation + year = DATA[i+4]; + month = DATA[i+5]; + dom = DATA[i+6]; + cal.setGregorianChange(PURE_JULIAN); + cal.clear(); + cal.set(year, month, dom); + calMillis = cal.getTime().getTime(); + delta = calMillis - millis; + cal.setTime(new Date(millis)); + year2 = cal.get(Calendar.YEAR); + month2 = cal.get(Calendar.MONTH); + dom2 = cal.get(Calendar.DAY_OF_MONTH); + s = "J " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom + + " => " + calMillis + + " (" + ((float)delta/ONE_DAY) + " day delta) => " + + year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2; + if (delta != 0 || year != year2 || month != month2 || + dom != dom2) { + errln(s + " FAIL"); + } else { + logln(s); + } + } + + cal.setGregorianChange(new Date(1582-1900, Calendar.OCTOBER, 15)); + auxMapping(cal, 1582, Calendar.OCTOBER, 4); + auxMapping(cal, 1582, Calendar.OCTOBER, 15); + auxMapping(cal, 1582, Calendar.OCTOBER, 16); + for (int y = 800; y < 3000; y += 1+(int)100*Math.random()) { + for (int m = Calendar.JANUARY; m <= Calendar.DECEMBER; ++m) { + auxMapping(cal, y, m, 15); + } + } + } + finally { + TimeZone.setDefault(saveZone); + } + } + private void auxMapping(Calendar cal, int y, int m, int d) { + cal.clear(); + cal.set(y, m, d); + long millis = cal.getTime().getTime(); + cal.setTime(new Date(millis)); + int year2 = cal.get(Calendar.YEAR); + int month2 = cal.get(Calendar.MONTH); + int dom2 = cal.get(Calendar.DAY_OF_MONTH); + if (y != year2 || m != month2 || dom2 != d) + errln("Round-trip failure: " + y + "-" + (m+1) + "-"+d+" =>ms=> " + + year2 + "-" + (month2+1) + "-" + dom2); + } + + public void TestGenericAPI() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + String str; + + Date when = new Date(90, Calendar.APRIL, 15); + + String tzid = "TestZone"; + int tzoffset = 123400; + + SimpleTimeZone zone = new SimpleTimeZone(tzoffset, tzid); + Calendar cal = (Calendar)Calendar.getInstance((SimpleTimeZone)zone.clone()); + + if (!zone.equals(cal.getTimeZone())) errln("FAIL: Calendar.getTimeZone failed"); + + Calendar cal2 = Calendar.getInstance(cal.getTimeZone()); + + cal.setTime(when); + cal2.setTime(when); + + if (!(cal.equals(cal2))) errln("FAIL: Calendar.operator== failed"); + // if ((*cal != *cal2)) errln("FAIL: Calendar.operator!= failed"); + if (!cal.equals(cal2) || + cal.before(cal2) || + cal.after(cal2)) errln("FAIL: equals/before/after failed"); + + cal2.setTime(new Date(when.getTime() + 1000)); + if (cal.equals(cal2) || + cal2.before(cal) || + cal.after(cal2)) errln("FAIL: equals/before/after failed"); + + cal.roll(Calendar.SECOND, true); + if (!cal.equals(cal2) || + cal.before(cal2) || + cal.after(cal2)) errln("FAIL: equals/before/after failed"); + + // Roll back to January + cal.roll(Calendar.MONTH, (int)(1 + Calendar.DECEMBER - cal.get(Calendar.MONTH))); + if (cal.equals(cal2) || + cal2.before(cal) || + cal.after(cal2)) errln("FAIL: equals/before/after failed"); + + // C++ only + /* TimeZone z = cal.orphanTimeZone(); + if (z.getID(str) != tzid || + z.getRawOffset() != tzoffset) + errln("FAIL: orphanTimeZone failed"); + */ + + for (int i = 0; i < 2; ++i) { + boolean lenient = ( i > 0 ); + cal.setLenient(lenient); + if (lenient != cal.isLenient()) errln("FAIL: setLenient/isLenient failed"); + // Later: Check for lenient behavior + } + + int i; + for (i = Calendar.SUNDAY; i <= Calendar.SATURDAY; ++i) { + cal.setFirstDayOfWeek(i); + if (cal.getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed"); + } + + for (i = 0; i <= 7; ++i) { + cal.setMinimalDaysInFirstWeek(i); + if (cal.getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed"); + } + + for (i = 0; i < Calendar.FIELD_COUNT; ++i) { + if (cal.getMinimum(i) != cal.getGreatestMinimum(i)) + errln("FAIL: getMinimum doesn't match getGreatestMinimum for field " + i); + if (cal.getLeastMaximum(i) > cal.getMaximum(i)) + errln("FAIL: getLeastMaximum larger than getMaximum for field " + i); + if (cal.getMinimum(i) >= cal.getMaximum(i)) + errln("FAIL: getMinimum not less than getMaximum for field " + i); + } + + cal.setTimeZone(TimeZone.getDefault()); + cal.clear(); + cal.set(1984, 5, 24); + if (cal.getTime().getTime() != new Date(84, 5, 24).getTime()) { + errln("FAIL: Calendar.set(3 args) failed"); + logln(" Got: " + cal.getTime() + " Expected: " + new Date(84, 5, 24)); + } + + cal.clear(); + cal.set(1985, 3, 2, 11, 49); + if (cal.getTime().getTime() != new Date(85, 3, 2, 11, 49).getTime()) { + errln("FAIL: Calendar.set(5 args) failed"); + logln(" Got: " + cal.getTime() + " Expected: " + new Date(85, 3, 2, 11, 49)); + } + + cal.clear(); + cal.set(1995, 9, 12, 1, 39, 55); + if (cal.getTime().getTime() != new Date(95, 9, 12, 1, 39, 55).getTime()) { + errln("FAIL: Calendar.set(6 args) failed"); + logln(" Got: " + cal.getTime() + " Expected: " + new Date(95, 9, 12, 1, 39, 55)); + } + + cal.getTime(); + for (i = 0; i < Calendar.FIELD_COUNT; ++i) { + switch(i) { + case Calendar.YEAR: case Calendar.MONTH: case Calendar.DATE: + case Calendar.HOUR_OF_DAY: case Calendar.MINUTE: case Calendar.SECOND: + if (!cal.isSet(i)) + errln("FAIL: !Calendar.isSet test failed: " + calendarFieldNames[i]); + break; + default: + if (cal.isSet(i)) + errln("FAIL: Calendar.isSet test failed: " + calendarFieldNames[i]); + } + cal.clear(i); + if (cal.isSet(i)) errln("FAIL: Calendar.clear/isSet failed"); + } + + // delete cal; + // delete cal2; + + Locale[] loc = Calendar.getAvailableLocales(); + long count = loc.length; + if (count < 1 || loc == null) { + errln("FAIL: getAvailableLocales failed"); + } + else { + for (i = 0; i < count; ++i) { + cal = Calendar.getInstance(loc[i]); + // delete cal; + } + } + + cal = Calendar.getInstance(TimeZone.getDefault(), Locale.ENGLISH); + // delete cal; + + cal = Calendar.getInstance(zone, Locale.ENGLISH); + // delete cal; + + GregorianCalendar gc = new GregorianCalendar(zone); + // delete gc; + + gc = new GregorianCalendar(Locale.ENGLISH); + // delete gc; + + gc = new GregorianCalendar(Locale.ENGLISH); + // delete gc; + + gc = new GregorianCalendar(zone, Locale.ENGLISH); + // delete gc; + + gc = new GregorianCalendar(zone); + // delete gc; + + gc = new GregorianCalendar(1998, 10, 14, 21, 43); + if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43).getTime()) + errln("FAIL: new GregorianCalendar(ymdhm) failed"); + // delete gc; + + gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55); + if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43, 55).getTime()) + errln("FAIL: new GregorianCalendar(ymdhms) failed"); + + // C++ only: + // GregorianCalendar gc2 = new GregorianCalendar(Locale.ENGLISH); + // gc2 = gc; + // if (gc2 != gc || !(gc2 == gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed"); + // delete gc; + // delete z; + } + + // Verify Roger Webster's bug + public void TestRog() { + GregorianCalendar gc = new GregorianCalendar(); + + int year = 1997, month = Calendar.APRIL, date = 1; + gc.set(year, month, date); // April 1, 1997 + + gc.set(Calendar.HOUR_OF_DAY, 23); + gc.set(Calendar.MINUTE, 0); + gc.set(Calendar.SECOND, 0); + gc.set(Calendar.MILLISECOND, 0); + + for (int i = 0; i < 9; i++, gc.add(Calendar.DATE, 1)) { + if (gc.get(Calendar.YEAR) != year || + gc.get(Calendar.MONTH) != month || + gc.get(Calendar.DATE) != (date + i)) + errln("FAIL: Date " + gc.getTime() + " wrong"); + } + } + + // Verify DAY_OF_WEEK + public void TestDOW943() { + dowTest(false); + dowTest(true); + } + + void dowTest(boolean lenient) { + GregorianCalendar cal = new GregorianCalendar(); + cal.set(1997, Calendar.AUGUST, 12); // Wednesday + cal.getTime(); // Force update + cal.setLenient(lenient); + cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996 + int dow = cal.get(Calendar.DAY_OF_WEEK); + int min = cal.getMinimum(Calendar.DAY_OF_WEEK); + int max = cal.getMaximum(Calendar.DAY_OF_WEEK); + if (dow < min || dow > max) errln("FAIL: Day of week " + dow + " out of range"); + if (dow != Calendar.SUNDAY) { + errln("FAIL2: Day of week should be SUNDAY; is " + dow + ": " + cal.getTime()); + } + if (min != Calendar.SUNDAY || max != Calendar.SATURDAY) errln("FAIL: Min/max bad"); + } + + // Verify that the clone method produces distinct objects with no + // unintentionally shared fields. + public void TestClonesUnique908() { + Calendar c = Calendar.getInstance(); + Calendar d = (Calendar)c.clone(); + c.set(Calendar.MILLISECOND, 123); + d.set(Calendar.MILLISECOND, 456); + if (c.get(Calendar.MILLISECOND) != 123 || + d.get(Calendar.MILLISECOND) != 456) { + errln("FAIL: Clones share fields"); + } + } + + // Verify effect of Gregorian cutoff value + public void TestGregorianChange768() { + boolean b; + GregorianCalendar c = new GregorianCalendar(); + logln("With cutoff " + c.getGregorianChange()); + logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800))); + logln(" (should be FALSE)"); + if (b != false) errln("FAIL"); + c.setGregorianChange(new Date(0, 0, 1)); // Jan 1 1900 + logln("With cutoff " + c.getGregorianChange()); + logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800))); + logln(" (should be TRUE)"); + if (b != true) errln("FAIL"); + } + + // Test the correct behavior of the disambiguation algorithm. + public void TestDisambiguation765() throws Exception { + Locale savedLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + Calendar c = Calendar.getInstance(); + c.setLenient(false); + + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.MONTH, Calendar.JUNE); + c.set(Calendar.DATE, 3); + + verify765("1997 third day of June = ", c, 1997, Calendar.JUNE, 3); + + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.MONTH, Calendar.JUNE); + c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1); + verify765("1997 first Tuesday in June = ", c, 1997, Calendar.JUNE, 3); + + c.setLenient(true); // for 4944795 + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.MONTH, Calendar.JUNE); + c.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1); + verify765("1997 last Tuesday in June = ", c, 1997, Calendar.JUNE, 24); + + c.setLenient(false); + IllegalArgumentException e = null; + try { + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.MONTH, Calendar.JUNE); + c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 0); + c.getTime(); + } + catch (IllegalArgumentException ex) { + e = ex; + } + verify765("1997 zero-th Tuesday in June = ", e); + + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.MONTH, Calendar.JUNE); + c.set(Calendar.WEEK_OF_MONTH, 1); + verify765("1997 Tuesday in week 1 of June = ", c, 1997, Calendar.JUNE, 3); + + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.MONTH, Calendar.JUNE); + c.set(Calendar.WEEK_OF_MONTH, 4); + verify765("1997 Tuesday in week 4 of June = ", c, 1997, Calendar.JUNE, 24); + + try { + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.MONTH, Calendar.JUNE); + c.set(Calendar.WEEK_OF_MONTH, 1); + verify765("1997 Tuesday in week 0 of June = ", c, 1997, Calendar.JUNE, 3); + } + catch (IllegalArgumentException ex) { + errln("FAIL: Exception seen: " + ex.getMessage()); + // ex.printStackTrace(log); + } + + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.WEEK_OF_YEAR, 2); + verify765("1997 Tuesday in week 2 of year = ", c, 1997, Calendar.JANUARY, 7); + + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.WEEK_OF_YEAR, 10); + verify765("1997 Tuesday in week 10 of year = ", c, 1997, Calendar.MARCH, 4); + + try { + c.clear(); + c.set(Calendar.YEAR, 1997); + c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY); + c.set(Calendar.WEEK_OF_YEAR, 0); + verify765("1997 Tuesday in week 0 of year = ", c, 1996, Calendar.DECEMBER, 24); + throw new Exception("Fail: WEEK_OF_YEAR 0 should be illegal"); + } + catch (IllegalArgumentException ex) {} + } + finally { + Locale.setDefault(savedLocale); + } + } + void verify765(String msg, Calendar c, int year, int month, int day) { + if (c.get(Calendar.YEAR) == year && + c.get(Calendar.MONTH) == month && + c.get(Calendar.DATE) == day) { + logln("PASS: " + msg + c.getTime()); + } + else { + errln("FAIL: " + msg + c.getTime() + + "; expected " + + year + "/" + (month+1) + "/" + day); + } + } + // Called when e expected to be non-null + void verify765(String msg, IllegalArgumentException e) { + if (e == null) errln("FAIL: No IllegalArgumentException for " + msg); + else logln("PASS: " + msg + "IllegalArgument as expected"); + } + + // Test the behavior of GMT vs. local time + public void TestGMTvsLocal4064654() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + // Sample output 1: + // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 1 1 12 0 0 + // date = Wed Jan 01 04:00:00 PST 1997 + // offset for Wed Jan 01 04:00:00 PST 1997= -8hr + test4064654(1997, 1, 1, 12, 0, 0); + + // Sample output 2: + // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 4 16 18 30 0 + // date = Wed Apr 16 10:30:00 PDT 1997 + // offset for Wed Apr 16 10:30:00 PDT 1997= -7hr + + // Note that in sample output 2 according to the offset, the gmt time + // of the result would be 1997 4 16 17 30 0 which is different from the + // input of 1997 4 16 18 30 0. + test4064654(1997, 4, 16, 18, 30, 0); + } + void test4064654(int yr, int mo, int dt, int hr, int mn, int sc) { + Date date; + Calendar gmtcal = Calendar.getInstance(); + gmtcal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca")); + gmtcal.set(yr, mo-1, dt, hr, mn, sc); + gmtcal.set(Calendar.MILLISECOND, 0); + + date = gmtcal.getTime(); + logln("date = "+date); + + Calendar cal = Calendar.getInstance(); + cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); + cal.setTime(date); + + int offset = cal.getTimeZone().getOffset(cal.get(Calendar.ERA), + cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH), + cal.get(Calendar.DATE), + cal.get(Calendar.DAY_OF_WEEK), + cal.get(Calendar.MILLISECOND)); + + logln("offset for "+date+"= "+(offset/1000/60/60.0) + "hr"); + + int utc = ((cal.get(Calendar.HOUR_OF_DAY) * 60 + + cal.get(Calendar.MINUTE)) * 60 + + cal.get(Calendar.SECOND)) * 1000 + + cal.get(Calendar.MILLISECOND) - offset; + + int expected = ((hr * 60 + mn) * 60 + sc) * 1000; + + if (utc != expected) + errln("FAIL: Discrepancy of " + + (utc - expected) + " millis = " + + ((utc-expected)/1000/60/60.0) + " hr"); + } + + // Verify that add and set work regardless of the order in which + // they are called. + public void TestAddSetOrder621() { + Date d = new Date(97, 4, 14, 13, 23, 45); + + Calendar cal = Calendar.getInstance (); + cal.setTime (d); + cal.add (Calendar.DATE, -5); + cal.set (Calendar.HOUR_OF_DAY, 0); + cal.set (Calendar.MINUTE, 0); + cal.set (Calendar.SECOND, 0); + // ma feb 03 00:00:00 GMT+00:00 1997 + String s = cal.getTime ().toString (); + + cal = Calendar.getInstance (); + cal.setTime (d); + cal.set (Calendar.HOUR_OF_DAY, 0); + cal.set (Calendar.MINUTE, 0); + cal.set (Calendar.SECOND, 0); + cal.add (Calendar.DATE, -5); + // ma feb 03 13:11:06 GMT+00:00 1997 + String s2 = cal.getTime ().toString (); + + if (s.equals(s2)) + logln("Pass: " + s + " == " + s2); + else + errln("FAIL: " + s + " != " + s2); + } + + // Verify that add works. + public void TestAdd520() { + int y = 1997, m = Calendar.FEBRUARY, d = 1; + GregorianCalendar temp = new GregorianCalendar( y, m, d ); + check520(temp, y, m, d); + + temp.add( temp.YEAR, 1 ); + y++; + check520(temp, y, m, d); + + temp.add( temp.MONTH, 1 ); + m++; + check520(temp, y, m, d); + + temp.add( temp.DATE, 1 ); + d++; + check520(temp, y, m, d); + + temp.add( temp.DATE, 2 ); + d += 2; + check520(temp, y, m, d); + + temp.add( temp.DATE, 28 ); + d = 1; ++m; + check520(temp, y, m, d); + } + void check520(Calendar c, int y, int m, int d) { + if (c.get(Calendar.YEAR) != y || + c.get(Calendar.MONTH) != m || + c.get(Calendar.DATE) != d) { + errln("FAILURE: Expected YEAR/MONTH/DATE of " + + y + "/" + (m+1) + "/" + d + + "; got " + + c.get(Calendar.YEAR) + "/" + + (c.get(Calendar.MONTH)+1) + "/" + + c.get(Calendar.DATE)); + } + else logln("Confirmed: " + + y + "/" + (m+1) + "/" + d); + } + + // Verify that setting fields works. This test fails when an exception is thrown. + public void TestFieldSet4781() { + try { + GregorianCalendar g = new GregorianCalendar(); + GregorianCalendar g2 = new GregorianCalendar(); + // At this point UTC value is set, various fields are not. + // Now set to noon. + g2.set(Calendar.HOUR, 12); + g2.set(Calendar.MINUTE, 0); + g2.set(Calendar.SECOND, 0); + // At this point the object thinks UTC is NOT set, but fields are set. + // The following line will result in IllegalArgumentException because + // it thinks the YEAR is set and it is NOT. + if (g2.equals(g)) + logln("Same"); + else + logln("Different"); + } + catch (IllegalArgumentException e) { + errln("Unexpected exception seen: " + e); + } + } + + // Test serialization of a Calendar object + public void TestSerialize337() { + Calendar cal = Calendar.getInstance(); + + boolean ok = false; + + try { + FileOutputStream f = new FileOutputStream(FILENAME); + ObjectOutput s = new ObjectOutputStream(f); + s.writeObject(PREFIX); + s.writeObject(cal); + s.writeObject(POSTFIX); + f.close(); + + FileInputStream in = new FileInputStream(FILENAME); + ObjectInputStream t = new ObjectInputStream(in); + String pre = (String)t.readObject(); + Calendar c = (Calendar)t.readObject(); + String post = (String)t.readObject(); + in.close(); + + ok = pre.equals(PREFIX) && + post.equals(POSTFIX) && + cal.equals(c); + + File fl = new File(FILENAME); + fl.delete(); + } + catch (IOException e) { + errln("FAIL: Exception received:"); + // e.printStackTrace(log); + } + catch (ClassNotFoundException e) { + errln("FAIL: Exception received:"); + // e.printStackTrace(log); + } + + if (!ok) errln("Serialization of Calendar object failed."); + } + static final String PREFIX = "abc"; + static final String POSTFIX = "def"; + static final String FILENAME = "tmp337.bin"; + + // Try to zero out the seconds field + public void TestSecondsZero121() { + Calendar cal = new GregorianCalendar(); + // Initialize with current date/time + cal.setTime(new Date()); + // Round down to minute + cal.set(Calendar.SECOND, 0); + Date d = cal.getTime(); + String s = d.toString(); + if (s.indexOf(":00 ") < 0) errln("Expected to see :00 in " + s); + } + + // Try various sequences of add, set, and get method calls. + public void TestAddSetGet0610() { + // + // Error case 1: + // - Upon initialization calendar fields, millis = System.currentTime + // - After set is called fields are initialized, time is not + // - Addition uses millis which are still *now* + // + { + Calendar calendar = new GregorianCalendar( ) ; + calendar.set( 1993, Calendar.JANUARY, 4 ) ; + logln( "1A) " + value( calendar ) ) ; + calendar.add( Calendar.DATE, 1 ) ; + String v = value(calendar); + logln( "1B) " + v ); + logln( "--) 1993/0/5" ) ; + if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + + "; saw " + v); + } + + // + // Error case 2: + // - Upon initialization calendar fields set, millis = 0 + // - Addition uses millis which are still 1970, 0, 1 + // + + { + Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ; + logln( "2A) " + value( calendar ) ) ; + calendar.add( Calendar.DATE, 1 ) ; + String v = value(calendar); + logln( "2B) " + v ); + logln( "--) 1993/0/5" ) ; + if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + + "; saw " + v); + } + + // + // Error case 3: + // - Upon initialization calendar fields, millis = 0 + // - getTime( ) is called which forces the millis to be set + // - Addition uses millis which are correct + // + + { + Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ; + logln( "3A) " + value( calendar ) ) ; + calendar.getTime( ) ; + calendar.add( Calendar.DATE, 1 ) ; + String v = value(calendar); + logln( "3B) " + v ) ; + logln( "--) 1993/0/5" ) ; + if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + + "; saw " + v); + } + } + static String value( Calendar calendar ) { + return( calendar.get( Calendar.YEAR ) + "/" + + calendar.get( Calendar.MONTH ) + "/" + + calendar.get( Calendar.DATE ) ) ; + } + static String EXPECTED_0610 = "1993/0/5"; + + // Test that certain fields on a certain date are as expected. + public void TestFields060() { + int year = 1997; + int month = java.util.Calendar.OCTOBER; //october + int dDate = 22; //DAYOFWEEK should return 3 for Wednesday + GregorianCalendar calendar = null; + + calendar = new GregorianCalendar( year, month, dDate); + for (int i = 0; i < EXPECTED_FIELDS.length; ) { + int field = EXPECTED_FIELDS[i++]; + int expected = EXPECTED_FIELDS[i++]; + if (calendar.get(field) != expected) { + errln("Expected field " + field + " to have value " + expected + + "; received " + calendar.get(field) + " instead"); + } + } + } + static int EXPECTED_FIELDS[] = { + Calendar.YEAR, 1997, + Calendar.MONTH, Calendar.OCTOBER, + Calendar.DAY_OF_MONTH, 22, + Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY, + Calendar.DAY_OF_WEEK_IN_MONTH, 4, + Calendar.DAY_OF_YEAR, 295 + }; + + static final String[] calendarFieldNames = { + /* 0 */ "ERA", + /* 1 */ "YEAR", + /* 2 */ "MONTH", + /* 3 */ "WEEK_OF_YEAR", + /* 4 */ "WEEK_OF_MONTH", + /* 5 */ "DAY_OF_MONTH", + /* 6 */ "DAY_OF_YEAR", + /* 7 */ "DAY_OF_WEEK", + /* 8 */ "DAY_OF_WEEK_IN_MONTH", + /* 9 */ "AM_PM", + /* 10 */ "HOUR", + /* 11 */ "HOUR_OF_DAY", + /* 12 */ "MINUTE", + /* 13 */ "SECOND", + /* 14 */ "MILLISECOND", + /* 15 */ "ZONE_OFFSET", + /* 16 */ "DST_OFFSET" + }; + + // Verify that the fields are as expected (mostly zero) at the epoch start. + // Note that we adjust for the default timezone to get most things to zero. + public void TestEpochStartFields() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + String[][] lt = { + {"en", "US", "US/Pacific"}, /* First day = 1, Minimum day = 1 */ + {"en", "US", "America/Anchorage"}, /* First day = 1, Minimum day = 1 */ + {"en", "TO", "Pacific/Tongatapu"}, /* First day = 1, Minimum day = 1 */ + {"en", "MH", "Pacific/Majuro"}, /* First day = 1, Minimum day = 1 */ + {"ja", "JP", "Asia/Tokyo"}, /* First day = 1, Minimum day = 1 */ + {"iw", "IL", "Asia/Jerusalem"}, /* First day = 1, Minimum day = 1 */ + {"hi", "IN", "Asia/Jakarta"}, /* First day = 1, Minimum day = 1 */ + {"en", "GB", "Europe/London"}, /* First day = 2, Minimum day = 1 */ + {"en", "GB", "GMT"}, /* First day = 2, Minimum day = 1 */ + {"de", "DE", "Europe/Berlin"}, /* First day = 2, Minimum day = 4 */ + {"ar", "EG", "Africa/Cairo"}, /* First day = 7, Minimum day = 1 */ + }; + + int[][] goldenData = { + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, -28800000, 0}, + {1, 1969, 11, 1, 5, 31, 365, 4, 5, 1, 11, 23, 0, 0, 0, -36000000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 46800000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 43200000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 32400000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 25200000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 1, 1, 0, 0, 0, 3600000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 3600000, 0}, + {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0}, + }; + + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + + try { + for (int j = 0; j < lt.length; j++) { + Locale l = new Locale(lt[j][0], lt[j][1]); + TimeZone z = TimeZone.getTimeZone(lt[j][2]); + Locale.setDefault(l); + TimeZone.setDefault(z); + Calendar c = Calendar.getInstance(); + Date d = new Date(-z.getRawOffset()); + + int val; + int[] EPOCH_FIELDS = goldenData[j]; + c.setTime(d); + + boolean err = false; + for (int i = 0; i < calendarFieldNames.length; ++i) { + if ((val = c.get(i)) != EPOCH_FIELDS[i]) { + errln("Wrong value: " + val + + " for field(" + calendarFieldNames[i] + + "), expected: " + EPOCH_FIELDS[i]); + err = true; + } + } + if (err) { + errln("Failed: \n\tDate=" + d + "\n\tTimeZone=" + z + + "\n\tLocale=" + l + "\n\tCalendar=" + c); + } + } + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + } + + // Verify that as you add days to the calendar (e.g., 24 day periods), + // the day of the week shifts in the expected pattern. + public void TestDOWProgression() { + Calendar cal = + new GregorianCalendar(1972, Calendar.OCTOBER, 26); + marchByDelta(cal, 24); // Last parameter must be != 0 modulo 7 + } + + // Supply a delta which is not a multiple of 7. + void marchByDelta(Calendar cal, int delta) { + Calendar cur = (Calendar)cal.clone(); + int initialDOW = cur.get(Calendar.DAY_OF_WEEK); + int DOW, newDOW = initialDOW; + do { + DOW = newDOW; + logln("DOW = " + DOW + " " + cur.getTime()); + + cur.add(Calendar.DAY_OF_WEEK, delta); + newDOW = cur.get(Calendar.DAY_OF_WEEK); + int expectedDOW = 1 + (DOW + delta - 1) % 7; + if (newDOW != expectedDOW) { + errln("Day of week should be " + expectedDOW + + " instead of " + newDOW + " on " + cur.getTime()); + return; + } + } + while (newDOW != initialDOW); + } + + public void TestActualMinMax() { + Calendar cal = new GregorianCalendar(1967, Calendar.MARCH, 10); + cal.setFirstDayOfWeek(Calendar.SUNDAY); + cal.setMinimalDaysInFirstWeek(3); + + if (cal.getActualMinimum(Calendar.DAY_OF_MONTH) != 1) + errln("Actual minimum date for 3/10/1967 should have been 1; got " + + cal.getActualMinimum(Calendar.DAY_OF_MONTH)); + if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 31) + errln("Actual maximum date for 3/10/1967 should have been 31; got " + + cal.getActualMaximum(Calendar.DAY_OF_MONTH)); + + cal.set(Calendar.MONTH, Calendar.FEBRUARY); + if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 28) + errln("Actual maximum date for 2/10/1967 should have been 28; got " + + cal.getActualMaximum(Calendar.DAY_OF_MONTH)); + if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 365) + errln("Number of days in 1967 should have been 365; got " + + cal.getActualMaximum(Calendar.DAY_OF_YEAR)); + + cal.set(Calendar.YEAR, 1968); + if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 29) + errln("Actual maximum date for 2/10/1968 should have been 29; got " + + cal.getActualMaximum(Calendar.DAY_OF_MONTH)); + if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 366) + errln("Number of days in 1968 should have been 366; got " + + cal.getActualMaximum(Calendar.DAY_OF_YEAR)); + // Using week settings of SUNDAY/3 (see above) + if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 52) + errln("Number of weeks in 1968 should have been 52; got " + + cal.getActualMaximum(Calendar.WEEK_OF_YEAR)); + + cal.set(Calendar.YEAR, 1976); + // Using week settings of SUNDAY/3 (see above) + if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 53) + errln("Number of weeks in 1976 should have been 53; got " + + cal.getActualMaximum(Calendar.WEEK_OF_YEAR)); + } + + public void TestRoll() { + Calendar cal = new GregorianCalendar(1997, Calendar.JANUARY, 31); + + int[] dayValues = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 }; + + for (int i = 0; i < dayValues.length; i++) { + Calendar cal2 = (Calendar)cal.clone(); + cal2.roll(Calendar.MONTH, i); + if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues[i]) + errln("Rolling the month in 1/31/1997 up by " + i + " should have yielded " + + ((i + 1) % 12) + "/" + dayValues[i] + "/1997, but actually yielded " + + ((i + 1) % 12) + "/" + cal2.get(Calendar.DAY_OF_MONTH) + "/1997."); + } + + cal.set(1996, Calendar.FEBRUARY, 29); + + int[] monthValues = { 1, 2, 2, 2, 1, 2, 2, 2, 1, 2 }; + int[] dayValues2 = { 29, 1, 1, 1, 29, 1, 1, 1, 29, 1 }; + + for (int i = 0; i < dayValues2.length; i++) { + Calendar cal2 = (Calendar)cal.clone(); + cal2.roll(Calendar.YEAR, i); + if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues2[i] || cal2.get(Calendar.MONTH) + != monthValues[i]) + errln("Rolling the year in 2/29/1996 up by " + i + " should have yielded " + + (monthValues[i] + 1) + "/" + dayValues2[i] + "/" + + (1996 + i) + ", but actually yielded " + + (cal2.get(Calendar.MONTH) + 1) + "/" + + cal2.get(Calendar.DAY_OF_MONTH) + "/" + (1996 + i) + "."); + } + + // Test rolling hour of day + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.roll(Calendar.HOUR_OF_DAY, -2); + int f = cal.get(Calendar.HOUR_OF_DAY); + if (f != 22) errln("Rolling HOUR_OF_DAY=0 delta=-2 gave " + f + " Wanted 22"); + cal.roll(Calendar.HOUR_OF_DAY, 5); + f = cal.get(Calendar.HOUR_OF_DAY); + if (f != 3) errln("Rolling HOUR_OF_DAY=22 delta=5 gave " + f + " Wanted 3"); + cal.roll(Calendar.HOUR_OF_DAY, 21); + f = cal.get(Calendar.HOUR_OF_DAY); + if (f != 0) errln("Rolling HOUR_OF_DAY=3 delta=21 gave " + f + " Wanted 0"); + + // Test rolling hour + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.roll(Calendar.HOUR, -2); + f = cal.get(Calendar.HOUR); + if (f != 10) errln("Rolling HOUR=0 delta=-2 gave " + f + " Wanted 10"); + cal.roll(Calendar.HOUR, 5); + f = cal.get(Calendar.HOUR); + if (f != 3) errln("Rolling HOUR=10 delta=5 gave " + f + " Wanted 3"); + cal.roll(Calendar.HOUR, 9); + f = cal.get(Calendar.HOUR); + if (f != 0) errln("Rolling HOUR=3 delta=9 gave " + f + " Wanted 0"); + } + + /* + * Confirm that multiple calls to Calendar.set() works correctly. + */ + public void Test4374886() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + + try { + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, 2001); + cal.set(Calendar.MONTH, Calendar.OCTOBER); + cal.set(Calendar.WEEK_OF_YEAR, 4); + cal.set(Calendar.DAY_OF_WEEK, 2); + + if (cal.get(Calendar.YEAR) != 2001 || + cal.get(Calendar.MONTH) != Calendar.JANUARY || + cal.get(Calendar.DATE) != 22 || + cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) { + errln("Failed : got " + cal.getTime() + ", expected Mon Jan 22, 2001"); + } + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + } +} + +//eof diff --git a/jdk/test/java/util/Calendar/FieldStateTest.java b/jdk/test/java/util/Calendar/FieldStateTest.java new file mode 100644 index 00000000000..caa6f219a24 --- /dev/null +++ b/jdk/test/java/util/Calendar/FieldStateTest.java @@ -0,0 +1,216 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4860664 4916815 4867075 + * @library /java/text/testlib + * @build Koyomi + * @run main FieldStateTest + * @summary Unit tests for internal fields states. + */ + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import static java.util.Calendar.*; + +public class FieldStateTest extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Locale.setDefault(Locale.US); + + new FieldStateTest().run(args); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + public void TestFieldState() { + Koyomi cal = new Koyomi(); + logln("Right after instantialtion:"); + if (!cal.checkAllSet()) { + errln(cal.getMessage()); + } + + logln("Set date to 2003/10/31 after the instantiation:"); + cal.set(2003, OCTOBER, 31); + // let cal calculate the time + cal.getTime(); + // At this point, all fields have to be recalculated and + // happen to have the set-state from the instantiation. The + // three fields should have "externally set" and the rest of + // the fields have "computed". But we can't distinguish them + // outside the package. + if (!cal.checkAllSet()) { + errln(cal.getMessage()); + } + // Make sure that the correct date was produced. + if (!cal.checkInternalDate(2003, OCTOBER, 31, FRIDAY)) { + errln(cal.getMessage()); + } + + logln("Change to Monday of the week, which is 2003/10/27:"); + cal.set(DAY_OF_WEEK, MONDAY); + cal.getTime(); + if (!cal.checkDate(2003, OCTOBER, 27)) { + errln(cal.getMessage()); + } + + // The same operation didn't work after calling clear() before + // 1.5 because the set-state was just depends on its previous + // operations. After the instantiation, all the fields are set + // to "computed". But after calling clear(), the state becomes + // "unset". + logln("Set to 2003/10/31 after clear():"); + cal.clear(); + cal.set(2003, OCTOBER, 31); + cal.getTime(); + cal.set(DAY_OF_WEEK, MONDAY); + if (!cal.checkDate(2003, OCTOBER, 27, MONDAY)) { + errln(cal.getMessage()); + } + + logln("Set to 2003/10/31 after clear(), then to the 51st week of year (12/19):"); + cal.clear(); + cal.set(2003, OCTOBER, 31); + cal.getTime(); + cal.set(WEEK_OF_YEAR, 51); + if (!cal.checkFieldValue(WEEK_OF_YEAR, 51)) { + errln(cal.getMessage()); + } + if (!cal.checkDate(2003, DECEMBER, 19, FRIDAY)) { + errln(cal.getMessage()); + } + + logln("Set to 2003/10 Mon of 4th week (10/20: 43rd week of year, 293rd day):"); + cal.clear(); + cal.set(YEAR, 2003); + cal.set(MONTH, OCTOBER); + cal.set(DAY_OF_WEEK, MONDAY); + cal.set(WEEK_OF_MONTH, 4); + cal.getTime(); + if (!cal.checkFieldValue(DAY_OF_MONTH, 20)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(WEEK_OF_YEAR, 43)) { + errln(cal.getMessage()); + } + + logln("Set to 2003/10 Mon of 43rd week of year (10/20: 4th week of month, 293rd day):"); + cal.clear(); + cal.set(YEAR, 2003); + cal.set(DAY_OF_WEEK, MONDAY); + cal.set(WEEK_OF_YEAR, 43); + cal.getTime(); + if (!cal.checkDate(2003, OCTOBER, 20, MONDAY)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(WEEK_OF_MONTH, 4)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) { + errln(cal.getMessage()); + } + + logln("Set day of week to SUNDAY and date to 2003/10/31. " + + "Then, getTime and set week of year to 43."); + cal.setTime(new Date(2003-1990, OCTOBER, 31)); + cal.set(DAY_OF_WEEK, SUNDAY); + cal.set(2003, OCTOBER, 31); // 2003/10/31 is Friday. + cal.set(ZONE_OFFSET, 0); + cal.set(DST_OFFSET, 0); + + // This call should change the day of week to FRIDAY since the + // selected field combination should be YEAR, MONTH and + // DAY_OF_MONTH. The other calendar fields must be normalized + // with the selected date. + cal.getTime(); + cal.set(WEEK_OF_YEAR, 43); + if (!cal.checkDate(2003, OCTOBER, 24, FRIDAY)) { + errln(cal.getMessage()); + } + } + + /* + * 4916815: REGRESSION: Problem with java.util.Calendar VM 1.4.2-b28 + */ + public void Test4916815() { + logln("Set date to 2003/9/26 (Fri). Roll to Aug and back to Sep. "+ + "Set dayofweek to Sunday which should be 2003/9/21."); + Koyomi cal = new Koyomi(); + cal.clear(); + // 2003/9/26 (Fri) + cal.set(2003, SEPTEMBER, 26); + // Go to August then back to September + cal.roll(MONTH, -1); + cal.roll(MONTH, +1); + Koyomi cal2 = (Koyomi) cal.clone(); + cal2.getTime(); + // Sunday of the week should be 2003/9/21. + cal2.set(DAY_OF_WEEK, SUNDAY); + if (!cal2.checkDate(2003, SEPTEMBER, 21, SUNDAY)) { + errln(cal2.getMessage()); + } + } + + /* + * 4867075: GregorianCalendar get() calls complete() internally, should getTime() too? + */ + public void Test4867075() { + Koyomi cal = new Koyomi(Locale.US); + cal.clear(); + cal.set(YEAR, 2004); + cal.set(WEEK_OF_YEAR, 1); + checkDate(cal, SUNDAY, 2003, DECEMBER, 28); + checkDate(cal, MONDAY, 2003, DECEMBER, 29); + checkDate(cal, TUESDAY, 2003, DECEMBER, 30); + checkDate(cal, WEDNESDAY, 2003, DECEMBER, 31); + checkDate(cal, THURSDAY, 2004, JANUARY, 1); + checkDate(cal, FRIDAY, 2004, JANUARY, 2); + checkDate(cal, SATURDAY, 2004, JANUARY, 3); + } + + private void checkDate(Koyomi cal, int dayOfWeek, + int expectedYear, int expectedMonth, int expectedDayOfMonth) { + cal.set(DAY_OF_WEEK, dayOfWeek); + cal.getTime(); + if (!cal.checkInternalDate(expectedYear, expectedMonth, expectedDayOfMonth, dayOfWeek)) { + errln(cal.getMessage()); + } + } + + static String toHexString(int x) { + return Integer.toHexString(x); + } +} diff --git a/jdk/test/java/util/Calendar/GregorianCutoverTest.java b/jdk/test/java/util/Calendar/GregorianCutoverTest.java new file mode 100644 index 00000000000..bd743ae19f6 --- /dev/null +++ b/jdk/test/java/util/Calendar/GregorianCutoverTest.java @@ -0,0 +1,324 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4359204 4928615 4743587 4956232 6459836 6549953 + * @library /java/text/testlib + * @build Koyomi + * @run main GregorianCutoverTest + * @summary Unit tests related to the Gregorian cutover support. + */ + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import static java.util.GregorianCalendar.*; + +public class GregorianCutoverTest extends IntlTest { + + public static void main(String[] args) throws Exception { + TimeZone tz = TimeZone.getDefault(); + Locale lc = Locale.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Locale.setDefault(Locale.US); + + new GregorianCutoverTest().run(args); + } finally { + TimeZone.setDefault(tz); + Locale.setDefault(lc); + } + } + + /** + * 4359204: GregorianCalendar.get(cal.DAY_OF_YEAR) is inconsistent for year 1582 + */ + public void Test4359204() { + Koyomi cal = new Koyomi(); + + cal.set(1582, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + cal.set(1582, OCTOBER, 1); + checkContinuity(cal, WEEK_OF_MONTH); + + // JCK tests the cutover date 1970-1-1 (Epoch) + cal.setGregorianChange(new Date(0)); + cal.set(1969, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + cal.set(1969, DECEMBER, 1); + checkContinuity(cal, WEEK_OF_MONTH); + cal.set(1970, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + + // Use large date (year >= 50000) + cal.setGregorianChange(new Date(50000-1900, JANUARY, 20)); + cal.set(49998, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + cal.set(49999, JANUARY, 1); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + cal.set(50000, JANUARY, 20); + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + + // Handling of "overlapping" dates may still be incorrect as + // of 1.5. Also, there's no way to disambiguate "overlapping" + // dates. + // millis=-112033929600000: date=-1581-10-15T00:00:00.000Z + cal.setGregorianChange(new Date(-112033929600000L)); + cal.set(ERA, AD); + cal.set(-1581, JANUARY, 1); + // The year should have 379 days. + checkContinuity(cal, DAY_OF_YEAR); + checkContinuity(cal, WEEK_OF_YEAR); + + logln("Default cutover"); + cal = new Koyomi(); + cal.set(1582, OCTOBER, 1); + logln(" roll --DAY_OF_MONTH from 1582/10/01"); + cal.roll(DAY_OF_MONTH, -1); + if (!cal.checkDate(1582, OCTOBER, 31)) { + errln(cal.getMessage()); + } + logln(" roll DAY_OF_MONTH+10 from 1582/10/31"); + cal.roll(DAY_OF_MONTH, +10); + if (!cal.checkDate(1582, OCTOBER, 20)) { + errln(cal.getMessage()); + } + logln(" roll DAY_OF_MONTH-10 from 1582/10/20"); + cal.roll(DAY_OF_MONTH, -10); + if (!cal.checkDate(1582, OCTOBER, 31)) { + errln(cal.getMessage()); + } + logln(" roll back one day further"); + cal.roll(DAY_OF_MONTH, +1); + if (!cal.checkDate(1582, OCTOBER, 1)) { + errln(cal.getMessage()); + } + + // should handle the gap between 1969/12/22 (Julian) to 1970/1/5 (Gregorian) + logln("Cutover date is 1970/1/5"); + cal.setGregorianChange(new Date(1970-1900, JANUARY, 5)); + cal.set(ERA, AD); + cal.set(YEAR, 1970); + logln(" Set DAY_OF_YEAR to the 28th day of 1970"); + cal.set(DAY_OF_YEAR, 28); + if (!cal.checkDate(1970, FEBRUARY, 1)) { + errln(cal.getMessage()); + } + if (!cal.checkFieldValue(WEEK_OF_YEAR, 5)) { + errln(cal.getMessage()); + } + logln(" 1969/12/22 should be the 356th day of the year."); + cal.set(1969, DECEMBER, 22); + if (!cal.checkFieldValue(DAY_OF_YEAR, 356)) { + errln(cal.getMessage()); + } + logln(" Set DAY_OF_YEAR to autual maximum."); + int actualMaxDayOfYear = cal.getActualMaximum(DAY_OF_YEAR); + if (actualMaxDayOfYear != 356) { + errln("actual maximum of DAY_OF_YEAR: got " + actualMaxDayOfYear + ", expected 356"); + } + cal.set(DAY_OF_YEAR, actualMaxDayOfYear); + if (!cal.checkDate(1969, DECEMBER, 22)) { + errln(cal.getMessage()); + } + cal.set(1969, DECEMBER, 22); + cal.roll(DAY_OF_YEAR, +1); + logln(" Set to 1969/12/22 and roll DAY_OF_YEAR++"); + if (!cal.checkDate(1969, JANUARY, 1)) { + errln(cal.getMessage()); + } + logln(" 1970/1/5 should be the first day of the year."); + cal.set(1970, JANUARY, 5); + if (!cal.checkFieldValue(DAY_OF_YEAR, 1)) { + errln(cal.getMessage()); + } + logln(" roll --DAY_OF_MONTH from 1970/1/5"); + cal.roll(DAY_OF_MONTH, -1); + if (!cal.checkDate(1970, JANUARY, 31)) { + errln(cal.getMessage()); + } + logln(" roll back one day of month"); + cal.roll(DAY_OF_MONTH, +1); + if (!cal.checkDate(1970, JANUARY, 5)) { + errln(cal.getMessage()); + } + + // Test "missing" dates in non-lenient. + cal = new Koyomi(); // new instance for the default cutover + cal.setLenient(false); + try { + // the next day of 1582/10/4 (Julian) is 1582/10/15 (Gregorian) + logln("1582/10/10 doesn't exit with the default cutover."); + cal.set(1582, OCTOBER, 10); + cal.getTime(); + errln(" Didn't throw IllegalArgumentException in non-lenient."); + } catch (IllegalArgumentException e) { + } + } + + private void checkContinuity(Koyomi cal, int field) { + cal.getTime(); + logln(Koyomi.getFieldName(field) + " starting on " + cal.toDateString()); + int max = cal.getActualMaximum(field); + for (int i = 1; i <= max; i++) { + logln(i + " " + cal.toDateString()); + if (!cal.checkFieldValue(field, i)) { + errln(" " + cal.toDateString() + ":\t" + cal.getMessage()); + } + cal.add(field, +1); + } + } + + /** + * 4928615: GregorianCalendar returns wrong dates after setGregorianChange + */ + public void Test4928615() { + Koyomi cal = new Koyomi(); + logln("Today is 2003/10/1 Gregorian."); + Date x = new Date(2003-1900, 10-1, 1); + cal.setTime(x); + + logln(" Changing the cutover date to yesterday..."); + cal.setGregorianChange(new Date(x.getTime() - (24*3600*1000))); + if (!cal.checkDate(2003, OCTOBER, 1)) { + errln(" " + cal.getMessage()); + } + logln(" Changing the cutover date to tomorrow..."); + cal.setGregorianChange(new Date(x.getTime() + (24*3600*1000))); + if (!cal.checkDate(2003, SEPTEMBER, 18)) { + errln(" " + cal.getMessage()); + } + } + + /** + * 4743587: GregorianCalendar.getLeastMaximum() returns wrong values + */ + public void Test4743587() { + Koyomi cal = new Koyomi(); + Koyomi cal2 = (Koyomi) cal.clone(); + logln("getLeastMaximum should handle cutover year.\n" + +" default cutover date"); + if (!cal.checkLeastMaximum(DAY_OF_YEAR, 365-10)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkLeastMaximum(WEEK_OF_YEAR, 52-((10+6)/7))) { + errln(" " + cal.getMessage()); + } + // Corrected for 4956232 + if (!cal.checkLeastMaximum(DAY_OF_MONTH, 28)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkLeastMaximum(WEEK_OF_MONTH, 3)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkLeastMaximum(DAY_OF_WEEK_IN_MONTH, 3)) { + errln(" " + cal.getMessage()); + } + // make sure that getLeastMaximum calls didn't affect the date + if (!cal.equals(cal2)) { + errln(" getLeastMaximum calls modified the object."); + } + if (!cal.checkGreatestMinimum(DAY_OF_MONTH, 1)) { + errln(" " + cal.getMessage()); + } + + logln(" changing the date to 1582/10/20 for actual min/max tests"); + cal.set(1582, OCTOBER, 20); + if (!cal.checkActualMinimum(DAY_OF_MONTH, 1)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkActualMaximum(DAY_OF_MONTH, 31)) { + errln(" " + cal.getMessage()); + } + + cal = new Koyomi(); + logln("Change the cutover date to 1970/1/5."); + cal.setGregorianChange(new Date(1970-1900, 0, 5)); + if (!cal.checkLeastMaximum(DAY_OF_YEAR, 356)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkLeastMaximum(DAY_OF_MONTH, 22)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkGreatestMinimum(DAY_OF_MONTH, 5)) { + errln(" " + cal.getMessage()); + } + cal.set(1970, JANUARY, 10); + if (!cal.checkActualMinimum(DAY_OF_MONTH, 5)) { + errln(" " + cal.getMessage()); + } + if (!cal.checkActualMaximum(DAY_OF_MONTH, 31)) { + errln(" " + cal.getMessage()); + } + } + + /** + * 6459836: (cal) GregorianCalendar set method provides wrong result + */ + public void Test6459836() { + int hour = 13865672; + Koyomi gc1 = new Koyomi(); + gc1.clear(); + gc1.set(1, gc1.JANUARY, 1, 0, 0, 0); + gc1.set(gc1.HOUR_OF_DAY, hour); + if (!gc1.checkDate(1582, gc1.OCTOBER, 4)) { + errln("test case 1: " + gc1.getMessage()); + } + gc1.clear(); + gc1.set(1, gc1.JANUARY, 1, 0, 0, 0); + gc1.set(gc1.HOUR_OF_DAY, hour + 24); + if (!gc1.checkDate(1582, gc1.OCTOBER, 15)) { + errln("test case 2: " + gc1.getMessage()); + } + } + + /** + * 6549953 (cal) WEEK_OF_YEAR and DAY_OF_YEAR calculation problems around Gregorian cutover + */ + public void Test6549953() { + Koyomi cal = new Koyomi(); + + cal.set(YEAR, 1582); + cal.set(WEEK_OF_YEAR, 42); + cal.set(DAY_OF_WEEK, FRIDAY); + cal.checkFieldValue(WEEK_OF_YEAR, 42); + cal.checkFieldValue(DAY_OF_WEEK, FRIDAY); + if (!cal.checkDate(1582, OCTOBER, 29)) { + errln(cal.getMessage()); + } + cal.clear(); + cal.set(1582, OCTOBER, 1); + cal.set(DAY_OF_YEAR, 292); + if (!cal.checkDate(1582, OCTOBER, 29)) { + errln(cal.getMessage()); + } + } +} diff --git a/jdk/test/java/util/Calendar/JulianTest.java b/jdk/test/java/util/Calendar/JulianTest.java new file mode 100644 index 00000000000..bd7105bce89 --- /dev/null +++ b/jdk/test/java/util/Calendar/JulianTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 5029449 + * @summary Tests for the Julian calendar system (before the Gregorian cutover) + * @library /java/text/testlib + */ + +import static java.util.GregorianCalendar.*; + +public class JulianTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new JulianTest().run(args); + } + + /* + * 5029449: Regression: GregorianCalendar produces wrong Julian calendar dates in BC 1 + */ + public void Test5029449() { + Koyomi cal = new Koyomi(); + cal.clear(); + cal.set(1, JANUARY, 0); + // Date should be BC 1/12/31 + if (!cal.checkFieldValue(ERA, BC) + || !cal.checkDate(1, DECEMBER, 31)) { + errln(cal.getMessage()); + } + } +} diff --git a/jdk/test/java/util/Calendar/Koyomi.java b/jdk/test/java/util/Calendar/Koyomi.java new file mode 100644 index 00000000000..8eec03b5de4 --- /dev/null +++ b/jdk/test/java/util/Calendar/Koyomi.java @@ -0,0 +1,289 @@ +/* + * 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 static java.util.Calendar.*; + +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + * GregorianCalendar subclass for testing. + */ +public class Koyomi extends GregorianCalendar { + static final String[] FIELD_NAMES = { + "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH", + "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", + "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET", + "DST_OFFSET" + }; + + static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1; + + public Koyomi() { + } + + public Koyomi(TimeZone tz) { + super(tz); + } + + public Koyomi(Locale loc) { + super(loc); + } + + public Koyomi(TimeZone tz, Locale loc) { + super(tz, loc); + } + + @Override + public void computeTime() { + super.computeTime(); + } + + @Override + public void computeFields() { + super.computeFields(); + } + + @Override + public void complete() { + super.complete(); + } + + static String getFieldName(int field) { + return FIELD_NAMES[field]; + } + + String toDateString() { + StringBuilder sb = new StringBuilder(); + sb.append(internalGet(ERA) == 0 ? "BCE " : ""); + sb.append(internalGet(YEAR)).append('-'); + sb.append(internalGet(MONTH)+1).append('-'); + sb.append(internalGet(DAY_OF_MONTH)); + return sb.toString(); + } + + String toTimeString() { + StringBuilder sb = new StringBuilder(); + sb.append(internalGet(HOUR_OF_DAY)).append(':'); + sb.append(internalGet(MINUTE)).append(':'); + sb.append(internalGet(SECOND)).append('.'); + int ms = internalGet(MILLISECOND); + if (ms < 100) { + sb.append('0'); + if (ms < 10) { + sb.append('0'); + } + } + sb.append(ms); + int offset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); + offset /= 60000; + offset = (offset/60) * 100 + (offset%60); + if (offset >= 0) { + sb.append('+'); + } else { + sb.append('-'); + offset = -offset; + } + if (offset < 1000) { + sb.append('0'); + if (offset < 100) { + sb.append('0'); + } + } + sb.append(offset); + return sb.toString(); + } + + String toDateTimeString() { + return toDateString() + "T" + toTimeString(); + } + + StringBuilder msg = new StringBuilder(); + + void initTest() { + msg = new StringBuilder(); + } + + String getMessage() { + String s = msg.toString(); + msg = new StringBuilder(); + return " " + s; + } + + void setMessage(String msg) { + this.msg = new StringBuilder(msg); + } + + void appendMessage(String msg) { + this.msg.append(msg); + } + + boolean getStatus() { + return msg.length() == 0; + } + + int getSetStateFields() { + int mask = 0; + for (int i = 0; i < FIELD_COUNT; i++) { + if (isSet(i)) { + mask |= 1 << i; + } + } + return mask; + } + + int[] getFields() { + int[] fds = new int[fields.length]; + System.arraycopy(fields, 0, fds, 0, fds.length); + return fds; + } + + boolean checkAllSet() { + initTest(); + for (int i = 0; i < FIELD_COUNT; i++) { + checkFieldState(i, true); + } + return getStatus(); + } + + boolean checkInternalDate(int year, int month, int dayOfMonth) { + initTest(); + checkInternalFieldValue(YEAR, year); + checkInternalFieldValue(MONTH, month); + checkInternalFieldValue(DAY_OF_MONTH, dayOfMonth); + return getStatus(); + } + + boolean checkInternalDate(int year, int month, int dayOfMonth, int dayOfWeek) { + initTest(); + checkInternalFieldValue(YEAR, year); + checkInternalFieldValue(MONTH, month); + checkInternalFieldValue(DAY_OF_MONTH, dayOfMonth); + checkInternalFieldValue(DAY_OF_WEEK, dayOfWeek); + return getStatus(); + } + + boolean checkActualMaximum(int field, int expectedValue) { + int val; + if ((val = getActualMaximum(field)) != expectedValue) { + appendMessage("getActualMaximum("+FIELD_NAMES[field]+"): got " + val + + " expected " + expectedValue); + } + return getStatus(); + } + + boolean checkLeastMaximum(int field, int expectedValue) { + int val; + if ((val = getLeastMaximum(field)) != expectedValue) { + appendMessage("getLeastMaximum("+FIELD_NAMES[field]+"): got " + val + + " expected " + expectedValue); + } + return getStatus(); + } + + boolean checkActualMinimum(int field, int expectedValue) { + int val; + if ((val = getActualMinimum(field)) != expectedValue) { + appendMessage("getActualMinimum("+FIELD_NAMES[field]+"): got " + val + + " expected " + expectedValue); + } + return getStatus(); + } + + boolean checkGreatestMinimum(int field, int expectedValue) { + int val; + if ((val = getGreatestMinimum(field)) != expectedValue) { + appendMessage("getGreatestMinimum("+FIELD_NAMES[field]+"): got " + val + + " expected " + expectedValue); + } + return getStatus(); + } + + boolean checkDate(int year, int month, int dayOfMonth) { + initTest(); + checkFieldValue(YEAR, year); + checkFieldValue(MONTH, month); + checkFieldValue(DAY_OF_MONTH, dayOfMonth); + return getStatus(); + } + + boolean checkDate(int year, int month, int dayOfMonth, int dayOfWeek) { + initTest(); + checkFieldValue(YEAR, year); + checkFieldValue(MONTH, month); + checkFieldValue(DAY_OF_MONTH, dayOfMonth); + checkFieldValue(DAY_OF_WEEK, dayOfWeek); + return getStatus(); + } + + boolean checkDateTime(int year, int month, int dayOfMonth, + int hourOfDay, int minute, int second, int ms) { + initTest(); + checkFieldValue(YEAR, year); + checkFieldValue(MONTH, month); + checkFieldValue(DAY_OF_MONTH, dayOfMonth); + checkFieldValue(HOUR_OF_DAY, hourOfDay); + checkFieldValue(MINUTE, minute); + checkFieldValue(SECOND, second); + checkFieldValue(MILLISECOND, ms); + return getStatus(); + } + + boolean checkTime(int hourOfDay, int minute, int second, int ms) { + initTest(); + checkFieldValue(HOUR_OF_DAY, hourOfDay); + checkFieldValue(MINUTE, minute); + checkFieldValue(SECOND, second); + checkFieldValue(MILLISECOND, ms); + return getStatus(); + } + + boolean checkFieldState(int field, boolean expectedState) { + if (isSet(field) != expectedState) { + appendMessage(FIELD_NAMES[field] + " state is not " + expectedState + "; "); + return false; + } + return true; + } + + boolean checkFieldValue(int field, int expectedValue) { + int val; + if ((val = get(field)) != expectedValue) { + appendMessage("get(" + FIELD_NAMES[field] + "): got " + val + + ", expected " + expectedValue + "; "); + return false; + } + return true; + } + + boolean checkInternalFieldValue(int field, int expectedValue) { + int val; + if ((val = internalGet(field)) != expectedValue) { + appendMessage("internalGet(" + FIELD_NAMES[field] + "): got " + val + + ", expected " + expectedValue + "; "); + return false; + } + return true; + } +} diff --git a/jdk/test/java/util/Calendar/Limit.java b/jdk/test/java/util/Calendar/Limit.java new file mode 100644 index 00000000000..1ab0e172dc8 --- /dev/null +++ b/jdk/test/java/util/Calendar/Limit.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.*; +import java.text.*; + +/** + * Test GregorianCalendar limits, which should not exist. + * @test + * @bug 4056585 + * @summary Make sure that GregorianCalendar works far in the past and future. + * @author Alan Liu + */ +public class Limit { + static final long ONE_DAY = 24*60*60*1000L; + + public static void main(String args[]) throws Exception { + GregorianCalendar c = new GregorianCalendar(); + DateFormat fmt = new SimpleDateFormat("EEEE, MMMM dd, yyyy G", Locale.US); + long bigMillis = 300000000000000L; + + try { + // We check two things: + // 1. That handling millis in the range of +/- bigMillis works. + // bigMillis is a value that used to blow up. + // 2. The round-trip format/parse works in these extreme areas. + c.setTime(new Date(-bigMillis)); + String s = fmt.format(c.getTime()); + Date d = fmt.parse(s); + if (Math.abs(d.getTime() + bigMillis) >= ONE_DAY) { + throw new Exception(s + " != " + fmt.format(d)); + } + + c.setTime(new Date(+bigMillis)); + s = fmt.format(c.getTime()); + d = fmt.parse(s); + if (Math.abs(d.getTime() - bigMillis) >= ONE_DAY) { + throw new Exception(s + " != " + fmt.format(d)); + } + } catch (IllegalArgumentException | ParseException e) { + throw e; + } + } +} diff --git a/jdk/test/java/util/Calendar/NonLenientTest.java b/jdk/test/java/util/Calendar/NonLenientTest.java new file mode 100644 index 00000000000..6c42c594932 --- /dev/null +++ b/jdk/test/java/util/Calendar/NonLenientTest.java @@ -0,0 +1,221 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4147269 4266783 4726030 + * @summary Make sure that validation is adequate in non-lenient mode. + * @library /java/text/testlib + */ + +import java.util.*; + +import static java.util.Calendar.*; + +public class NonLenientTest extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale reservedLocale = Locale.getDefault(); + TimeZone reservedTimeZone = TimeZone.getDefault(); + try { + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + new NonLenientTest().run(args); + } finally { + // restore the reserved locale and time zone + Locale.setDefault(reservedLocale); + TimeZone.setDefault(reservedTimeZone); + } + } + + public void TestValidationInNonLenient() { + Koyomi cal = getNonLenient(); + + // 2003 isn't a leap year. + cal.set(2003, FEBRUARY, 29); + validate(cal, "2003/2/29"); + + // October has only 31 days. + cal.set(2003, OCTOBER, 32); + validate(cal, "2003/10/32"); + + // 2003/10/31 is Friday. + cal.set(2003, OCTOBER, 31); + cal.set(DAY_OF_WEEK, SUNDAY); + validate(cal, "2003/10/31 SUNDAY"); + + // 2003/10/31 is the 304th day of the year. + cal.clear(); + cal.set(DAY_OF_YEAR, 1); + cal.set(2003, OCTOBER, 31); + validate(cal, "2003/10/31 DAY_OF_YEAR=1"); + + // 2003/10 isn't the 1st week of the year. + cal.clear(); + cal.set(YEAR, 2003); + cal.set(WEEK_OF_YEAR, 1); + cal.set(MONTH, OCTOBER); + validate(cal, "2003/10 WEEK_OF_YEAR=1"); + + // The 1st week of 2003 doesn't have Monday. + cal.clear(); + cal.set(YEAR, 2003); + cal.set(WEEK_OF_YEAR, 1); + cal.set(DAY_OF_WEEK, MONDAY); + validate(cal, "2003 WEEK_OF_YEAR=1 MONDAY."); + + // 2003 has 52 weeks. + cal.clear(); + cal.set(YEAR, 2003); + cal.set(WEEK_OF_YEAR, 53); + cal.set(DAY_OF_WEEK, WEDNESDAY); + validate(cal, "2003 WEEK_OF_YEAR=53"); + + /* + * These test cases assume incompatible behavior in Tiger as + * the result of the validation bug fixes. However, it looks + * like we have to allow applications to set ZONE_OFFSET and + * DST_OFFSET values to modify the time zone offsets given by + * a TimeZone. The definition of non-leniency for time zone + * offsets is somewhat vague. (See 6231602) + * + * The following test cases are now disabled. + + // America/Los_Angeles is GMT-08:00 + cal.clear(); + cal.set(2003, OCTOBER, 31); + cal.set(ZONE_OFFSET, 0); + validate(cal, "ZONE_OFFSET=0:00 in America/Los_Angeles"); + + // 2003/10/31 shouldn't be in DST. + cal.clear(); + cal.set(2003, OCTOBER, 31); + cal.set(DST_OFFSET, 60*60*1000); + validate(cal, "2003/10/31 DST_OFFSET=1:00 in America/Los_Angeles"); + + */ + } + + /** + * 4266783: java.util.GregorianCalendar: incorrect validation in non-lenient + */ + public void Test4266783() { + Koyomi cal = getNonLenient(); + // 2003/1 has up to 5 weeks. + cal.set(YEAR, 2003); + cal.set(MONTH, JANUARY); + cal.set(WEEK_OF_MONTH, 6); + cal.set(DAY_OF_WEEK, SUNDAY); + validate(cal, "6th Sunday in Jan 2003"); + } + + + /** + * 4726030: GregorianCalendar doesn't check invalid dates in non-lenient + */ + public void Test4726030() { + Koyomi cal = getNonLenient(); + // Default year is 1970 in GregorianCalendar which isn't a leap year. + cal.set(MONTH, FEBRUARY); + cal.set(DAY_OF_MONTH, 29); + validate(cal, "2/29 in the default year 1970"); + } + + /** + * 4147269: java.util.GregorianCalendar.computeTime() works wrong when lenient is false + */ + public void Test4147269() { + Koyomi calendar = getNonLenient(); + Date date = (new GregorianCalendar(1996,0,3)).getTime(); + + for (int field = 0; field < Calendar.FIELD_COUNT; field++) { + calendar.setTime(date); + int max = calendar.getActualMaximum(field); + int value = max+1; + calendar.set(field, value); + try { + calendar.computeTime(); // call method under test + errln("Test failed with field " + calendar.getFieldName(field) + + "\n\tdate before: " + date + + "\n\tdate after: " + calendar.getTime() + + "\n\tvalue: " + value + " (max = " + max +")"); + } catch (IllegalArgumentException e) { + } + } + + for (int field = 0; field < Calendar.FIELD_COUNT; field++) { + calendar.setTime(date); + int min = calendar.getActualMinimum(field); + int value = min-1; + calendar.set(field, value); + try { + calendar.computeTime(); // call method under test + errln("Test failed with field " + calendar.getFieldName(field) + + "\n\tdate before: " + date + + "\n\tdate after: " + calendar.getTime() + + "\n\tvalue: " + value + " (min = " + min +")"); + } catch (IllegalArgumentException e) { + } + } + } + + void validate(Koyomi cal, String desc) { + int[] originalFields = cal.getFields(); + int setFields = cal.getSetStateFields(); + + try { + cal.complete(); + errln(desc + " should throw IllegalArgumentException in non-lenient."); + } catch (IllegalArgumentException e) { + } + + // The code below will be executed with the -nothrow option + + // In non-lenient, calendar field values that have beeb set by + // user shouldn't be modified. + int[] afterFields = cal.getFields(); + for (int i = 0; i < Calendar.FIELD_COUNT; i++) { + if (cal.isSet(i) && originalFields[i] != afterFields[i]) { + errln(" complete() modified fields[" + cal.getFieldName(i) + "] got " + + afterFields[i] + ", expected " + originalFields[i]); + } + } + // In non-lenient, set state of fields shouldn't be modified. + int afterSetFields = cal.getSetStateFields(); + if (setFields != afterSetFields) { + errln(" complate() modified set states: before 0x" + toHex(setFields) + + ", after 0x"+ toHex(afterSetFields)); + } + } + + static Koyomi getNonLenient() { + Koyomi cal = new Koyomi(); + cal.clear(); + cal.setLenient(false); + return cal; + } + + static String toHex(int x) { + return Integer.toHexString(x); + } +} diff --git a/jdk/test/java/util/Calendar/ResolutionTest.java b/jdk/test/java/util/Calendar/ResolutionTest.java new file mode 100644 index 00000000000..98356131b0a --- /dev/null +++ b/jdk/test/java/util/Calendar/ResolutionTest.java @@ -0,0 +1,111 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6452848 + * @summary Make sure that the resolution of (WEKK_OF_MONTH + + * DAY_OF_WEEK) and (DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK) works as + * specified in the API. + * @key randomness + */ + +import java.util.*; +import static java.util.Calendar.*; + +public class ResolutionTest { + static Random rand = new Random(); + + public static void main(String[] args) { + for (int year = 1995; year < 2011; year++) { + for (int month = JANUARY; month <= DECEMBER; month++) { + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + test(year, month, dow); + } + } + } + } + + static void test(int year, int month, int dow) { + Calendar cal = new GregorianCalendar(year, month, 1); + int max = cal.getActualMaximum(DAY_OF_MONTH); + ArrayList list = new ArrayList(); + for (int d = 1; d <= max; d++) { + cal.clear(); + cal.set(year, month, d); + if (cal.get(DAY_OF_WEEK) == dow) { + list.add(d); + } + } + for (int i = 0; i < 100; i++) { + int nth = rand.nextInt(list.size()); // 0-based + int day = list.get(nth); + nth++; // 1-based + testDayOfWeekInMonth(year, month, nth, dow, day); + } + + // Put WEEK_OF_MONTH-DAY_OF_MONTH pairs + list = new ArrayList(); + for (int d = 1; d <= max; d++) { + cal.clear(); + cal.set(year, month, d); + if (cal.get(DAY_OF_WEEK) == dow) { + list.add(cal.get(WEEK_OF_MONTH)); + list.add(d); + } + } + for (int i = 0; i < list.size(); i++) { + int nth = list.get(i++); + int day = list.get(i); + testWeekOfMonth(year, month, nth, dow, day); + } + } + + static Koyomi cal = new Koyomi(); + + static void testDayOfWeekInMonth(int year, int month, int nth, int dow, int expected) { + // don't call clear() here + cal.set(YEAR, year); + cal.set(MONTH, month); + // Set DAY_OF_WEEK_IN_MONTH before DAY_OF_WEEK + cal.set(DAY_OF_WEEK_IN_MONTH, nth); + cal.set(DAY_OF_WEEK, dow); + if (!cal.checkDate(year, month, expected)) { + throw new RuntimeException(String.format("DOWIM: year=%d, month=%d, nth=%d, dow=%d:%s%n", + year, month+1, nth, dow, cal.getMessage())); + } + } + + static void testWeekOfMonth(int year, int month, int nth, int dow, int expected) { + // don't call clear() here + cal.set(YEAR, year); + cal.set(MONTH, month); + // Set WEEK_OF_MONTH before DAY_OF_WEEK + cal.set(WEEK_OF_MONTH, nth); + cal.set(DAY_OF_WEEK, dow); + if (!cal.checkDate(year, month, expected)) { + throw new RuntimeException(String.format("WOM: year=%d, month=%d, nth=%d, dow=%d:%s%n", + year, month+1, nth, dow, cal.getMessage())); + } + } +} diff --git a/jdk/test/java/util/Calendar/RollDayOfWeekTest.java b/jdk/test/java/util/Calendar/RollDayOfWeekTest.java new file mode 100644 index 00000000000..5b85016c311 --- /dev/null +++ b/jdk/test/java/util/Calendar/RollDayOfWeekTest.java @@ -0,0 +1,137 @@ +/* + * 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 5090555 5091805 + * @summary Make sure that rolling DAY_OF_WEEK stays in the same week + * around year boundaries. + * @run main/othervm RollDayOfWeekTest 5 5 + */ + +import java.util.*; + +import static java.util.Calendar.*; + +// Usage: java RollDayOfWeekTest [pastYears futureYears] +public class RollDayOfWeekTest { + public static void main(String[] args) { + int pastYears = 5, futureYears = 23; + if (args.length == 2) { + pastYears = Integer.parseInt(args[0]); + pastYears = Math.max(1, Math.min(pastYears, 5)); + futureYears = Integer.parseInt(args[1]); + futureYears = Math.max(1, Math.min(futureYears, 28)); + } + + System.out.printf("Test [%d .. %+d] year range.%n", -pastYears, futureYears); + Calendar cal = new GregorianCalendar(); + int year = cal.get(YEAR) - pastYears; + + // Use the all combinations of firstDayOfWeek and + // minimalDaysInFirstWeek values in the year range current + // year - pastYears to current year + futureYears. + for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) { + for (int mdifw = 1; mdifw <= 7; mdifw++) { + cal.clear(); + cal.setFirstDayOfWeek(fdw); + cal.setMinimalDaysInFirstWeek(mdifw); + cal.set(year, JANUARY, 1); + checkRoll(cal, futureYears); + } + } + + // testing roll from BCE to CE + year = -1; + for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) { + for (int mdifw = 1; mdifw <= 7; mdifw++) { + cal.clear(); + cal.setFirstDayOfWeek(fdw); + cal.setMinimalDaysInFirstWeek(mdifw); + cal.set(year, JANUARY, 1); + checkRoll(cal, 4); + } + } + } + + + static void checkRoll(Calendar cal, int years) { + Calendar cal2 = null, cal3 = null, prev = null; + // Check 28 years + for (int x = 0; x < (int)(365.2425*years); x++) { + cal2 = (Calendar) cal.clone(); + cal3 = (Calendar) cal.clone(); + + // roll foreword + for (int i = 0; i < 10; i++) { + prev = (Calendar) cal2.clone(); + cal2.roll(Calendar.DAY_OF_WEEK, +1); + roll(cal3, +1); + long t2 = cal2.getTimeInMillis(); + long t3 = cal3.getTimeInMillis(); + if (t2 != t3) { + System.err.println("prev: " + prev.getTime() + "\n" + prev); + System.err.println("cal2: " + cal2.getTime() + "\n" + cal2); + System.err.println("cal3: " + cal3.getTime() + "\n" + cal3); + throw new RuntimeException("+1: t2=" + t2 + ", t3=" + t3); + } + } + + // roll backward + for (int i = 0; i < 10; i++) { + prev = (Calendar) cal2.clone(); + cal2.roll(Calendar.DAY_OF_WEEK, -1); + roll(cal3, -1); + long t2 = cal2.getTimeInMillis(); + long t3 = cal3.getTimeInMillis(); + if (t2 != t3) { + System.err.println("prev: " + prev.getTime() + "\n" + prev); + System.err.println("cal2: " + cal2.getTime() + "\n" + cal2); + System.err.println("cal3: " + cal3.getTime() + "\n" + cal3); + throw new RuntimeException("-1: t2=" + t2 + ", t3=" + t3); + } + } + cal.add(DAY_OF_YEAR, +1); + } + } + + // Another way to roll within the same week. + static void roll(Calendar cal, int n) { + int doy = cal.get(DAY_OF_YEAR); + int diff = cal.get(DAY_OF_WEEK) - cal.getFirstDayOfWeek(); + if (diff < 0) { + diff += 7; + } + + // dow1: first day of the week + int dow1 = doy - diff; + n %= 7; + doy += n; + if (doy < dow1) { + doy += 7; + } else if (doy >= dow1 + 7) { + doy -= 7; + } + cal.set(DAY_OF_YEAR, doy); + } +} diff --git a/jdk/test/java/util/Calendar/StampOverflow.java b/jdk/test/java/util/Calendar/StampOverflow.java new file mode 100644 index 00000000000..fc10595c87f --- /dev/null +++ b/jdk/test/java/util/Calendar/StampOverflow.java @@ -0,0 +1,80 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4404619 6348819 + * @summary Make sure that Calendar doesn't cause nextStamp overflow. + */ + +import java.lang.reflect.*; +import java.util.*; +import static java.util.Calendar.*; + +// Calendar fails when turning negative to positive (zero), not +// positive to negative with nextStamp. If a negative value was set to +// nextStamp, it would fail even with the fix. So, there's no way to +// reproduce the symptom in a short time -- at leaset it would take a +// couple of hours even if we started with Integer.MAX_VALUE. So, this +// test case just checks that set() calls don't cause any nextStamp +// overflow. + +public class StampOverflow { + public static void main(String[] args) throws IllegalAccessException { + // Get a Field for "nextStamp". + Field nextstamp = null; + try { + nextstamp = Calendar.class.getDeclaredField("nextStamp"); + } catch (NoSuchFieldException e) { + throw new RuntimeException("implementation changed?", e); + } + + nextstamp.setAccessible(true); + + Calendar cal = new GregorianCalendar(); + int initialValue = nextstamp.getInt(cal); + // Set nextStamp to a very large number + nextstamp.setInt(cal, Integer.MAX_VALUE - 100); + + for (int i = 0; i < 1000; i++) { + invoke(cal); + int stampValue = nextstamp.getInt(cal); + // nextStamp must not be less than initialValue. + if (stampValue < initialValue) { + throw new RuntimeException("invalid nextStamp: " + stampValue); + } + } + } + + static void invoke(Calendar cal) { + cal.clear(); + cal.set(2000, NOVEMBER, 2, 0, 0, 0); + int y = cal.get(YEAR); + int m = cal.get(MONTH); + int d = cal.get(DAY_OF_MONTH); + if (y != 2000 || m != NOVEMBER || d != 2) { + throw new RuntimeException("wrong date produced (" + + y + "/" + (m+1) + "/" + d + ")"); + } + } +} diff --git a/jdk/test/java/util/Calendar/ZoneOffsets.java b/jdk/test/java/util/Calendar/ZoneOffsets.java new file mode 100644 index 00000000000..147df337497 --- /dev/null +++ b/jdk/test/java/util/Calendar/ZoneOffsets.java @@ -0,0 +1,231 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6231602 + * @summary Make sure that ZONE_OFFSET and/or DST_OFFSET setting is + * taken into account for time calculations. + */ + +import java.util.*; +import static java.util.GregorianCalendar.*; + +public class ZoneOffsets { + // This TimeZone always returns the dstOffset value. + private static class TestTimeZone extends TimeZone { + private int gmtOffset; + private int dstOffset; + + TestTimeZone(int gmtOffset, String id, int dstOffset) { + this.gmtOffset = gmtOffset; + setID(id); + this.dstOffset = dstOffset; + } + + public int getOffset(int era, int year, int month, int day, + int dayOfWeek, int milliseconds) { + return gmtOffset + dstOffset; + } + + public int getOffset(long date) { + return gmtOffset + dstOffset; + } + + public void setRawOffset(int offsetMillis) { + gmtOffset = offsetMillis; + } + + public int getRawOffset() { + return gmtOffset; + } + + public int getDSTSavings() { + return dstOffset; + } + + public boolean useDaylightTime() { + return dstOffset != 0; + } + + public boolean inDaylightTime(Date date) { + return dstOffset != 0; + } + + public String toString() { + return "TestTimeZone[" + getID() + ", " + gmtOffset + ", " + dstOffset + "]"; + } + } + + private static Locale[] locales = { + Locale.getDefault(), + new Locale("th", "TH"), + new Locale("ja", "JP", "JP"), + }; + + private static final int HOUR = 60 * 60 * 1000; + + private static int[][] offsets = { + { 0, 0 }, + { 0, HOUR }, + { 0, 2 * HOUR }, + { -8 * HOUR, 0 }, + { -8 * HOUR, HOUR }, + { -8 * HOUR, 2 * HOUR }, + { 9 * HOUR, 0 }, + { 9 * HOUR, HOUR }, + { 9 * HOUR, 2 * HOUR }, + }; + + public static void main(String[] args) { + for (int l = 0; l < locales.length; l++) { + Locale loc = locales[l]; + for (int i = 0; i < offsets.length; i++) { + test(loc, offsets[i][0], offsets[i][1]); + } + } + + // The test case in the bug report. + GregorianCalendar cal = new GregorianCalendar(); + cal.setLenient(false); + cal.setGregorianChange(new Date(Long.MIN_VALUE)); + cal.clear(); + cal.set(ZONE_OFFSET, 0); + cal.set(DST_OFFSET, 0); + cal.set(ERA, AD); + cal.set(2004, FEBRUARY, 3, 0, 0, 0); + cal.set(MILLISECOND, 0); + // The following line should not throw an IllegalArgumentException. + cal.getTime(); + } + + private static void test(Locale loc, int gmtOffset, int dstOffset) { + TimeZone tz1 = new TestTimeZone(gmtOffset, + "GMT" + (gmtOffset/HOUR) + "." + (dstOffset/HOUR), + dstOffset); + int someDifferentOffset = gmtOffset + 2 * HOUR; + TimeZone tz2 = new TestTimeZone(someDifferentOffset, + "GMT"+ (someDifferentOffset/HOUR) + "." + (dstOffset/HOUR), + dstOffset); + + int someDifferentDSTOffset = dstOffset == 2 * HOUR ? HOUR : dstOffset + HOUR; + TimeZone tz3 = new TestTimeZone(gmtOffset, + "GMT"+ (gmtOffset/HOUR) + "." + (someDifferentDSTOffset/HOUR), + someDifferentDSTOffset); + + // cal1 is the base line. + Calendar cal1 = Calendar.getInstance(tz1, loc); + cal1.clear(); + cal1.set(2005, MARCH, 11); + long t1 = cal1.getTime().getTime(); + int gmt = cal1.get(ZONE_OFFSET); + int dst = cal1.get(DST_OFFSET); + + // Test 8 cases with cal2. + Calendar cal2 = Calendar.getInstance(tz2, loc); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test1: set only ZONE_OFFSET + cal2.set(ZONE_OFFSET, gmtOffset); + if (t1 != cal2.getTime().getTime() || dst != cal2.get(DST_OFFSET)) { + error("Test1", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz3); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test2: set only DST_OFFSET + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime() || gmt != cal2.get(ZONE_OFFSET)) { + error("Test2", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz2); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test3: set both ZONE_OFFSET and DST_OFFSET + cal2.set(ZONE_OFFSET, gmtOffset); + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime()) { + error("Test3", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz3); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test4: set both ZONE_OFFSET and DST_OFFSET + cal2.set(ZONE_OFFSET, gmtOffset); + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime()) { + error("Test4", loc, cal2, gmtOffset, dstOffset, t1); + } + + // Test the same thing in non-lenient + cal2.setLenient(false); + + cal2.setTimeZone(tz2); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test5: set only ZONE_OFFSET in non-lenient + cal2.set(ZONE_OFFSET, gmtOffset); + if (t1 != cal2.getTime().getTime() || dst != cal2.get(DST_OFFSET)) { + error("Test5", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz3); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test6: set only DST_OFFSET in non-lenient + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime() || gmt != cal2.get(ZONE_OFFSET)) { + error("Test6", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz2); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test7: set both ZONE_OFFSET and DST_OFFSET in non-lenient + cal2.set(ZONE_OFFSET, gmtOffset); + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime()) { + error("Test7", loc, cal2, gmtOffset, dstOffset, t1); + } + + cal2.setTimeZone(tz3); + cal2.clear(); + cal2.set(2005, MARCH, 11); + // test8: set both ZONE_OFFSET and DST_OFFSET in non-lenient + cal2.set(ZONE_OFFSET, gmtOffset); + cal2.set(DST_OFFSET, dstOffset); + if (t1 != cal2.getTime().getTime()) { + error("Test8", loc, cal2, gmtOffset, dstOffset, t1); + } + } + + private static void error(String msg, Locale loc, Calendar cal2, int gmtOffset, int dstOffset, long t1) { + System.err.println(cal2); + throw new RuntimeException(msg + ": Locale=" + loc + + ", gmtOffset=" + gmtOffset + ", dstOffset=" + dstOffset + + ", cal1 time=" + t1 + ", cal2 time=" + cal2.getTime().getTime()); + } +} diff --git a/jdk/test/java/util/Calendar/bug4028518.java b/jdk/test/java/util/Calendar/bug4028518.java new file mode 100644 index 00000000000..982b93adc86 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4028518.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4028518 + * @summary Make sure cloned GregorianCalendar is unchanged by modifying its original. + */ + +import java.util.GregorianCalendar ; +import static java.util.Calendar.*; + +public class bug4028518 { + + public static void main(String[] args) + { + GregorianCalendar cal1 = new GregorianCalendar() ; + GregorianCalendar cal2 = (GregorianCalendar) cal1.clone() ; + + printdate(cal1, "cal1: ") ; + printdate(cal2, "cal2 - cloned(): ") ; + cal1.add(DAY_OF_MONTH, 1) ; + printdate(cal1, "cal1 after adding 1 day: ") ; + printdate(cal2, "cal2 should be unmodified: ") ; + if (cal1.get(DAY_OF_MONTH) == cal2.get(DAY_OF_MONTH)) { + throw new RuntimeException("cloned GregorianCalendar modified"); + } + } + + private static void printdate(GregorianCalendar cal, String string) + { + System.out.println(string + (cal.get(MONTH) + 1) + + "/" + cal.get(DAY_OF_MONTH) + + "/" + cal.get(YEAR)) ; + } +} diff --git a/jdk/test/java/util/Calendar/bug4100311.java b/jdk/test/java/util/Calendar/bug4100311.java new file mode 100644 index 00000000000..ef0f36ecbd2 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4100311.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4100311 + * @summary Make sure set(DAY_OF_YEAR, 1) works. + */ + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Date; + +public class bug4100311 +{ + @SuppressWarnings("deprecation") + public static void main(String args[]) + { + GregorianCalendar cal = new GregorianCalendar(); + cal.set(Calendar.YEAR, 1997); + cal.set(Calendar.DAY_OF_YEAR, 1); + Date d = cal.getTime(); // Should be Jan 1 + if (d.getMonth() != 0 || d.getDate() != 1) { + throw new RuntimeException("Date isn't Jan 1"); + } + } +} diff --git a/jdk/test/java/util/Calendar/bug4243802.java b/jdk/test/java/util/Calendar/bug4243802.java new file mode 100644 index 00000000000..1f3b910c1b3 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4243802.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4243802 + * @summary confirm that Calendar.setTimeInMillis() and + * getTimeInMillis() can be called from a user program. (They used to + * be protected methods.) + * @library /java/text/testlib + */ + +import java.util.*; + +public class bug4243802 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4243802().run(args); + } + + /** + * 4243802: RFE: need way to set the date of a calendar without a Date object + */ + public void Test4243802() { + TimeZone saveZone = TimeZone.getDefault(); + Locale saveLocale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + + Calendar cal1 = Calendar.getInstance(); + Calendar cal2 = Calendar.getInstance(); + + cal1.clear(); + cal2.clear(); + cal1.set(2001, Calendar.JANUARY, 25, 1, 23, 45); + cal2.setTimeInMillis(cal1.getTimeInMillis()); + if ((cal2.get(Calendar.YEAR) != 2001) || + (cal2.get(Calendar.MONTH) != Calendar.JANUARY) || + (cal2.get(Calendar.DAY_OF_MONTH) != 25) || + (cal2.get(Calendar.HOUR_OF_DAY) != 1) || + (cal2.get(Calendar.MINUTE) != 23) || + (cal2.get(Calendar.SECOND) != 45) || + (cal2.get(Calendar.MILLISECOND) != 0)) { + errln("Failed: expected 1/25/2001 1:23:45.000" + + ", got " + (cal2.get(Calendar.MONTH)+1) + "/" + + cal2.get(Calendar.DAY_OF_MONTH) +"/" + + cal2.get(Calendar.YEAR) + " " + + cal2.get(Calendar.HOUR_OF_DAY) + ":" + + cal2.get(Calendar.MINUTE) + ":" + + cal2.get(Calendar.SECOND) + "." + + toMillis(cal2.get(Calendar.MILLISECOND))); + } + logln("Passed."); + } + finally { + Locale.setDefault(saveLocale); + TimeZone.setDefault(saveZone); + } + } + + private String toMillis(int m) { + StringBuffer sb = new StringBuffer(); + if (m < 100) { + sb.append('0'); + } + if (m < 10) { + sb.append('0'); + } + sb.append(m); + return sb.toString(); + } +} diff --git a/jdk/test/java/util/Calendar/bug4316678.java b/jdk/test/java/util/Calendar/bug4316678.java new file mode 100644 index 00000000000..8ae6bbc294f --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4316678.java @@ -0,0 +1,69 @@ +/* + * 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 java.io.*; +import java.util.*; +import java.text.*; + +/** + * @test + * @bug 4316678 + * @summary test that Calendar's Serializasion works correctly. + * @library /java/text/testlib + */ +public class bug4316678 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4316678().run(args); + } + + public void Test4316678() throws Exception { + GregorianCalendar gc1; + GregorianCalendar gc2; + TimeZone saveZone = TimeZone.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + + gc1 = new GregorianCalendar(2000, Calendar.OCTOBER, 10); + try (ObjectOutputStream out + = new ObjectOutputStream(new FileOutputStream("bug4316678.ser"))) { + out.writeObject(gc1); + } + + try (ObjectInputStream in + = new ObjectInputStream(new FileInputStream("bug4316678.ser"))) { + gc2 = (GregorianCalendar)in.readObject(); + } + + gc1.set(Calendar.DATE, 16); + gc2.set(Calendar.DATE, 16); + if (!gc1.getTime().equals(gc2.getTime())) { + errln("Invalid Time :" + gc2.getTime() + + ", expected :" + gc1.getTime()); + } + } finally { + TimeZone.setDefault(saveZone); + } + } +} diff --git a/jdk/test/java/util/Calendar/bug4372743.java b/jdk/test/java/util/Calendar/bug4372743.java new file mode 100644 index 00000000000..1800ebc002a --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4372743.java @@ -0,0 +1,133 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4372743 + * @summary test that checks transitions of ERA and YEAR which are caused by add(MONTH). + * @library /java/text/testlib + */ + +import java.io.*; +import java.util.*; +import java.text.*; + +import static java.util.GregorianCalendar.*; + +public class bug4372743 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4372743().run(args); + } + + private int[][] data = { + {AD, 2, MARCH}, + {AD, 2, FEBRUARY}, + {AD, 2, JANUARY}, + {AD, 1, DECEMBER}, + {AD, 1, NOVEMBER}, + {AD, 1, OCTOBER}, + {AD, 1, SEPTEMBER}, + {AD, 1, AUGUST}, + {AD, 1, JULY}, + {AD, 1, JUNE}, + {AD, 1, MAY}, + {AD, 1, APRIL}, + {AD, 1, MARCH}, + {AD, 1, FEBRUARY}, + {AD, 1, JANUARY}, + {BC, 1, DECEMBER}, + {BC, 1, NOVEMBER}, + {BC, 1, OCTOBER}, + {BC, 1, SEPTEMBER}, + {BC, 1, AUGUST}, + {BC, 1, JULY}, + {BC, 1, JUNE}, + {BC, 1, MAY}, + {BC, 1, APRIL}, + {BC, 1, MARCH}, + {BC, 1, FEBRUARY}, + {BC, 1, JANUARY}, + {BC, 2, DECEMBER}, + {BC, 2, NOVEMBER}, + {BC, 2, OCTOBER}, + }; + private int tablesize = data.length; + + private void check(GregorianCalendar gc, int index) { + if (gc.get(ERA) != data[index][ERA]) { + errln("Invalid era :" + gc.get(ERA) + + ", expected :" + data[index][ERA]); + } + if (gc.get(YEAR) != data[index][YEAR]) { + errln("Invalid year :" + gc.get(YEAR) + + ", expected :" + data[index][YEAR]); + } + if (gc.get(MONTH) != data[index][MONTH]) { + errln("Invalid month :" + gc.get(MONTH) + + ", expected :" + data[index][MONTH]); + } + } + + public void Test4372743() { + GregorianCalendar gc; + TimeZone saveZone = TimeZone.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + + /* Set March 3, A.D. 2 */ + gc = new GregorianCalendar(2, MARCH, 3); + for (int i = 0; i < tablesize; i++) { + check(gc, i); + gc.add(gc.MONTH, -1); + } + + /* Again, Set March 3, A.D. 2 */ + gc = new GregorianCalendar(2, MARCH, 3); + for (int i = 0; i < tablesize; i+=7) { + check(gc, i); + gc.add(gc.MONTH, -7); + } + + /* Set March 10, 2 B.C. */ + gc = new GregorianCalendar(2, OCTOBER, 10); + gc.add(gc.YEAR, -3); + for (int i = tablesize -1; i >= 0; i--) { + check(gc, i); + gc.add(gc.MONTH, 1); + } + + /* Again, Set March 10, 2 B.C. */ + gc = new GregorianCalendar(2, OCTOBER, 10); + gc.add(gc.YEAR, -3); + for (int i = tablesize -1; i >= 0; i-=8) { + check(gc, i); + gc.add(gc.MONTH, 8); + } + } + finally { + TimeZone.setDefault(saveZone); + } + } +} diff --git a/jdk/test/java/util/Calendar/bug4401223.java b/jdk/test/java/util/Calendar/bug4401223.java new file mode 100644 index 00000000000..fbd9e29a8f6 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4401223.java @@ -0,0 +1,91 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4401223 + * @summary Make sure that GregorianCalendar doesn't cause IllegalArgumentException at some special situations which are related to the Leap Year. + * @library /java/text/testlib + */ + +import java.util.*; + +public class bug4401223 extends IntlTest { + + public void Test4401223a() { + int status = 0; + String s = null; + + try { + Date date = new Date(2000-1900, Calendar.FEBRUARY, 29); + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(date); + gc.setLenient(false); + gc.set(Calendar.YEAR, 2001); + s = "02/29/00 & set(YEAR,2001) = " + gc.getTime().toString(); + } catch (Exception ex) { + status++; + s = "Exception occurred for 2/29/00 & set(YEAR,2001): " + ex; + } + if (status > 0) { + errln(s); + } else { + logln(s); + } + } + + public void Test4401223b() { + int status = 0; + String s = null; + + try { + Date date = new Date(2000-1900, Calendar.DECEMBER, 31); + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(date); + gc.setLenient(false); + gc.set(Calendar.YEAR, 2001); + + if (gc.get(Calendar.YEAR) != 2001 || + gc.get(Calendar.MONTH) != Calendar.DECEMBER || + gc.get(Calendar.DATE) != 31 || + gc.get(Calendar.DAY_OF_YEAR) != 365) { + status++; + s = "Wrong Date : 12/31/00 & set(YEAR,2001) ---> " + gc.getTime().toString(); + } else { + s = "12/31/00 & set(YEAR,2001) = " + gc.getTime().toString(); + } + } catch (Exception ex) { + status++; + s = "Exception occurred for 12/31/00 & set(YEAR,2001) : " + ex; + } + if (status > 0) { + errln(s); + } else { + logln(s); + } + } + + public static void main(String[] args) throws Exception { + new bug4401223().run(args); + } +} diff --git a/jdk/test/java/util/Calendar/bug4409072.java b/jdk/test/java/util/Calendar/bug4409072.java new file mode 100644 index 00000000000..d8e56a45547 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4409072.java @@ -0,0 +1,683 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4409072 + * @summary tests for set(), add(), and roll() with various week parameters. + * @library /java/text/testlib + */ + +import java.util.*; +import static java.util.Calendar.*; + +public class bug4409072 extends IntlTest { + + public static void main(String[] args) throws Exception { + new bug4409072().run(args); + } + + /* Confirm some public methods' behavior in Calendar. + * (e.g. add(), roll(), set()) + */ + public void Test4409072() { + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + + Locale savedLocale = Locale.getDefault(); + TimeZone savedTZ = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + testSet(); + testAdd(); + testRoll(); + } finally { + TimeZone.setDefault(savedTZ); + Locale.setDefault(savedLocale); + } + } + + /* + * Golden data for set() test + */ + static final int[][][] resultWOMForSetTest = { + { /* For year1998 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, {11,11}, + /* Mon */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, + /* Tue */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + /* Wed */ {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + /* Thu */ {10,27}, {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + /* Fri */ {10,27}, {10,27}, {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + /* Sat */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, {11,11}, {11,11}, + }, + { /* For year1999 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, + /* Mon */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, + /* Tue */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, + /* Wed */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Thu */ {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Fri */ {10,26}, {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Sat */ {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, {11,10}, + }, + { /* For year2000 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + /* Mon */ {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + /* Tue */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, + /* Wed */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, + /* Thu */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, + /* Fri */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, + /* Sat */ {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + }, + { /* For year2001 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, + /* Mon */ {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, + /* Tue */ {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, + /* Wed */ {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, + /* Thu */ {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, + /* Fri */ {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, + /* Sat */ {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, + }, + { /* For year2002 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, + /* Mon */ {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, + /* Tue */ {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, + /* Wed */ {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, + /* Thu */ {10,29}, {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, + /* Fri */ {10,29}, {10,29}, {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, + /* Sat */ {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11,13}, + }, + { /* For year2003 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11,12}, + /* Mon */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, + /* Tue */ {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, + /* Wed */ {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, + /* Thu */ {10,28}, {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, + /* Fri */ {10,28}, {10,28}, {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, + /* Sat */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11,12}, {11,12}, + }, + { /* For year2004 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, + /* Mon */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, + /* Tue */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, + /* Wed */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Thu */ {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Fri */ {10,26}, {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, + /* Sat */ {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, {11,10}, + }, + { /* For year2005 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, {11, 9}, + /* Mon */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, + /* Tue */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, + /* Wed */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, + /* Thu */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, + /* Fri */ {10,25}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, + /* Sat */ {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, {11, 9}, {11, 9}, + }, + { /* For year2006 */ + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + /* Mon */ {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + /* Tue */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, + /* Wed */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, + /* Thu */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, + /* Fri */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, + /* Sat */ {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, + }, + }; + + static final int[][][] resultWOYForSetTest1 = { + { /* For year1998 */ + /* FirstDayOfWeek = Sunday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9}, + {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9}, + /* FirstDayOfWeek = Monday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9}, + /* FirstDayOfWeek = Tuesday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 2}, {1998, 0, 9}, {1998, 0, 9}, + /* FirstDayOfWeek = Wednesday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9}, + /* FirstDayOfWeek = Thursday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + /* FirstDayOfWeek = Friday */ + {1997,11,26}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, + /* FirstDayOfWeek = Saturday */ + {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9}, {1998, 0, 9}, + {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9}, + }, + { /* For year1999 */ + /* FirstDayOfWeek = Sunday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8}, + {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + /* FirstDayOfWeek = Monday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8}, + {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + /* FirstDayOfWeek = Tuesday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + /* FirstDayOfWeek = Wednesday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8}, + /* FirstDayOfWeek = Thursday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8}, + /* FirstDayOfWeek = Friday */ + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, + /* FirstDayOfWeek = Saturday */ + {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8}, + }, + { /* For year2000 */ + /* FirstDayOfWeek = Sunday */ + {1999,11,31}, {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Monday */ + {1999,11,31}, {1999,11,31}, {2000, 0, 7}, {2000, 0, 7}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Tuesday */ + {1999,11,31}, {1999,11,31}, {1999,11,31}, {2000, 0, 7}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Wednesday */ + {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Thursday */ + {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31}, + {1999,11,31}, {2000, 0, 7}, {2000, 0, 7}, + /* FirstDayOfWeek = Friday */ + {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31}, + {1999,11,31}, {1999,11,31}, {2000, 0, 7}, + /* FirstDayOfWeek = Saturday */ + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, + }, + { /* For year2001 */ + /* FirstDayOfWeek = Sunday */ + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0,12}, + /* FirstDayOfWeek = Monday */ + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Tuesday */ + {2000,11,29}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Wednesday */ + {2000,11,29}, {2000,11,29}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Thursday */ + {2000,11,29}, {2000,11,29}, {2000,11,29}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Friday */ + {2000,11,29}, {2000,11,29}, {2000,11,29}, {2000,11,29}, + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + /* FirstDayOfWeek = Saturday */ + {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, + {2001, 0, 5}, {2001, 0,12}, {2001, 0,12}, + }, + { /* For year2002 */ + /* FirstDayOfWeek = Sunday */ + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0,11}, {2002, 0,11}, + /* FirstDayOfWeek = Monday */ + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0,11}, + /* FirstDayOfWeek = Tuesday */ + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + /* FirstDayOfWeek = Wednesday */ + {2001,11,28}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + /* FirstDayOfWeek = Thursday */ + {2001,11,28}, {2001,11,28}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + /* FirstDayOfWeek = Friday */ + {2001,11,28}, {2001,11,28}, {2001,11,28}, {2002, 0, 4}, + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + /* FirstDayOfWeek = Saturday */ + {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, + {2002, 0,11}, {2002, 0,11}, {2002, 0,11}, + }, + { /* For year2003 */ + /* FirstDayOfWeek = Sunday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0,10}, {2003, 0,10}, {2003, 0,10}, + /* FirstDayOfWeek = Monday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0,10}, {2003, 0,10}, + /* FirstDayOfWeek = Tuesday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0, 3}, {2003, 0,10}, + /* FirstDayOfWeek = Wednesday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + /* FirstDayOfWeek = Thursday */ + {2002,11,27}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + /* FirstDayOfWeek = Friday */ + {2002,11,27}, {2002,11,27}, {2003, 0, 3}, {2003, 0, 3}, + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, + /* FirstDayOfWeek = Saturday */ + {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0,10}, + {2003, 0,10}, {2003, 0,10}, {2003, 0,10}, + }, + { /* For year2004 */ + /* FirstDayOfWeek = Sunday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9}, + {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9}, + /* FirstDayOfWeek = Monday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9}, + /* FirstDayOfWeek = Tuesday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 2}, {2004, 0, 9}, {2004, 0, 9}, + /* FirstDayOfWeek = Wednesday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9}, + /* FirstDayOfWeek = Thursday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + /* FirstDayOfWeek = Friday */ + {2003,11,26}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, + /* FirstDayOfWeek = Saturday */ + {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9}, {2004, 0, 9}, + {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9}, + }, + { /* For year2005 */ + /* FirstDayOfWeek = Sunday */ + {2004,11,31}, {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Monday */ + {2004,11,31}, {2004,11,31}, {2005, 0, 7}, {2005, 0, 7}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Tuesday */ + {2004,11,31}, {2004,11,31}, {2004,11,31}, {2005, 0, 7}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Wednesday */ + {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Thursday */ + {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31}, + {2004,11,31}, {2005, 0, 7}, {2005, 0, 7}, + /* FirstDayOfWeek = Friday */ + {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31}, + {2004,11,31}, {2004,11,31}, {2005, 0, 7}, + /* FirstDayOfWeek = Saturday */ + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, + }, + { /* For year2006 */ + /* FirstDayOfWeek = Sunday */ + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Monday */ + {2005,11,30}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Tuesday */ + {2005,11,30}, {2005,11,30}, {2006, 0, 6}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Wednesday */ + {2005,11,30}, {2005,11,30}, {2005,11,30}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Thursday */ + {2005,11,30}, {2005,11,30}, {2005,11,30}, {2005,11,30}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Friday */ + {2005,11,30}, {2005,11,30}, {2005,11,30}, {2005,11,30}, + {2005,11,30}, {2006, 0, 6}, {2006, 0, 6}, + /* FirstDayOfWeek = Saturday */ + {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, + {2006, 0, 6}, {2006, 0, 6}, {2006, 0,13}, + } + }; + + static final int[][] resultWOYForSetTest2 = { + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, + /* Mon */ {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, + /* Tue */ {4,25}, {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, + /* Wed */ {4,25}, {4,25}, {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, + /* Thu */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 8}, {5, 8}, + /* Fri */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 8}, + /* Sat */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, + }; + + /** + * Test for set() + */ + void testSet() { + boolean noerror = true; + Calendar cal = Calendar.getInstance(); + int sYear=1998; + int eYear=2006; + + // Loop for FirstDayOfWeek: SUNDAY..SATURDAY + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + + // Loop for MinimalDaysInFirstWeek: 1..7 + for (int minDow = 1; minDow <= 7; minDow++) { + int index = (dow-1)*7 + (minDow-1); + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(YEAR, 2005); + cal.set(DAY_OF_WEEK, WEDNESDAY); + cal.set(WEEK_OF_YEAR, 22); + + int y = 2005; + int m = resultWOYForSetTest2[index][0]; + int d = resultWOYForSetTest2[index][1]; + int year = cal.get(YEAR); + int month = cal.get(MONTH); + int date = cal.get(DATE); + + if (cal.get(WEEK_OF_YEAR) != 22) { + noerror = false; + errln("Failed : set(WEEK_OF_YEAR=22)" + + " *** get(WEEK_OF_YEAR=" + + cal.get(WEEK_OF_YEAR) + ")" + + ", got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+2005 + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } else if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : set(WEEK_OF_YEAR=22)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + for (int targetYear = sYear; targetYear<= eYear; targetYear++) { + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(YEAR, targetYear); + cal.set(DAY_OF_WEEK, FRIDAY); + cal.set(MONTH, DECEMBER); + cal.set(WEEK_OF_MONTH, 1); + + y = targetYear; + m = resultWOMForSetTest[targetYear-sYear][index][0]; + d = resultWOMForSetTest[targetYear-sYear][index][1]; + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : set(WEEK_OF_MONTH=1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(YEAR, targetYear); + cal.set(DAY_OF_WEEK, FRIDAY); + cal.set(WEEK_OF_YEAR, 1); + + y = resultWOYForSetTest1[targetYear-sYear][index][0]; + m = resultWOYForSetTest1[targetYear-sYear][index][1]; + d = resultWOYForSetTest1[targetYear-sYear][index][2]; + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if (cal.get(WEEK_OF_YEAR) != 1) { + noerror = false; + errln("Failed : set(WEEK_OF_YEAR=1)" + + " *** get(WEEK_OF_YEAR=" + + cal.get(WEEK_OF_YEAR) + ")" + + ", got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } else if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : set(WEEK_OF_YEAR=1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + } + } + } + + if (noerror) { + logln("Passed : set() test"); + } + } + + /** + * Test for add() + */ + void testAdd() { + boolean noerror = true; + Calendar cal = Calendar.getInstance(); + + // Loop for FirstDayOfWeek: SUNDAY..SATURDAY + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + + // Loop for MinimalDaysInFirstWeek: 1..7 + for (int minDow = 1; minDow <= 7; minDow++) { + int oldWOY, newWOY; + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(2005, DECEMBER, 7); + oldWOY = cal.get(WEEK_OF_YEAR); + + for (int cnt = 0; cnt < 7; cnt++) { + cal.add(WEEK_OF_YEAR, 1); + } + + int year = cal.get(YEAR); + int month = cal.get(MONTH); + int date = cal.get(DATE); + + if ((year != 2006) || (month != 0) || (date != 25)) { + noerror = false; + errln("Failed : add(WEEK_OF_YEAR+1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected 1/25/2006" + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + for (int cnt = 0; cnt < 10; cnt++) { + cal.add(WEEK_OF_YEAR, -1); + } + newWOY = cal.get(WEEK_OF_YEAR); + + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if ((oldWOY - newWOY) != 3) { + errln("Failed : add(WEEK_OF_YEAR-1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected 11/16/2005" + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow + + ", WEEK_OF_YEAR=" + newWOY + + " should be " + (oldWOY-3)); + } else if ((year != 2005) || (month != 10) || (date != 16)) { + errln("Failed : add(-1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected 11/16/2005" + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + } + } + + if (noerror) { + logln("Passed : add() test"); + } + } + + /* + * Golden data for roll() test + */ + static final int[] resultWOMForRollTest = { + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ 1, 1, 1, 26, 26, 26, 26, + /* Mon */ 1, 1, 1, 1, 26, 26, 26, + /* Tue */ 31, 31, 31, 31, 31, 24, 24, + /* Wed */ 31, 31, 31, 31, 31, 31, 24, + /* Thu */ 31, 31, 31, 31, 31, 31, 31, + /* Fri */ 1, 31, 31, 31, 31, 31, 31, + /* Sat */ 1, 1, 31, 31, 31, 31, 31, + }; + + static final int[][] resultWOYForRollTest = { + /* Min = 1 2 3 4 5 6 7 */ + /* Sun */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, + /* Mon */ {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, + /* Tue */ {1, 2}, {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, + /* Wed */ {1, 2}, {1, 2}, {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, + /* Thu */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {1, 2}, {1, 2}, + /* Fri */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {1, 2}, + /* Sat */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, + }; + + /** + * Test for roll() + */ + void testRoll() { + boolean noerror = true; + Calendar cal = Calendar.getInstance(); + + // Loop for FirstDayOfWeek: SUNDAY..SATURDAY + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + + // Loop for MinimalDaysInFirstWeek: 1..7 + for (int minDow = 1; minDow <= 7; minDow++) { + int oldWOY, newWOY; + int index = (dow-1)*7 + (minDow-1); + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(2005, DECEMBER, 12); + oldWOY = cal.get(WEEK_OF_YEAR); + for (int cnt = 0; cnt < 2; cnt++) { + cal.roll(WEEK_OF_MONTH, -1); + } + int y = 2005; + int m = DECEMBER; + int d = resultWOMForRollTest[index]; + int year = cal.get(YEAR); + int month = cal.get(MONTH); + int date = cal.get(DATE); + + if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : roll(WEEK_OF_MONTH-1)" + + " got " + (month+1) + "/" + date + "/" + year + + ", expected " + (m+1) + "/" + d + "/" + y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + cal.clear(); + cal.setLenient(true); + cal.setMinimalDaysInFirstWeek(minDow); + cal.setFirstDayOfWeek(dow); + cal.set(2005, DECEMBER, 7); + oldWOY = cal.get(WEEK_OF_YEAR); + + for (int cnt = 0; cnt < 7; cnt++) { + cal.roll(WEEK_OF_YEAR, 1); + } + + y = 2005; + m = resultWOYForRollTest[index][0]; + d = resultWOYForRollTest[index][1]; + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : roll(WEEK_OF_YEAR+1)" + + " got " + (month+1) + "/" + date + "/" + year + + ", expected " + (m+1) + "/" + d + "/" + y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + + for (int cnt = 0; cnt < 10; cnt++) { + cal.roll(WEEK_OF_YEAR, -1); + } + newWOY = cal.get(WEEK_OF_YEAR); + + y = 2005; + m = NOVEMBER; + d = 16; + year = cal.get(YEAR); + month = cal.get(MONTH); + date = cal.get(DATE); + + if ((year != y) || (month != m) || (date != d)) { + noerror = false; + errln("Failed : roll(WEEK_OF_YEAR-1)" + + " got " + (month+1)+"/"+date+"/"+year + + ", expected " + (m+1)+"/"+d+"/"+y + + ", MinFirstDOW=" + minDow + + ", FirstDOW=" + dow); + } + } + } + + if (noerror) { + logln("Passed : roll() test"); + } + } +} diff --git a/jdk/test/java/util/Calendar/bug4514831.java b/jdk/test/java/util/Calendar/bug4514831.java new file mode 100644 index 00000000000..9d635e26167 --- /dev/null +++ b/jdk/test/java/util/Calendar/bug4514831.java @@ -0,0 +1,95 @@ +/* + * 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 4514831 + * @summary Confirm that GregorianCalendar.roll() works properly during transition from Daylight Saving Time to Standard Time. + */ + +import java.util.*; + +public class bug4514831 { + + public static void main(String[] args) { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + boolean err = false; + + String golden_data1 ="27-28 28-29 29-30 30-31 31-1 1-2 2-3 "; + String golden_data2 ="27-28 28-29 29-30 30-31 31-25 25-26 26-27 "; + String golden_data3 ="1-8 8-15 15-22 22-29 29-1 1-8 8-15 "; + + try { + Locale.setDefault(Locale.US); + TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific")); + + String test_roll = ""; + GregorianCalendar c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 27); + for (int i=0; i < 7; i++) { + test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-"; + c_roll.roll(c_roll.DAY_OF_YEAR, true); + test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " "; + } + if (!test_roll.equals(golden_data1)) { + err = true; + System.err.println("Wrong roll(DAY_OF_YEAR) transition: got "+ + test_roll + "expected " + golden_data1); + } + + test_roll = ""; + c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 27); + c_roll.setFirstDayOfWeek(Calendar.THURSDAY); + for (int i=0; i < 7; i++) { + test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-"; + c_roll.roll(c_roll.DAY_OF_WEEK, true); + test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " "; + } + if (!test_roll.equals(golden_data2)) { + err = true; + System.err.println("Wrong roll(DAY_OF_WEEK) transition: got "+ + test_roll + "expected " + golden_data2); + } + + test_roll = ""; + c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 1); + for (int i=0; i < 7; i++) { + test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-"; + c_roll.roll(c_roll.DAY_OF_WEEK_IN_MONTH, true); + test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " "; + } + if (!test_roll.equals(golden_data3)) { + err = true; + System.err.println("Wrong roll(DAY_OF_WEEK_IN_MONTH) transition: got "+ + test_roll + "expected " + golden_data3); + } + } finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + + if (err) { + throw new RuntimeException("Wrong roll() transition"); + } + } +} diff --git a/jdk/test/java/util/Currency/PropertiesTest.java b/jdk/test/java/util/Currency/PropertiesTest.java index 96127bf19fe..fe35f2e6161 100644 --- a/jdk/test/java/util/Currency/PropertiesTest.java +++ b/jdk/test/java/util/Currency/PropertiesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, 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 @@ -25,6 +25,7 @@ import java.io.*; import java.text.*; import java.util.*; import java.util.regex.*; +import java.util.stream.Collectors; public class PropertiesTest { public static void main(String[] args) throws Exception { @@ -32,9 +33,14 @@ public class PropertiesTest { dump(args[1]); } else if (args.length == 4 && args[0].equals("-c")) { compare(args[1], args[2], args[3]); + } else if (args.length == 1 && args[0].equals("bug7102969")) { + bug7102969(); + } else if (args.length == 1 && args[0].equals("bug8157138")) { + bug8157138(); } else { System.err.println("Usage: java PropertiesTest -d "); System.err.println(" java PropertiesTest -c "); + System.err.println(" java PropertiesTest bug[JBS bug id number] e.g. bug7102969"); System.exit(-1); } } @@ -174,6 +180,74 @@ public class PropertiesTest { } } + private static void bug7102969() { + + // check the correct overriding of special case entries + Currency cur = Currency.getInstance(new Locale("", "JP")); + if (!cur.getCurrencyCode().equals("ABC")) { + throw new RuntimeException("[Expected: ABC as currency code of JP, found: " + + cur.getCurrencyCode() + "]"); + } + + /* check if the currency instance is returned by + * getAvailableCurrencies() method + */ + if (!Currency.getAvailableCurrencies().contains(cur)) { + throw new RuntimeException("[The Currency instance [" + + cur.getCurrencyCode() + ", " + + cur.getNumericCode() + ", " + + cur.getDefaultFractionDigits() + + "] is not available in the currencies list]"); + } + + } + + private static void bug8157138() { + + /* check the currencies which exist only as a special case are + * accessible i.e. it should not throw IllegalArgumentException + */ + try { + Currency.getInstance("MAD"); + } catch (IllegalArgumentException ex) { + throw new RuntimeException("Test Failed: " + + "special case currency instance MAD not found" + + " via Currency.getInstance(\"MAD\")"); + } + + try { + Currency.getInstance("ABC"); + } catch (IllegalArgumentException ex) { + throw new RuntimeException("Test Failed: " + + "special case currency instance ABC not found" + + " via Currency.getInstance(\"ABC\")"); + } + + /* check the currency value is returned by getAvailableCurrencies() + * method + */ + List list = Currency.getAvailableCurrencies().stream() + .filter(cur -> cur.getCurrencyCode().equals("MAD")) + .collect(Collectors.toList()); + + if (list.isEmpty()) { + throw new RuntimeException("Test Failed: " + + "special case currency instance MAD not found" + + " in Currency.getAvailableCurrencies() list"); + } + + list = Currency.getAvailableCurrencies().stream() + .filter(cur -> cur.getCurrencyCode().equals("ABC")) + .collect(Collectors.toList()); + + if (list.isEmpty()) { + throw new RuntimeException("Test Failed: " + + "special case currency instance ABC not found" + + " in Currency.getAvailableCurrencies() list"); + } + + } + private static boolean isPastCutoverDate(String s) throws IndexOutOfBoundsException, NullPointerException, ParseException { String dateString = s.substring(s.lastIndexOf(',')+1, s.length()).trim(); diff --git a/jdk/test/java/util/Currency/PropertiesTest.sh b/jdk/test/java/util/Currency/PropertiesTest.sh index a6f8a76d189..215be9229ae 100644 --- a/jdk/test/java/util/Currency/PropertiesTest.sh +++ b/jdk/test/java/util/Currency/PropertiesTest.sh @@ -23,7 +23,8 @@ # # @test -# @bug 6332666 6863624 7180362 8003846 8074350 8074351 8130246 8149735 +# @bug 6332666 6863624 7180362 8003846 8074350 8074351 8130246 8149735 7102969 +# 8157138 # @summary tests the capability of replacing the currency data with user # specified currency properties file # @build PropertiesTest @@ -113,6 +114,16 @@ ${WRITABLEJDK}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} PropertiesTest if [ $? != 0 ]; then failures=`expr $failures + 1`; fi if [ ! -f dump3 ]; then echo "file dump3 not created. Test cannot execute. Failed."; exit 1; fi +# run bug7102969 test +echo '' +${WRITABLEJDK}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} PropertiesTest bug7102969 +if [ $? != 0 ]; then failures=`expr $failures + 1`; fi + +# run bug8157138 test +echo '' +${WRITABLEJDK}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} PropertiesTest bug8157138 +if [ $? != 0 ]; then failures=`expr $failures + 1`; fi + # Cleanup rm -rf $WRITABLEJDK diff --git a/jdk/test/java/util/Currency/currency.properties b/jdk/test/java/util/Currency/currency.properties index d8e874d819a..57b293542b8 100644 --- a/jdk/test/java/util/Currency/currency.properties +++ b/jdk/test/java/util/Currency/currency.properties @@ -6,7 +6,7 @@ CL=CLF,990,4 CM=IED,111,2, 2004-01-01T00:70:00 ES=ESD,877,2 -JP=JPZ,123,2 +JP=ABC,999,0 MA=MAA,555,5 MC=MCC,555,6 MD=MDD,555,7 diff --git a/jdk/test/java/util/Currency/tablea1.txt b/jdk/test/java/util/Currency/tablea1.txt index 92e43adf2be..dacc0fb5210 100644 --- a/jdk/test/java/util/Currency/tablea1.txt +++ b/jdk/test/java/util/Currency/tablea1.txt @@ -5,7 +5,7 @@ # # Version -FILEVERSION=2 +FILEVERSION=3 DATAVERSION=160 # ISO 4217 currency data diff --git a/jdk/test/java/util/Date/Bug4955000.java b/jdk/test/java/util/Date/Bug4955000.java new file mode 100644 index 00000000000..c94b23868ca --- /dev/null +++ b/jdk/test/java/util/Date/Bug4955000.java @@ -0,0 +1,144 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4955000 + * @summary Make sure that a Date and a GregorianCalendar produce the + * same date/time. Both are new implementations in 1.5. + */ + +import java.util.*; +import static java.util.GregorianCalendar.*; + +@SuppressWarnings("deprecation") +public class Bug4955000 { + // Tests for Date.UTC(), derived from JCK + // Date.miscTests.Date1025 and Date2015 + public static void main(String[] args) { + TimeZone defaultTZ = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("NST")); + GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("UTC")); + // Date1025 + int[] years1 = { + Integer.MIN_VALUE, + Integer.MIN_VALUE + 1, + gc.getMinimum(YEAR) - 1, + gc.getMaximum(YEAR) + 1, + Integer.MAX_VALUE - 1, + Integer.MAX_VALUE + }; + for (int i = 0; i < years1.length; i++) { + gc.clear(); + gc.set(years1[i], gc.JANUARY, 1); + long t = gc.getTimeInMillis(); + long utc = Date.UTC(years1[i] - 1900, 1-1, 1, + 0, 0, 0); // Jan 1 00:00:00 + if (t != utc) { + throw new RuntimeException("t (" + t + ") != utc (" + utc +")"); + } + } + + // Date2015 + int years[] = { + gc.getGreatestMinimum(YEAR), + gc.getGreatestMinimum(YEAR) + 1, + -1, + 0, + 1, + gc.getLeastMaximum(YEAR) - 1, + gc.getLeastMaximum(YEAR) + }; + + int months[] = { + gc.getMinimum(MONTH), + gc.getMinimum(MONTH) + 1, + gc.getMaximum(MONTH) - 1, + gc.getMaximum(MONTH) + }; + + int dates[] = { + gc.getMinimum(DAY_OF_MONTH), + gc.getMinimum(DAY_OF_MONTH) + 1, + gc.getMaximum(DAY_OF_MONTH) - 1, + gc.getMaximum(DAY_OF_MONTH) + }; + + int hs[] = { + gc.getMinimum(HOUR), + gc.getMinimum(HOUR) + 1, + gc.getMaximum(HOUR) - 1, + gc.getMaximum(HOUR) + }; + + int ms[] = { + gc.getMinimum(MINUTE), + gc.getMinimum(MINUTE) + 1, + gc.getMaximum(MINUTE) - 1, + gc.getMaximum(MINUTE) + }; + + int ss[] = { + gc.getMinimum(SECOND), + gc.getMinimum(SECOND) + 1, + gc.getMaximum(SECOND) - 1, + gc.getMaximum(SECOND) + }; + + for(int i = 0; i < years.length; i++) { + for(int j = 0; j < months.length; j++) { + for(int k = 0; k < dates.length; k++) { + for(int m = 0; m < hs.length; m++) { + for(int n = 0; n < ms.length; n++) { + for(int p = 0; p < ss.length; p++) { + int year = years[i] - 1900; + int month = months[j]; + int date = dates[k]; + int hours = hs[m]; + int minutes = ms[n]; + int seconds = ss[p]; + + long result = Date.UTC(year, month, date, + hours, minutes, seconds); + + gc.clear(); + gc.set(year + 1900, month, date, hours, minutes, seconds); + + long expected = gc.getTime().getTime(); + + if (expected != result) { + throw new RuntimeException("expected (" + expected + + ") != result (" + result +")"); + } + } + } + } + } + } + } + } finally { + TimeZone.setDefault(defaultTZ); + } + } +} diff --git a/jdk/test/java/util/Date/DateGregorianCalendarTest.java b/jdk/test/java/util/Date/DateGregorianCalendarTest.java new file mode 100644 index 00000000000..49dbc8bc41a --- /dev/null +++ b/jdk/test/java/util/Date/DateGregorianCalendarTest.java @@ -0,0 +1,235 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4614842 + * @summary Make sure that a Date and a GregorianCalendar produce the same date/time. Both are new implementations in 1.5. + * @run main DateGregorianCalendarTest 15 + */ + +import java.util.*; +import static java.util.GregorianCalendar.*; + +// Usage: java DateGregorianCalendarTest [duration] + +@SuppressWarnings("deprecation") +public class DateGregorianCalendarTest { + static volatile boolean runrun = true; + static int nThreads; + + public static void main(String[] args) { + int duration = 600; + if (args.length == 1) { + duration = Math.max(10, Integer.parseInt(args[0])); + } + + TimeZone savedTZ = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Thread[] t = new Thread[10]; // for future bugs... + int index = 0; + t[index++] = new Thread(new Runnable() { + public void run() { + GregorianCalendar gc = new GregorianCalendar(); + + long delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000); + long count = 0; + try { + for (long t = Long.MIN_VALUE; runrun && t < Long.MAX_VALUE-delta; t += delta) { + gc.setTimeInMillis(t); + Date date = new Date(t); + int y; + if (!((y = gc.get(YEAR)) == (date.getYear()+1900) && + gc.get(MONTH) == date.getMonth() && + gc.get(DAY_OF_MONTH) == date.getDate() && + gc.get(HOUR_OF_DAY) == date.getHours() && + gc.get(MINUTE) == date.getMinutes() && + gc.get(SECOND) == date.getSeconds())) { + throw new RuntimeException("GregorinCalendar and Date returned different dates." + +" (millis=" + t + ")\n" + +"GC=" + gc + "\nDate=" + date); + } + ++count; + if (y >= 1) { + delta = (long)(365.2422 * 24 * 60 * 60 * 1000); + } + if (y >= 1970) { + delta = (24 * 60 * 60 * 1000); + } + if (y >= 2039) { + delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000); + } + } + if (runrun) { + System.out.println("Part I (count="+count+"): Passed"); + } else { + System.out.println("Part I (count="+count+"): Incomplete"); + } + } catch (RuntimeException e) { + System.out.println("Part I (count="+count+"): FAILED"); + runrun = false; + throw e; + } finally { + decrementCounter(); + } + } + }); + + t[index++] = new Thread(new Runnable() { + public void run() { + GregorianCalendar gc = new GregorianCalendar(); + + long count = 0; + int delta; + try { + for (long year = Integer.MIN_VALUE+1900; + runrun && year <= Integer.MAX_VALUE; year += delta) { + checkTimes(gc, year, JANUARY, 1, 0, 0, 0); + ++count; + delta = getDelta((int)year); + } + + for (long month = Integer.MIN_VALUE; + runrun && month <= Integer.MAX_VALUE; month += delta) { + checkTimes(gc, 1900, month, 1, 0, 0, 0); + ++count; + delta = getDelta(gc.get(YEAR)); + } + + for (long dayOfMonth = Integer.MIN_VALUE; + runrun && dayOfMonth <= Integer.MAX_VALUE; dayOfMonth += delta) { + checkTimes(gc, 1900, JANUARY, dayOfMonth, 0, 0, 0); + ++count; + delta = getDelta(gc.get(YEAR)); + } + if (runrun) { + System.out.println("Part II (count="+count+"): Passed"); + } else { + System.out.println("Part II (count="+count+"): Incomplete"); + } + } catch (RuntimeException e) { + System.out.println("Part II (count="+count+"): FAILED"); + runrun = false; + throw e; + } finally { + decrementCounter(); + } + } + }); + + // t3 takes more than 10 minutes (on Ultra-60 450MHz) without + // the 4936355 fix due to getting the small delta. + t[index++] = new Thread(new Runnable() { + public void run() { + GregorianCalendar gc = new GregorianCalendar(); + + long count = 0; + int delta; + try { + for (long hourOfDay = Integer.MIN_VALUE; + runrun && hourOfDay <= Integer.MAX_VALUE; hourOfDay += delta) { + checkTimes(gc, 1970, JANUARY, 1, hourOfDay, 0, 0); + ++count; + delta = getDelta(gc.get(YEAR)); + } + for (long minutes = Integer.MIN_VALUE; + runrun && minutes <= Integer.MAX_VALUE; minutes += delta) { + checkTimes(gc, 1970, JANUARY, 1, 0, minutes, 0); + ++count; + delta = getDelta(gc.get(YEAR)) * 60; + } + for (long seconds = Integer.MIN_VALUE; + runrun && seconds <= Integer.MAX_VALUE; seconds += delta) { + checkTimes(gc, 1970, JANUARY, 1, 0, 0, seconds); + ++count; + delta = getDelta(gc.get(YEAR)) * 60 * 60; + } + if (runrun) { + System.out.println("Part III (count="+count+"): Passed"); + } else { + System.out.println("Part III (count="+count+"): Incomplete"); + } + } catch (RuntimeException e) { + System.out.println("Part III (count="+count+"): FAILED"); + runrun = false; + throw e; + } finally { + decrementCounter(); + } + } + }); + + for (int i = 0; i < index; i++) { + incrementCounter(); + t[i].start(); + } + + try { + for (int i = 0; getCounter() > 0 && i < duration; i++) { + Thread.sleep(1000); + } + runrun = false; + for (int i = 0; i < index; i++) { + t[i].join(); + } + } catch (InterruptedException e) { + } + } finally { + TimeZone.setDefault(savedTZ); + } + } + + static void checkTimes(GregorianCalendar gc, long year, long month, long dayOfMonth, + long hourOfDay, long minutes, long seconds) { + gc.clear(); + gc.set((int)year, (int)month, (int)dayOfMonth, (int)hourOfDay, (int)minutes, (int)seconds); + long time = gc.getTimeInMillis(); + Date date = new Date((int)year - 1900, (int)month, (int)dayOfMonth, + (int)hourOfDay, (int)minutes, (int)seconds); + long time2 = date.getTime(); + if (time != time2) { + throw new RuntimeException("GregorinCalendar and Date returned different values.\n" + +"year="+year+", month="+month+", dayOfMonth="+dayOfMonth + +"\nhourOfDay="+hourOfDay+", minutes="+minutes+", seconds="+seconds + +"\ntime=" + time + ", time2=" + time2 + +"\nGC=" + gc + "\nDate=" + date); + } + } + + static final int getDelta(int year) { + return (year >= 1970 && year <= 2039) ? 1 : 1<<13; + } + + synchronized static void incrementCounter() { + nThreads++; + } + + synchronized static void decrementCounter() { + nThreads--; + } + + synchronized static int getCounter() { + return nThreads; + } +} diff --git a/jdk/test/java/util/Date/DateRegression.java b/jdk/test/java/util/Date/DateRegression.java new file mode 100644 index 00000000000..70d8a5bf706 --- /dev/null +++ b/jdk/test/java/util/Date/DateRegression.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4023247 4027685 4032037 4072029 4073003 4118010 4120606 4133833 4136916 6274757 6314387 + * @library /java/text/testlib + */ + +import java.util.*; + +@SuppressWarnings("deprecation") +public class DateRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new DateRegression().run(args); + } + + /** + * @bug 4023247 + */ + public void Test4023247() { + Date d1 = new Date(0); + Date d2 = new Date(0); + + d1.setYear(96); + d1.setMonth(11); + d1.setDate(22); + d1.setHours(0); + d1.setMinutes(0); + d1.setSeconds(0); + + d2.setYear(96); + d2.setMonth(11); + d2.setDate(22); + d2.setHours(0); + d2.setMinutes(0); + d2.setSeconds(0); + + if (d1.hashCode() != d2.hashCode()) + errln("Fail: Date hashCode misbehaves"); + } + + /** + * @bug 4027685 + */ + public void Test4027685() { + // Should be 01/16/97 00:00:00 + Date nite = new Date("16-JAN-97 12:00 AM"); + // Should be 01/16/97 12:00:00 + Date noon = new Date("16-JAN-97 12:00 PM"); + + logln("Midnight = " + nite + ", Noon = " + noon); + if (!nite.equals(new Date(97, Calendar.JANUARY, 16, 0, 0)) || + !noon.equals(new Date(97, Calendar.JANUARY, 16, 12, 0))) + errln("Fail: Nite/Noon confused"); + } + + /** + * @bug 4032037 + */ + public void Test4032037() { + Date ref = new Date(97, 1, 10); + Date d = new Date(Date.parse("2/10/97")); + logln("Date.parse(2/10/97) => " + d); + if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d); + d = new Date(Date.parse("10 feb 1997")); + logln("Date.parse(10 feb 1997) => " + d); + if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d); + d = new Date("2/10/97"); + logln("Date(2/10/97) => " + d); + if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d); + d = new Date("10 feb 1997"); + logln("Date(10 feb 1997) => " + d); + if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d); + } + + /** + * @bug 4072029 + */ + public void Test4072029() { + TimeZone saveZone = TimeZone.getDefault(); + + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + Date now = new Date(); + String s = now.toString(); + Date now2 = new Date(now.toString()); + String s2 = now2.toString(); // An hour's difference + + if (!s.equals(s2) || + Math.abs(now.getTime() - now2.getTime()) > 60000 /*one min*/) { + errln("Fail: Roundtrip toString/parse"); + } + } + finally { + TimeZone.setDefault(saveZone); + } + } + + /** + * @bug 4073003 + */ + public void Test4073003() { + Date d = new Date(Date.parse("01/02/1984")); + if (!d.equals(new Date(84, 0, 2))) + errln("Fail: Want 1/2/1984 Got " + d); + d = new Date(Date.parse("02/03/2012")); + if (!d.equals(new Date(112, 1, 3))) + errln("Fail: Want 2/3/2012 Got " + d); + d = new Date(Date.parse("03/04/15")); + if (!d.equals(new Date(115, 2, 4))) + errln("Fail: Want 3/4/2015 Got " + d); + } + + /** + * @bug 4118010 + * Regress bug: + * Feb. 2000 has 29 days, but Date(2000, 1, 29) returns March 01, 2000 + * NOTE: This turned out to be a user error (passing in 2000 instead + * of 2000-1900 to the Date constructor). + */ + public void Test4118010() { + Date d=new java.util.Date(2000-1900, Calendar.FEBRUARY, 29); + int m=d.getMonth(); + int date=d.getDate(); + if (m != Calendar.FEBRUARY || + date != 29) + errln("Fail: Want Feb 29, got " + d); + } + + /** + * @bug 4120606 + * Date objects share state after cloning. + */ + public void Test4120606() { + Date d = new Date(98, Calendar.JUNE, 24); + d.setMonth(Calendar.MAY); + Date e = (Date)d.clone(); + d.setMonth(Calendar.FEBRUARY); + if (e.getMonth() != Calendar.MAY) { + errln("Cloned Date objects share state"); + } + } + + /** + * @bug 4133833 + * Date constructor crashes with parameters out of range, when it should + * normalize. + */ + public void Test4133833() { + Date date = new java.util.Date(12,15,19); + Date exp = new Date(1913-1900, Calendar.APRIL, 19); + if (!date.equals(exp)) + errln("Fail: Want " + exp + + "; got " + date); + } + + /** + * @bug 4136916 + * Date.toString() throws exception in 1.2b4-E + * CANNOT REPRODUCE this bug + */ + public void Test4136916() { + Date time = new Date(); + logln(time.toString()); + } + + /** + * @bug 6274757 + * Date getTime and toString interaction for some time values + */ + public void Test6274757() { + TimeZone savedTz = TimeZone.getDefault(); + try { + // Use a time zone west of GMT. + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + TimeZone jdkGMT = TimeZone.getTimeZone("GMT"); + Calendar jdkCal = Calendar.getInstance(jdkGMT); + jdkCal.clear(); + jdkCal.set(1582, Calendar.OCTOBER, 15); + logln("JDK time: " + jdkCal.getTime().getTime() ); + logln("JDK time (str): " + jdkCal.getTime() ); + logln("Day of month: " + jdkCal.get(Calendar.DAY_OF_MONTH)); + Date co = jdkCal.getTime(); + logln("Change over (Oct 15 1582) = " + co + " (" + + co.getTime() + ")"); + long a = jdkCal.getTime().getTime(); + Date c = jdkCal.getTime(); + c.toString(); + long b = c.getTime(); + + if (a != b) { + errln("ERROR: " + a + " != " + b); + } else { + logln(a + " = " + b); + } + } finally { + TimeZone.setDefault(savedTz); + } + } + + /** + * @bug 6314387 + * JCK6.0: api/java_util/Date/index.html#misc fails, mustang + */ + public void Test6314387() { + Date d = new Date(Long.MAX_VALUE); + int y = d.getYear(); + if (y != 292277094) { + errln("yesr: got " + y + ", expected 292277094"); + } + d = new Date(Long.MIN_VALUE); + y = d.getYear(); + if (y != 292267155) { + errln("yesr: got " + y + ", expected 292267155"); + } + } +} + +//eof diff --git a/jdk/test/java/util/Date/DateTest.java b/jdk/test/java/util/Date/DateTest.java new file mode 100644 index 00000000000..98392760ba3 --- /dev/null +++ b/jdk/test/java/util/Date/DateTest.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4143459 + * @summary test Date + * @library /java/text/testlib + */ + +import java.text.*; +import java.util.*; + +@SuppressWarnings("deprecation") +public class DateTest extends IntlTest +{ + public static void main(String[] args) throws Exception { + new DateTest().run(args); + } + + /** + * @bug 4143459 + * Warning: Use TestDefaultZone() for complete testing of this bug. + */ + public void TestDefaultZoneLite() { + // Note: This test is redundant with TestDefaultZone(). It was added by + // request to provide a short&sweet test for this bug. It does not test + // all cases though, so IF THIS TEST PASSES, THE BUG MAY STILL BE + // PRESENT. Use TestDefaultZone() to be sure. + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Date d = new Date(); + d.setYear(98); + d.setMonth(Calendar.JANUARY); + d.setDate(1); + d.setHours(6); + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + if (d.getHours() != 22) { + errln("Fail: Date.setHours()/getHours() ignoring default zone"); + } + } + finally { TimeZone.setDefault(save); } + } + + /** + * @bug 4143459 + */ + public void TestDefaultZone() { + // Various problems can creep up, with the current implementation of Date, + // when the default zone is changed. + + TimeZone saveZone = TimeZone.getDefault(); + try { + + Date d = new Date(); // Trigger static init + Date ref = new Date(883634400000L); // This is Thu Jan 1 1998 6:00 am GMT + String refstr = "Jan 1 1998 6:00"; + TimeZone GMT = TimeZone.getTimeZone("GMT"); + TimeZone PST = TimeZone.getTimeZone("PST"); + + String[] names = { "year", "month", "date", "day of week", "hour", "offset" }; + int[] GMT_EXP = { 98, Calendar.JANUARY, 1, Calendar.THURSDAY - Calendar.SUNDAY, 6, 0 }; + int[] PST_EXP = { 97, Calendar.DECEMBER, 31, Calendar.WEDNESDAY - Calendar.SUNDAY, 22, 480 }; + + // There are two cases to consider: a Date object with no Calendar + // sub-object (most Date objects), and a Date object with a Calendar + // sub-object. We make two passes to cover the two cases. + for (int pass=0; pass<2; ++pass) { + logln(pass == 0 ? "Normal Date object" : "Date with Calendar sub-object"); + + TimeZone.setDefault(GMT); + d = new Date(refstr); + if (pass == 1) { + // Force creation of Calendar sub-object + d.setYear(d.getYear()); + } + if (d.getTime() != ref.getTime()) { + errln("FAIL: new Date(\"" + refstr + "\") x GMT -> " + d + + " " + d.getTime() + " ms"); + } + + int[] fields = { d.getYear(), d.getMonth(), d.getDate(), + d.getDay(), d.getHours(), d.getTimezoneOffset() }; + for (int i=0; i PER_LOOP_LIMIT) + logln("WARNING: Date constructor/getYear slower than " + + PER_LOOP_LIMIT + " ms"); + } + static double PER_LOOP_LIMIT = 3.0; + + /** + * Verify that the Date(String) constructor works. + */ + public void TestParseOfGMT() + { + Date OUT = null; + + /* Input values */ + String stringVal = "Jan 01 00:00:00 GMT 1900"; + long expectedVal = -2208988800000L; + + OUT = new Date( stringVal ); + + if( OUT.getTime( ) == expectedVal ) { + // logln("PASS"); + } + else { + errln( "Expected: " + + new Date( expectedVal ) + + ": " + + expectedVal + + " Received: " + + OUT.toString() + + ": " + + OUT.getTime() ); + } + } + + // Check out Date's behavior with large negative year values; bug 664 + // As of the fix to bug 4056585, Date should work correctly with + // large negative years. + public void TestDateNegativeYears() + { + Date d1= new Date(80,-1,2); + logln(d1.toString()); + d1= new Date(-80,-1,2); + logln(d1.toString()); + boolean e = false; + try { + d1= new Date(-800000,-1,2); + logln(d1.toString()); + } + catch (IllegalArgumentException ex) { + e = true; + } + if (e) errln("FAIL: Saw exception for year -800000"); + else logln("Pass: No exception for year -800000"); + } + + // Verify the behavior of Date + public void TestDate480() + { + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + Date d1=new java.util.Date(97,8,13,10,8,13); + logln("d = "+d1); + Date d2=new java.util.Date(97,8,13,30,8,13); // 20 hours later + logln("d+20h = "+d2); + + double delta = (d2.getTime() - d1.getTime()) / 3600000; + + logln("delta = " + delta + "h"); + + if (delta != 20.0) errln("Expected delta of 20; got " + delta); + + Calendar cal = Calendar.getInstance(); + cal.clear(); + cal.set(1997,8,13,10,8,13); + Date t1 = cal.getTime(); + logln("d = "+t1); + cal.clear(); + cal.set(1997,8,13,30,8,13); // 20 hours later + Date t2 = cal.getTime(); + logln("d+20h = "+t2); + + double delta2 = (t2.getTime() - t1.getTime()) / 3600000; + + logln("delta = " + delta2 + "h"); + + if (delta != 20.0) errln("Expected delta of 20; got " + delta2); + } + finally { + TimeZone.setDefault(save); + } + } +} diff --git a/jdk/test/java/util/Date/TZ.java b/jdk/test/java/util/Date/TZ.java new file mode 100644 index 00000000000..56722a1cdb7 --- /dev/null +++ b/jdk/test/java/util/Date/TZ.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4108737 + * @summary java.util.Date doesn't fail if current TimeZone is changed + */ + +import java.util.TimeZone; +import java.util.Date; + +public class TZ { + + public static void main(String args[]) { + TimeZone tz = TimeZone.getDefault(); + try { + testMain(); + } finally { + TimeZone.setDefault(tz); + } + } + + static void testMain() { + String expectedResult = "Sat Feb 01 00:00:00 PST 1997"; + + // load the java.util.Date class in the GMT timezone + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + new Date(); // load the class (to run static initializers) + + // use the class in different timezone + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + @SuppressWarnings("deprecation") + Date date = new Date(97, 1, 1); + if (!date.toString().equals(expectedResult)) { + throw new RuntimeException("Regression bug id #4108737 - Date fails if default time zone changed"); + } + } +} diff --git a/jdk/test/java/util/Date/TimestampTest.java b/jdk/test/java/util/Date/TimestampTest.java new file mode 100644 index 00000000000..950f0a5fb91 --- /dev/null +++ b/jdk/test/java/util/Date/TimestampTest.java @@ -0,0 +1,134 @@ +/* + * 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 5008227 + * @summary Make sure that changes to the Date class don't break java.sql.Timestamp. + * @modules java.sql + * @library /java/text/testlib + */ + +import java.util.*; +import java.sql.Timestamp; + +public class TimestampTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new TimestampTest().run(args); + } + + /** + * 5008227: java.sql.Timestamp.after() is not returning correct result + * + * Test before(), after(), equals(), compareTo() and getTime(). + */ + public void Test5008227() { + long t = System.currentTimeMillis(); + Timestamp ts1 = new Timestamp(t), ts2 = new Timestamp(t); + ts1.setNanos(999999999); + ts2.setNanos( 1000000); + compareTimestamps(ts1, ts2, 1); + + ts1.setTime(t + 1000); + ts2.setTime(t); + ts1.setNanos( 999999); + ts2.setNanos(999999999); + compareTimestamps(ts1, ts2, 1); + + ts1.setTime(t); + ts2.setTime(t); + ts1.setNanos(123456789); + ts2.setNanos(123456789); + compareTimestamps(ts1, ts2, 0); + + ts1.setTime(t); + ts2.setTime(t); + ts1.setNanos(1); + ts2.setNanos(2); + compareTimestamps(ts1, ts2, -1); + + ts1.setTime(t); + ts2.setTime(t+1000); + ts1.setNanos(999999); + ts2.setNanos( 0); + compareTimestamps(ts1, ts2, -1); + } + + /** + * Compares two Timestamps with the expected result. + * + * @param ts1 the first Timestamp + * @param ts2 the second Timestamp + * @param expect the expected relation between ts1 and ts2; 0 if + * ts1 equals to ts2, or 1 if ts1 is after ts2, or -1 if ts1 is + * before ts2. + */ + private void compareTimestamps(Timestamp ts1, Timestamp ts2, int expected) { + boolean expectedResult = expected > 0; + boolean result = ts1.after(ts2); + if (result != expectedResult) { + errln("ts1.after(ts2) returned " + result + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + + expectedResult = expected < 0; + result = ts1.before(ts2); + if (result != expectedResult) { + errln("ts1.before(ts2) returned " + result + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + + expectedResult = expected == 0; + result = ts1.equals(ts2); + if (result != expectedResult) { + errln("ts1.equals(ts2) returned " + result + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + + int x = ts1.compareTo(ts2); + int y = (x > 0) ? 1 : (x < 0) ? -1 : 0; + if (y != expected) { + errln("ts1.compareTo(ts2) returned " + x + ", expected " + + relation(expected, "") + "0" + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + long t1 = ts1.getTime(); + long t2 = ts2.getTime(); + int z = (t1 > t2) ? 1 : (t1 < t2) ? -1 : 0; + if (z == 0) { + int n1 = ts1.getNanos(); + int n2 = ts2.getNanos(); + z = (n1 > n2) ? 1 : (n1 < n2) ? -1 : 0; + } + if (z != expected) { + errln("ts1.getTime() " + relation(z, "==") + " ts2.getTime(), expected " + + relation(expected, "==") + + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")"); + } + } + + private static String relation(int x, String whenEqual) { + return (x > 0) ? ">" : (x < 0) ? "<" : whenEqual; + } +} diff --git a/jdk/test/java/util/Objects/CheckIndex.java b/jdk/test/java/util/Objects/CheckIndex.java index c4efdb1c253..bcfa1d5b23d 100644 --- a/jdk/test/java/util/Objects/CheckIndex.java +++ b/jdk/test/java/util/Objects/CheckIndex.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,13 @@ /** * @test - * @summary IndexOutOfBoundsException check index tests + * @summary Objects.checkIndex/jdk.internal.util.Preconditions.checkIndex tests * @run testng CheckIndex - * @bug 8135248 8142493 + * @bug 8135248 8142493 8155794 + * @modules java.base/jdk.internal.util */ +import jdk.internal.util.Preconditions; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -95,7 +97,7 @@ public class CheckIndex { public void testCheckIndex(int index, int length, boolean withinBounds) { String expectedMessage = withinBounds ? null - : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). + : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). apply("checkIndex", List.of(index, length)).getMessage(); BiConsumer, IntSupplier> checker = (ec, s) -> { @@ -117,21 +119,21 @@ public class CheckIndex { }; checker.accept(AssertingOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, - assertingOutOfBounds(expectedMessage, "checkIndex", index, length))); + () -> Preconditions.checkIndex(index, length, + assertingOutOfBounds(expectedMessage, "checkIndex", index, length))); checker.accept(IndexOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, - assertingOutOfBoundsReturnNull("checkIndex", index, length))); + () -> Preconditions.checkIndex(index, length, + assertingOutOfBoundsReturnNull("checkIndex", index, length))); checker.accept(IndexOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, null)); + () -> Preconditions.checkIndex(index, length, null)); checker.accept(IndexOutOfBoundsException.class, () -> Objects.checkIndex(index, length)); checker.accept(ArrayIndexOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, - Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); + () -> Preconditions.checkIndex(index, length, + Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); checker.accept(StringIndexOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, - Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); + () -> Preconditions.checkIndex(index, length, + Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); } @@ -157,7 +159,7 @@ public class CheckIndex { public void testCheckFromToIndex(int fromIndex, int toIndex, int length, boolean withinBounds) { String expectedMessage = withinBounds ? null - : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). + : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). apply("checkFromToIndex", List.of(fromIndex, toIndex, length)).getMessage(); BiConsumer, IntSupplier> check = (ec, s) -> { @@ -179,21 +181,21 @@ public class CheckIndex { }; check.accept(AssertingOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, - assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length))); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, + assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length))); check.accept(IndexOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, - assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length))); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, + assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length))); check.accept(IndexOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, null)); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, null)); check.accept(IndexOutOfBoundsException.class, () -> Objects.checkFromToIndex(fromIndex, toIndex, length)); check.accept(ArrayIndexOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, - Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, + Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); check.accept(StringIndexOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, - Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, + Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); } @@ -226,7 +228,7 @@ public class CheckIndex { public void testCheckFromIndexSize(int fromIndex, int size, int length, boolean withinBounds) { String expectedMessage = withinBounds ? null - : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). + : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). apply("checkFromIndexSize", List.of(fromIndex, size, length)).getMessage(); BiConsumer, IntSupplier> check = (ec, s) -> { @@ -248,27 +250,27 @@ public class CheckIndex { }; check.accept(AssertingOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, - assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length))); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, + assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length))); check.accept(IndexOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, - assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length))); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, + assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length))); check.accept(IndexOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, null)); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, null)); check.accept(IndexOutOfBoundsException.class, () -> Objects.checkFromIndexSize(fromIndex, size, length)); check.accept(ArrayIndexOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, - Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, + Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); check.accept(StringIndexOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, - Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, + Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); } @Test public void uniqueMessagesForCheckKinds() { BiFunction, IndexOutOfBoundsException> f = - Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new); + Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new); List messages = new ArrayList<>(); // Exact arguments diff --git a/jdk/test/java/util/Properties/CheckOverrides.java b/jdk/test/java/util/Properties/CheckOverrides.java new file mode 100644 index 00000000000..327143a66cb --- /dev/null +++ b/jdk/test/java/util/Properties/CheckOverrides.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/* + * @test + * @bug 8029891 + * @summary Test that the Properties class overrides all public+protected + * methods of all ancestor classes and interfaces + * @run main CheckOverrides + */ +public class CheckOverrides { + + public static void main(String[] args) { + Set pMethodSignatures = + Stream.of(Properties.class.getDeclaredMethods()) + .filter(CheckOverrides::isMethodOfInterest) + .map(MethodSignature::new) + .collect(Collectors.toSet()); + + Map unoverriddenMethods = new HashMap<>(); + for (Class superclass = Properties.class.getSuperclass(); + superclass != Object.class; + superclass = superclass.getSuperclass()) { + Stream.of(superclass.getDeclaredMethods()) + .filter(CheckOverrides::isMethodOfInterest) + .forEach(m -> unoverriddenMethods.putIfAbsent(new MethodSignature(m), m)); + } + unoverriddenMethods.keySet().removeAll(pMethodSignatures); + + if (!unoverriddenMethods.isEmpty()) { + throw new RuntimeException( + "The following methods should be overridden by Properties class:\n" + + unoverriddenMethods.values().stream() + .map(Method::toString) + .collect(Collectors.joining("\n ", " ", "\n")) + ); + } + } + + static boolean isMethodOfInterest(Method method) { + int mods = method.getModifiers(); + return !Modifier.isStatic(mods) && + (Modifier.isPublic(mods) || Modifier.isProtected(mods)); + } + + static class MethodSignature { + final Class returnType; + final String name; + final Class[] parameterTypes; + + MethodSignature(Method method) { + this(method.getReturnType(), method.getName(), method.getParameterTypes()); + } + + private MethodSignature(Class returnType, String name, Class[] parameterTypes) { + this.returnType = returnType; + this.name = name; + this.parameterTypes = parameterTypes; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MethodSignature that = (MethodSignature) o; + if (!returnType.equals(that.returnType)) return false; + if (!name.equals(that.name)) return false; + return Arrays.equals(parameterTypes, that.parameterTypes); + } + + @Override + public int hashCode() { + int result = returnType.hashCode(); + result = 31 * result + name.hashCode(); + result = 31 * result + Arrays.hashCode(parameterTypes); + return result; + } + } +} + diff --git a/jdk/test/java/util/Properties/CheckUnsynchronized.java b/jdk/test/java/util/Properties/CheckUnsynchronized.java new file mode 100644 index 00000000000..1b32cca0827 --- /dev/null +++ b/jdk/test/java/util/Properties/CheckUnsynchronized.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Enumeration; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; + +/* + * @test + * @bug 8029891 + * @summary Test Properties methods that do not synchronize any more + * @run main CheckUnsynchronized + */ +public class CheckUnsynchronized { + public static void main(String[] args) { + Properties props = new Properties(); + synchronized (props) { + props.setProperty("key", "value"); + System.out.println("contains(value)? " + + CompletableFuture.supplyAsync(() -> props.contains("value")).join()); + System.out.println("containsKey(key)? " + + CompletableFuture.supplyAsync(() -> props.containsKey("key")).join()); + System.out.println("containsValue(value)? " + + CompletableFuture.supplyAsync(() -> props.containsValue("value")).join()); + Enumeration elems = + CompletableFuture.supplyAsync(() -> props.elements()).join(); + System.out.println("first value from elements(): " + elems.nextElement()); + System.out.println("value from get(): " + + CompletableFuture.supplyAsync(() -> props.getProperty("key")).join()); + System.out.println("getOrDefault(\"missing\"): " + + CompletableFuture.supplyAsync(() -> props.getOrDefault("missing", "default")).join()); + System.out.println("isEmpty()? " + + CompletableFuture.supplyAsync(() -> props.isEmpty()).join()); + Enumeration keys = + CompletableFuture.supplyAsync(() -> props.keys()).join(); + System.out.println("first key from keys(): " + keys.nextElement()); + System.out.println("size(): " + + CompletableFuture.supplyAsync(() -> props.size()).join()); + } + } +} diff --git a/jdk/test/java/util/Properties/PropertiesSerialization.java b/jdk/test/java/util/Properties/PropertiesSerialization.java new file mode 100644 index 00000000000..2fcf1dc810a --- /dev/null +++ b/jdk/test/java/util/Properties/PropertiesSerialization.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Base64; +import java.util.Properties; + +/** + * @test + * @bug 8029891 + * @summary tests the compatibility of Properties serial form + * @run main PropertiesSerialization read + * + * To update this test in case the serial form of Properties changes, run this + * test with the 'write' flag, and copy the resulting output back into this + * file, replacing the existing String declaration(s). + */ +public class PropertiesSerialization { + private static final Properties TEST_PROPS; + static { + TEST_PROPS = new Properties(); + TEST_PROPS.setProperty("one", "two"); + TEST_PROPS.setProperty("buckle", "shoe"); + TEST_PROPS.setProperty("three", "four"); + TEST_PROPS.setProperty("shut", "door"); + } + + /** + * Base64 encoded string for Properties object + * Java version: 1.8.0 + **/ + private static final String TEST_SER_BASE64 = + "rO0ABXNyABRqYXZhLnV0aWwuUHJvcGVydGllczkS0HpwNj6YAgABTAAIZGVmYXVs" + + "dHN0ABZMamF2YS91dGlsL1Byb3BlcnRpZXM7eHIAE2phdmEudXRpbC5IYXNodGFi" + + "bGUTuw8lIUrkuAMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAI" + + "dwgAAAALAAAABHQAA29uZXQAA3R3b3QABHNodXR0AARkb29ydAAGYnVja2xldAAE" + + "c2hvZXQABXRocmVldAAEZm91cnhw"; + + public static void main(String[] args) throws IOException, + ClassNotFoundException { + if (args.length == 0) { + System.err.println("Run with 'read' or 'write'"); + System.err.println(" read mode: normal test mode."); + System.err.println(" Confirms that serial stream can"); + System.err.println(" be deserialized as expected."); + System.err.println(" write mode: meant for updating the test,"); + System.err.println(" should the serial form change."); + System.err.println(" Test output should be pasted"); + System.err.println(" back into the test source."); + return; + } + + Properties deserializedObject; + if ("read".equals(args[0])) { + ByteArrayInputStream bais = new + ByteArrayInputStream(Base64.getDecoder().decode(TEST_SER_BASE64)); + try (ObjectInputStream ois = new ObjectInputStream(bais)) { + deserializedObject = (Properties) ois.readObject(); + } + if (!TEST_PROPS.equals(deserializedObject)) { + throw new RuntimeException("deserializedObject not equals()"); + } + System.out.println("Test passed"); + } else if ("write".equals(args[0])) { + System.out.println("\nTo update the test, paste the following back " + + "into the test code:\n"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(TEST_PROPS); + oos.flush(); + oos.close(); + + byte[] byteArray = baos.toByteArray(); + // Check that the Properties deserializes correctly + ByteArrayInputStream bais = new ByteArrayInputStream(byteArray); + ObjectInputStream ois = new ObjectInputStream(bais); + Properties deser = (Properties)ois.readObject(); + if (!TEST_PROPS.equals(deser)) { + throw new RuntimeException("write: Deserialized != original"); + } + + // Now get a Base64 string representation of the serialized bytes. + final String base64 = Base64.getEncoder().encodeToString(byteArray); + // Check that we can deserialize the Base64 string we just computed. + ByteArrayInputStream bais2 = + new ByteArrayInputStream(Base64.getDecoder().decode(base64)); + ObjectInputStream ois2 = new ObjectInputStream(bais2); + Properties deser2 = (Properties)ois2.readObject(); + if (!TEST_PROPS.equals(deser2)) { + throw new RuntimeException("write: Deserialized base64 != " + + "original"); + } + System.out.println(dumpBase64SerialStream(base64)); + } + } + + private static final String INDENT = " "; + /* Based on: + * java/util/logging/HigherResolutionTimeStamps/SerializeLogRecored.java + */ + private static String dumpBase64SerialStream(String base64) { + // Generates the Java Pseudo code that can be cut & pasted into + // this test (see Jdk8SerializedLog and Jdk9SerializedLog below) + final StringBuilder sb = new StringBuilder(); + sb.append(INDENT).append(" /**").append('\n'); + sb.append(INDENT).append(" * Base64 encoded string for Properties object\n"); + sb.append(INDENT).append(" * Java version: ") + .append(System.getProperty("java.version")).append('\n'); + sb.append(INDENT).append(" **/").append('\n'); + sb.append(INDENT).append(" private static final String TEST_SER_BASE64 = ") + .append("\n").append(INDENT).append(" "); + final int last = base64.length() - 1; + for (int i=0; i -This is a test. - diff --git a/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java b/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java deleted file mode 100644 index 7a1969164f0..00000000000 --- a/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please 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 4126805 - * @ignore until 6842022 is resolved - * @run applet RestrictedBundleTest.html - * @summary I was able to reproduce this bug with 1.2b2, but not with the current 1.2 - * build. It appears that it was fixed by changes to the class-loading mechanism, - * which now throws a ClassNotFoundException where before it was propagating through - * a bogus ClassFormatError. Therefore, this is just an additional regression test - * for whatever bug that was. - */ - -import java.util.ResourceBundle; -import java.applet.Applet; -import java.util.MissingResourceException; - -public class RestrictedBundleTest extends Applet { - public void init() { - super.init(); - try { - ResourceBundle bundle = ResourceBundle.getBundle("unavailable.base.name"); - - throw new RuntimeException("Error: MissingResourceException is not thrown"); - } - catch (MissingResourceException e) { - // other types of error will propagate back out into the test harness - System.out.println("OK"); - } - } -} diff --git a/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java b/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java index abb90c0b695..55d4c2f1453 100644 --- a/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java +++ b/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java @@ -157,7 +157,7 @@ public class ServicesTest { Layer bootLayer = Layer.boot(); Configuration parent = bootLayer.configuration(); Configuration cf - = parent.resolveRequiresAndUses(finder, ModuleFinder.empty(), Set.of()); + = parent.resolveRequiresAndUses(finder, ModuleFinder.of(), Set.of()); ClassLoader scl = ClassLoader.getSystemClassLoader(); Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl); diff --git a/jdk/test/java/util/TimeZone/Bug4322313.java b/jdk/test/java/util/TimeZone/Bug4322313.java new file mode 100644 index 00000000000..fdd1f7c92ce --- /dev/null +++ b/jdk/test/java/util/TimeZone/Bug4322313.java @@ -0,0 +1,228 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4322313 + * @summary Make sure that new implementation of custom time zone + * support for TimeZone.getTimeZone() works correctly and the + * getDisplayName() methods are locale independent. + * @library /java/text/testlib + */ + +import java.io.*; +import java.text.*; +import java.util.*; + +public class Bug4322313 extends IntlTest { + private static final int MPM = 60 * 1000; /* Milliseconds per minute */ + private static final Object[][] VALIDS = { + /* given ID rawOffset normalized ID */ + {"GMT+00:00", 0, "GMT+00:00"}, + {"GMT+3:04", 184 * MPM, "GMT+03:04"}, + {"GMT+03:04", 184 * MPM, "GMT+03:04"}, + {"GMT+13:42", 822 * MPM, "GMT+13:42"}, + /* ISO-LATIN-1 digits */ + {"GMT+\u0030\u0031:\u0032\u0033", 83 * MPM, "GMT+01:23"}, + + {"GMT+0", 0, "GMT+00:00"}, + {"GMT+3", 180 * MPM, "GMT+03:00"}, + {"GMT+13", 780 * MPM, "GMT+13:00"}, + {"GMT+034", 34 * MPM, "GMT+00:34"}, + {"GMT+1034", 634 * MPM, "GMT+10:34"}, + + {"GMT-00:00", 0, "GMT-00:00"}, + {"GMT-3:04", -184 * MPM, "GMT-03:04"}, + {"GMT-03:04", -184 * MPM, "GMT-03:04"}, + {"GMT-13:42", -822 * MPM, "GMT-13:42"}, + /* ISO-LATIN-1 digits */ + {"GMT-\u0030\u0031:\u0032\u0033", -83 * MPM, "GMT-01:23"}, + + {"GMT-0", 0, "GMT-00:00"}, + {"GMT-3", -180 * MPM, "GMT-03:00"}, + {"GMT-13", -780 * MPM, "GMT-13:00"}, + {"GMT-034", -34 * MPM, "GMT-00:34"}, + {"GMT-1034", -634 * MPM, "GMT-10:34"}, + }; + + private static final String[] INVALIDS = { + "GMT+5:8", "GMT+11:1", "GMT+23:60", "GMT+24:13", + "GMT+0a:0A", "GMT +13:42", "GMT+ 13:42", "GMT+13 :42", + "GMT+13: 42", "GMT+421:950", "GMT+-13:42", "GMT+!13:42", + "GMT+a", "GMT+24", "GMT+060", "GMT+3003", + "GMT+42195", "GMT+-1", "GMT+-15", " GMT", + + "GMT-5:8", "GMT-11:1", "GMT-23:60", "GMT-24:13", + "GMT-0a:0A", "GMT -13:42", "GMT- 13:42", "GMT-13 :42", + "GMT-13: 42", "GMT-421:950", "GMT-+13:42", "GMT-#13:42", + "GMT-a", "GMT-24", "GMT-060", "GMT-2403", + "GMT-42195", "GMT-+1", "GMT-+15", "G M T", + "GMT+09:00 ", + }; + + void Test4322313() { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + boolean err = false; + + Locale[] locs = Locale.getAvailableLocales(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + + for (int i = 0; i < locs.length; i++) { + Locale.setDefault(locs[i]); + + /* Okay case */ + for (int k = 0; k < VALIDS.length; k++) { + TimeZone tz = TimeZone.getTimeZone((String)VALIDS[k][0]); + int offset; + + if (!tz.getID().equals(VALIDS[k][2])) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] Invalid TimeZone ID, expected:" + + VALIDS[k][2] + ", got:" + tz.getID() + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] Valid TimeZone ID, got:" + VALIDS[k][2]); + } + + offset = tz.getRawOffset(); + if (offset != (int)VALIDS[k][1]) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] Invalid RawOffset, expected:" + VALIDS[k][1] + + ", got:" + offset + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] Vaild RawOffset, got:" + offset); + } + + offset = tz.getDSTSavings(); + if (offset != 0) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] DSTSavings should be zero, got:" + offset + + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + VALIDS[k][0] + + "\"] DSTSavings is zero."); + } + } + + /* Error case */ + for (int k=0; k < INVALIDS.length; k++) { + TimeZone tz = TimeZone.getTimeZone(INVALIDS[k]); + int offset; + + if (!tz.getID().equals("GMT")) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] Invalid TimeZone ID, expected:GMT, got:" + + tz.getID() + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] Valid TimeZone ID, got:" + tz.getID()); + } + + offset = tz.getRawOffset(); + if (offset != 0) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] RawOffset should be zero, got:" + offset + + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] RawOffset is zero."); + } + + offset = tz.getDSTSavings(); + if (offset != 0) { + err = true; + System.err.println("\tFailed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] DSTSavings should be zero, got:" + offset + + ", " + tz); + } else { + logln("\tPassed [Locale=" + + Locale.getDefault() + ", \"" + INVALIDS[k] + + "\"] DSTSavings is zero."); + } + } + + // getDisplayName() tests + { + String normalizedID = "GMT-08:00"; + TimeZone tz = TimeZone.getTimeZone("GMT-8"); + String s; + s = tz.getDisplayName(true, tz.LONG); + if (!normalizedID.equals(s)) { + err = true; + System.err.println("getDisplayName returned unexpected name: " + s + + " in " + Locale.getDefault()); + } + s = tz.getDisplayName(true, tz.SHORT); + if (!normalizedID.equals(s)) { + err = true; + System.err.println("getDisplayName returned unexpected name: " + s + + " in " + Locale.getDefault()); + } + s = tz.getDisplayName(false, tz.LONG); + if (!normalizedID.equals(s)) { + err = true; + System.err.println("getDisplayName returned unexpected name: " + s + + " in " + Locale.getDefault()); + } + s = tz.getDisplayName(false, tz.SHORT); + if (!normalizedID.equals(s)) { + err = true; + System.err.println("getDisplayName returned unexpected name: " + s + + " in " + Locale.getDefault()); + } + } + } + } finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + } + if (err) { + errln("TimeZone.getTimeZone() test failed"); + } else { + logln("TimeZone.getTimeZone() test passed"); + } + } + + public static void main (String[] args) throws Exception { + new Bug4322313().run(args); + } +} diff --git a/jdk/test/java/util/TimeZone/Bug5097350.java b/jdk/test/java/util/TimeZone/Bug5097350.java new file mode 100644 index 00000000000..ff0894bf3d7 --- /dev/null +++ b/jdk/test/java/util/TimeZone/Bug5097350.java @@ -0,0 +1,63 @@ +/* + * 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 5097350 + * @summary Make sure that TimeZone.getTimeZone returns a clone of a cached TimeZone instance. + */ + +import java.util.*; +import java.text.*; + +public class Bug5097350 { + public static void main(String[] args) { + String[] tzids = TimeZone.getAvailableIDs(); + List ids = new ArrayList<>(tzids.length + 10); + ids.addAll(Arrays.asList(tzids)); + // add some custom ids + ids.add("GMT+1"); + ids.add("GMT-7:00"); + ids.add("GMT+10:20"); + ids.add("GMT-00:00"); + ids.add("GMT+00:00"); + + for (String id : ids) { + test(id); + } + } + + private static void test(String id) { + TimeZone tz1 = TimeZone.getTimeZone(id); + int offset1 = tz1.getRawOffset(); + tz1.setRawOffset(offset1 + 13 * 60 * 60 * 1000); + + TimeZone tz2 = TimeZone.getTimeZone(id); + if (tz1 == tz2) { + throw new RuntimeException("TimeZones are identical: " + id); + } + if (offset1 != tz2.getRawOffset()) { + throw new RuntimeException("Offset changed through aliasing: " + id); + } + } +} diff --git a/jdk/test/java/util/TimeZone/Bug8149452.java b/jdk/test/java/util/TimeZone/Bug8149452.java new file mode 100644 index 00000000000..eb4c0bced15 --- /dev/null +++ b/jdk/test/java/util/TimeZone/Bug8149452.java @@ -0,0 +1,58 @@ +/* + * 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 8149452 + * @summary Check the missing time zone names. + */ +import java.text.DateFormatSymbols; +import java.util.ArrayList; +import java.util.TimeZone; +import java.util.Arrays; +import java.util.List; + +public class Bug8149452 { + + public static void main(String[] args) { + + List listNotFound = new ArrayList<>(); + String[][] zoneStrings = DateFormatSymbols.getInstance() + .getZoneStrings(); + for (String tzID : TimeZone.getAvailableIDs()) { + if (!Arrays.stream(zoneStrings) + .anyMatch(zone -> tzID.equalsIgnoreCase(zone[0]))) { + // to ignore names for Etc/GMT[+-][0-9]+ which are not supported + if (!tzID.startsWith("Etc/GMT") && !tzID.startsWith("GMT")) { + listNotFound.add(tzID); + } + } + } + + if (!listNotFound.isEmpty()) { + throw new RuntimeException("Test Failed: Time Zone Strings for " + + listNotFound + " not found"); + } + + } + +} diff --git a/jdk/test/java/util/TimeZone/CheckDisplayNames.java b/jdk/test/java/util/TimeZone/CheckDisplayNames.java new file mode 100644 index 00000000000..efdb5cdf38d --- /dev/null +++ b/jdk/test/java/util/TimeZone/CheckDisplayNames.java @@ -0,0 +1,296 @@ +/* + * 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 6405639 8008577 + * @summary Validate timezone display names in + * src/java.base/share/classes/sun/util/resources/TimeZoneNames.java. + * @modules java.base/sun.util.resources + * @compile -XDignore.symbol.file CheckDisplayNames.java + * @run main/othervm -Djava.locale.providers=COMPAT,SPI CheckDisplayNames + */ + +import java.util.*; +import sun.util.resources.TimeZoneNames; + +/** + * CheckDisplayNames checks all available time zones in the Java run + * time environment and sees if those have their display names besides doing + * some other test cases. It outputs time zones that don't have display names + * if -source option is specified. + *
    + *
    + *    Usage: java CheckDisplayNames [-source]
    + *              -source ... produces source code for editing TimeZoneNames.java.
    + * 
    + *
    + */ +public class CheckDisplayNames { + + private static boolean err = false; + private static boolean src = false; + + private static Locale[] locales = Locale.getAvailableLocales(); + private static String[] zones = TimeZone.getAvailableIDs(); + + private static String[] zones_118 = { + "ACT", "Australia/Darwin", + "AET", "Australia/Sydney", + "AGT", "America/Buenos_Aires", + "ART", "Africa/Cairo", + "AST", "America/Anchorage", + "BET", "America/Sao_Paulo", + "BST", "Asia/Dacca", + "CAT", "Africa/Harare", + "CNT", "America/St_Johns", + "CST", "America/Chicago", + "CTT", "Asia/Shanghai", + "EAT", "Africa/Addis_Ababa", + "ECT", "Europe/Paris", +// "EET", "Africa/Istanbul", + "EST", "America/New_York", + "HST", "Pacific/Honolulu", + "IET", "America/Indiana/Indianapolis", +// Comment out for this test case fails as the result of L10N for hi_IN. +// "IST", "Asia/Calcutta", + "JST", "Asia/Tokyo", +// "MET", "Asia/Tehran", + "MIT", "Pacific/Apia", + "MST", "America/Denver", + "NET", "Asia/Yerevan", + "NST", "Pacific/Auckland", + "PLT", "Asia/Karachi", + "PNT", "America/Phoenix", + "PRT", "America/Puerto_Rico", + "PST", "America/Los_Angeles", + "SST", "Pacific/Guadalcanal", + "VST", "Asia/Saigon", + }; + + + public static void main(String[] argv) { + Locale reservedLocale = Locale.getDefault(); + try { + if (argv.length == 1 && "-source".equals(argv[0])) { + src = true; + } + + testDisplayNames(); + testRAWoffsetAndDisplayNames(); + test118DisplayNames(); + + if (err) { + throw new RuntimeException( + "TimeZone display name validation failed."); + } else { + System.out.println( + "\nAll test passed.\nTotal number of valid TimeZone id is " + + zones.length); + } + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + + } + + /* + * Checks if each timezone ID has display names. If it doesn't and + * "-source" option was specified, source code is generated. + */ + private static void testDisplayNames() { + System.out.println("Checking if each entry in TimeZoneNames is a valid TimeZone ID"); + + Locale.setDefault(Locale.US); + Enumeration data = new TimeZoneNames().getKeys(); + + while (data.hasMoreElements()) { + String name = (String)data.nextElement(); + String id = TimeZone.getTimeZone(name).getID(); + if (!name.equals(id)) { + System.err.println("\t" + name + " doesn't seem to be a valid TimeZone ID."); + err = true; + } + } + + System.out.println("Checking if each TimeZone ID has display names."); + + for (int i = 0; i < zones.length; i++) { + String id = zones[i]; + + if (id != null) { + if (id.startsWith("Etc/GMT")) { + continue; + } + if (id.indexOf("Riyadh8") != -1) { + continue; + } + if (id.equals("GMT0")) { + continue; + } + } + + TimeZone tz = TimeZone.getTimeZone(id); + String name = tz.getDisplayName(); + + if (name == null || name.startsWith("GMT+") || name.startsWith("GMT-")) { + if (src) { + System.out.println("\t {\"" + tz.getID() + "\", " + + "new String[] {\"Standard Time Name\", \"ST\",\n" + + "\t\t\t\t\t\t\"Daylight Time Name\", \"DT\"}},"); + } else { + System.err.println("\t" + tz.getID() + " doesn't seem to have display names"); + err = true; + } + } + } + } + + /* + * Compares + * - raw DST offset + * - short display names in non-DST + * - short display names in DST + * - long display names in DST + * of two timezones whose long display names in non-DST are same. + * If one of these are different, there may be a bug. + */ + private static void testRAWoffsetAndDisplayNames() { + System.out.println("Checking if each entry in TimeZoneNames is a valid TimeZone ID"); + + HashMap map = new HashMap(); + + for (int i = 0; i < locales.length; i++) { + map.clear(); + + for (int j = 0; j < zones.length; j++) { + TimeZone tz1 = TimeZone.getTimeZone(zones[j]); + String name = tz1.getDisplayName(false, TimeZone.LONG, locales[i]); + + if (map.containsKey(name)) { + TimeZone tz2 = map.get(name); + + int offset1 = tz1.getRawOffset(); + int offset2 = tz2.getRawOffset(); + if (offset1 != offset2) { + System.err.println("Two timezones which have the same long display name \"" + + name + "\" in non-DST have different DST offsets in " + + locales[i] + " locale.\n\tTimezone 1=" + + tz1.getID() + "(" + offset1 + ")\n\tTimezone 2=" + + tz2.getID() + "(" + offset2 + ")"); + } + + String name1 = tz1.getDisplayName(false, TimeZone.SHORT, locales[i]); + String name2 = tz2.getDisplayName(false, TimeZone.SHORT, locales[i]); + if (!(name1.equals("GMT") && name2.equals("GMT")) && + !(name1.equals("CET") && name2.equals("MET")) && + !(name1.equals("MET") && name2.equals("CET"))) { + if (!name1.equals(name2)) { + System.err.println("Two timezones which have the same short display name \"" + + name + + "\" in non-DST have different short display names in non-DST in " + + locales[i] + " locale.\n\tTimezone 1=" + + tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" + + tz2.getID() + "(" + name2 + ")"); + } + + name1 = tz1.getDisplayName(true, TimeZone.SHORT, locales[i]); + name2 = tz2.getDisplayName(true, TimeZone.SHORT, locales[i]); + if (!name1.equals(name2)) { + System.err.println("Two timezones which have the same short display name \"" + + name + + "\" in non-DST have different short display names in DST in " + + locales[i] + " locale.\n\tTimezone 1=" + + tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" + + tz2.getID() + "(" + name2 + ")"); + } + + name1 = tz1.getDisplayName(true, TimeZone.LONG, locales[i]); + name2 = tz2.getDisplayName(true, TimeZone.LONG, locales[i]); + if (!name1.equals(name2)) { + System.err.println("Two timezones which have the same long display name \"" + + name + + "\" in non-DST have different long display names in DST in " + + locales[i] + " locale.\n\tTimezone 1=" + + tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" + + tz2.getID() + "(" + name2 + ")"); + } + } + } else { + map.put(name, tz1); + } + } + } + } + + /* + * Compares three-letter timezones' display names with corresponding + * "popular" timezones. + */ + private static void test118DisplayNames() { + System.out.println("Checking compatibility of Java 1.1.X's three-letter timezones"); + + for (int i = 0; i < zones_118.length; i+=2) { + String id_118 = zones_118[i]; + String id_later = zones_118[i+1]; + String zone_118, zone_later, localename; + TimeZone tz_118 = TimeZone.getTimeZone(id_118); + TimeZone tz_later = TimeZone.getTimeZone(id_later); + + for (int j = 0; j < locales.length; j++) { + localename = locales[j].toString(); + zone_118 = tz_118.getDisplayName(false, TimeZone.SHORT, locales[j]); + zone_later = tz_later.getDisplayName(false, TimeZone.SHORT, locales[j]); + check(id_118, id_later, zone_118, zone_later, "short", "non-DST", localename); + + zone_118 = tz_118.getDisplayName(true, TimeZone.SHORT, locales[j]); + zone_later = tz_later.getDisplayName(true, TimeZone.SHORT, locales[j]); + check(id_118, id_later, zone_118, zone_later, "short", "DST", localename); + + zone_118 = tz_118.getDisplayName(false, TimeZone.LONG, locales[j]); + zone_later = tz_later.getDisplayName(false, TimeZone.LONG, locales[j]); + check(id_118, id_later, zone_118, zone_later, "long", "non-DST", localename); + + zone_118 = tz_118.getDisplayName(true, TimeZone.LONG, locales[j]); + zone_later = tz_later.getDisplayName(true, TimeZone.LONG, locales[j]); + check(id_118, id_later, zone_118, zone_later, "long", "DST", localename); + } + } + } + + private static void check(String zoneID_118, String zoneID_later, + String zonename_118, String zonename_later, + String format, String dst, String loc) { + if (!zonename_118.equals(zonename_later)) { + System.err.println("JDK 118 TimeZone \"" + zoneID_118 + + "\" has a different " + format + + " display name from its equivalent timezone \"" + + zoneID_later + "\" in " + dst + " in " + loc + " locale."); + System.err.println(" Got: " + zonename_118 + ", Expected: " + + zonename_later); + err = true; + } + } + +} diff --git a/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.html b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.html new file mode 100644 index 00000000000..1fa0659ed63 --- /dev/null +++ b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.html @@ -0,0 +1,74 @@ + + + + + + Disable Auto-adjust Daylight Saving Time Test + + + +This applet tests the platform time zone detection on all platforms (Part I) +and on/off of DST adjustment on Windows (Part II). + +Part I: + +Observe the displayed Time zone ID and the local time. If you can change +the platform time zone setting, try several time zones. If both the ID and +the local time, including the time zone name and its time zone offset, are +always correct, Part I passes. Note that some time zone IDs have their +aliases that may be displayed. For example, "US/Pacific" is an alias of +"America/Los_Angeles". + +If you are running this applet in non-English locale, the time zone names +can be displayed in the local language and English by pushing the +English/Local button. + +If platform time zones are NOT detected correctly, press the Fail button +to finish this applet. + +If this platform is Windows, proceed to Part II. Otherwise, press the Pass +button to finish this applet. + +Part II: + +Note that Part II may require the Administrator privilege to change +Windows setting. + + 1. Open the Date and Time control panel. + 2. Select any time zone where daylight saving time is *currently* in effect, + such as "(GMT-08:00) Pacific Time (US & Canada); Tijuana", + "(GMT+10:00) Canberra, Melbourne, Sydney", and Apply. + 3. Observe the local time on the control panel (Date&Time pane) and + the applet local time should be the same (daylight time). + 4. Clear "Automatically adjust clock for daylight saving changes" and Apply. + 5. Observe the two local times should be the same (standard time). + 6. Select "Automatically adjust clock for daylight saving changes" and Apply. + +If the local time in the control panel and applet are always the same, +then this test passes. Press the Pass or Fail button based on the Part II +result and finish this applet. + + + + diff --git a/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.java b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.java new file mode 100644 index 00000000000..a6d3ac50866 --- /dev/null +++ b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4296930 5033603 7092679 + * @summary Make sure that Java runtime detects the platform time zone + * correctly. Also make sure that the system time zone detection code + * detects the "Automatically adjust clock for daylight saving + * changes" setting correctly on Windows. + * @run applet/manual=yesno DefaultTimeZoneTest.html + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.text.*; +import java.util.*; + +public class DefaultTimeZoneTest extends JApplet implements Runnable { + static final String FORMAT = "yyyy-MM-dd HH:mm:ss zzzz (XXX)"; + JLabel tzid; + JLabel label; + SimpleDateFormat sdf = new SimpleDateFormat(FORMAT); + JButton button = new JButton("English"); + Thread clock; + boolean english = false; + + @Override + public void init() { + tzid = new JLabel("Time zone ID: " + sdf.getTimeZone().getID(), SwingConstants.CENTER); + tzid.setAlignmentX(Component.CENTER_ALIGNMENT); + label = new JLabel(sdf.format(new Date()), SwingConstants.CENTER); + label.setAlignmentX(Component.CENTER_ALIGNMENT); + button.addActionListener(new ActionListener() { + @Override + @SuppressWarnings("deprecation") + public void actionPerformed(ActionEvent e) { + english = (english == false); + Locale loc = english ? Locale.US : Locale.getDefault(); + sdf = new SimpleDateFormat(FORMAT, loc); + button.setLabel(!english ? "English" : "Local"); + } + }); + button.setAlignmentX(Component.CENTER_ALIGNMENT); + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); + panel.add(Box.createRigidArea(new Dimension(0, 10))); + panel.add(tzid); + panel.add(Box.createRigidArea(new Dimension(0, 5))); + panel.add(label); + panel.add(Box.createRigidArea(new Dimension(0, 10))); + panel.add(button); + getContentPane().add(panel); + } + + @Override + public void start() { + clock = new Thread(this); + clock.start(); + } + + @Override + public void stop() { + clock = null; + } + + @Override + public void run() { + Thread me = Thread.currentThread(); + + while (clock == me) { + // Reset the default time zone so that + // TimeZone.getDefault will detect the platform time zone + TimeZone.setDefault(null); + System.setProperty("user.timezone", ""); + TimeZone tz = TimeZone.getDefault(); + sdf.setTimeZone(tz); + tzid.setText("Time zone ID: " + tz.getID()); + label.setText(sdf.format(new Date())); + repaint(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } +} diff --git a/jdk/test/java/util/TimeZone/HongKong.java b/jdk/test/java/util/TimeZone/HongKong.java new file mode 100644 index 00000000000..ef9c3f923f5 --- /dev/null +++ b/jdk/test/java/util/TimeZone/HongKong.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +/* + * @test + * @bug 4487276 8008577 + * @summary Verify that Hong Kong locale uses traditional Chinese names. + * @run main/othervm -Djava.locale.providers=COMPAT,SPI HongKong + */ + +import java.util.Locale; +import java.util.TimeZone; + +public class HongKong { + public static void main(String[] args) { + Locale reservedLocale = Locale.getDefault(); + try { + Locale.setDefault(new Locale("zh", "HK")); + checkCountry(Locale.GERMANY, "\u5fb7\u570b"); + checkCountry(Locale.FRANCE, "\u6cd5\u570b"); + checkCountry(Locale.ITALY, "\u7fa9\u5927\u5229"); + checkTimeZone("Asia/Shanghai", + "\u4e2d\u570b\u6a19\u6e96\u6642\u9593"); + } finally { + // restore the reserved locale + Locale.setDefault(reservedLocale); + } + } + + private static void checkCountry(Locale country, String expected) { + String actual = country.getDisplayCountry(); + if (!expected.equals(actual)) { + throw new RuntimeException(); + } + } + + private static void checkTimeZone(String timeZoneID, String expected) { + TimeZone timeZone = TimeZone.getTimeZone(timeZoneID); + String actual = timeZone.getDisplayName(); + if (!expected.equals(actual)) { + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/util/TimeZone/IDTest.java b/jdk/test/java/util/TimeZone/IDTest.java new file mode 100644 index 00000000000..d5396b619b8 --- /dev/null +++ b/jdk/test/java/util/TimeZone/IDTest.java @@ -0,0 +1,121 @@ +/* + * 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 4509255 5055567 6176318 7090844 + * @summary Tests consistencies of time zone IDs. + */ + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeMap; + +public class IDTest { + public static void main(String[] args) { + Set ids = new HashSet<>(); + Map> tree = new TreeMap<>(); + + String[] tzs = TimeZone.getAvailableIDs(); + String[] tzs2 = TimeZone.getAvailableIDs(); + if (tzs.length != tzs2.length) { + throw new RuntimeException("tzs.length(" + tzs.length + + ") != tzs2.length(" + tzs2.length + ")"); + } + for (int i = 0; i < tzs.length; i++) { + if (tzs[i] != tzs2[i]) { + throw new RuntimeException(i + ": " + tzs[i] + " != " + tzs2[i]); + } + } + + System.out.println("Total: " + tzs.length + " time zone IDs"); + for (String id : tzs) { + ids.add(id); + TimeZone tz = TimeZone.getTimeZone(id); + Integer offset = tz.getRawOffset(); + Set s = tree.get(offset); + if (s == null) { + s = new HashSet<>(); + tree.put(offset, s); + } + s.add(id); + } + + for (Integer key : tree.keySet()) { + Set s1 = tree.get(key); + + // Make sure no duplicates in the other sets + for (Integer k : tree.keySet()) { + if (k.equals(key)) { + continue; + } + Set s2 = new HashSet<>(tree.get(k)); + s2.retainAll(s1); + if (!s2.isEmpty()) { + throw new RuntimeException("s1 included in the subset for " + (k.intValue()/60000) + + " (" + s2 + " shouldn't be in s1)"); + } + } + + // Check the getAvailableIDs(int) call to return the same + // set of IDs + int offset = key.intValue(); + tzs = TimeZone.getAvailableIDs(offset); + tzs2 = TimeZone.getAvailableIDs(offset); + if (!Arrays.equals(tzs, tzs2)) { + throw new RuntimeException("inconsistent tzs from getAvailableIDs("+offset+")"); + } + Set s2 = new HashSet<>(); + s2.addAll(Arrays.asList(tzs)); + if (!s1.equals(s2)) { + throw new RuntimeException("s1 != s2 for " + offset/60000 + + " (diff=" + getDiff(s1, s2) + ")"); + } + if (!ids.containsAll(s2)) { + throw new RuntimeException("s2 isn't a subset of ids (" + getDiff(s2, ids) + + " not in ids)"); + } + } + + for (Integer key : tree.keySet()) { + Set s1 = tree.get(key); + ids.removeAll(s1); + } + if (!ids.isEmpty()) { + throw new RuntimeException("ids didn't become empty. (" + ids + ")"); + } + } + + private static String getDiff(Set set1, Set set2) { + Set s1 = new HashSet<>(set1); + s1.removeAll(set2); + + Set s2 = new HashSet<>(set2); + s2.removeAll(set1); + s2.addAll(s1); + return s2.toString(); + } +} diff --git a/jdk/test/java/util/TimeZone/TimeZoneBoundaryTest.java b/jdk/test/java/util/TimeZone/TimeZoneBoundaryTest.java new file mode 100644 index 00000000000..a1d44ea080d --- /dev/null +++ b/jdk/test/java/util/TimeZone/TimeZoneBoundaryTest.java @@ -0,0 +1,491 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 /java/text/testlib + * @summary test Time Zone Boundary + */ + +import java.text.*; +import java.util.*; + +/** + * A test which discovers the boundaries of DST programmatically and verifies + * that they are correct. + */ +public class TimeZoneBoundaryTest extends IntlTest +{ + static final int ONE_SECOND = 1000; + static final int ONE_MINUTE = 60*ONE_SECOND; + static final int ONE_HOUR = 60*ONE_MINUTE; + static final long ONE_DAY = 24*ONE_HOUR; + static final long ONE_YEAR = (long)(365.25 * ONE_DAY); + static final long SIX_MONTHS = ONE_YEAR / 2; + + static final int MONTH_LENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31}; + + // These values are empirically determined to be correct + static final long PST_1997_BEG = 860320800000L; + static final long PST_1997_END = 877856400000L; + + // Minimum interval for binary searches in ms; should be no larger + // than 1000. + static final long INTERVAL = 10; // Milliseconds + + static final String AUSTRALIA = "Australia/Adelaide"; + static final long AUSTRALIA_1997_BEG = 877797000000L; + static final long AUSTRALIA_1997_END = 859653000000L; + + public static void main(String[] args) throws Exception { + new TimeZoneBoundaryTest().run(args); + } + + /** + * Date.toString().substring() Boundary Test + * Look for a DST changeover to occur within 6 months of the given Date. + * The initial Date.toString() should yield a string containing the + * startMode as a SUBSTRING. The boundary will be tested to be + * at the expectedBoundary value. + */ + void findDaylightBoundaryUsingDate(Date d, String startMode, long expectedBoundary) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + if (d.toString().indexOf(startMode) == -1) + { + logln("Error: " + startMode + " not present in " + d); + } + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + SIX_MONTHS; + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + String s = new Date(mid).toString(); + // logln(s); + if (s.indexOf(startMode) != -1) + { + min = mid; + } + else + { + max = mid; + } + } + + logln("Date Before: " + showDate(min)); + logln("Date After: " + showDate(max)); + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, long expectedBoundary) + { + findDaylightBoundaryUsingTimeZone(d, startsInDST, expectedBoundary, + TimeZone.getDefault()); + } + + void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, + long expectedBoundary, TimeZone tz) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + SIX_MONTHS; + + if (tz.inDaylightTime(d) != startsInDST) + { + errln("FAIL: " + tz.getID() + " inDaylightTime(" + + d + ") != " + startsInDST); + startsInDST = !startsInDST; // Flip over; find the apparent value + } + + if (tz.inDaylightTime(new Date(max)) == startsInDST) + { + errln("FAIL: " + tz.getID() + " inDaylightTime(" + + (new Date(max)) + ") != " + (!startsInDST)); + return; + } + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + boolean isIn = tz.inDaylightTime(new Date(mid)); + if (isIn == startsInDST) + { + min = mid; + } + else + { + max = mid; + } + } + + logln(tz.getID() + " Before: " + showDate(min, tz)); + logln(tz.getID() + " After: " + showDate(max, tz)); + + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + private static String showDate(long l) + { + return showDate(new Date(l)); + } + + @SuppressWarnings("deprecation") + private static String showDate(Date d) + { + return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) + + " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) + + " \"" + d + "\" = " + + d.getTime(); + } + + private static String showDate(long l, TimeZone z) + { + return showDate(new Date(l), z); + } + + @SuppressWarnings("deprecation") + private static String showDate(Date d, TimeZone zone) + { + DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + fmt.setTimeZone(zone); + return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) + + " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) + + " \"" + d + "\" = " + + fmt.format(d); + } + + private static String showNN(int n) + { + return ((n < 10) ? "0" : "") + n; + } + + /** + * Given a date, a TimeZone, and expected values for inDaylightTime, + * useDaylightTime, zone and DST offset, verify that this is the case. + */ + void verifyDST(Date d, TimeZone time_zone, + boolean expUseDaylightTime, boolean expInDaylightTime, + int expZoneOffset, int expDSTOffset) + { + logln("-- Verifying time " + d + + " in zone " + time_zone.getID()); + + if (time_zone.inDaylightTime(d) == expInDaylightTime) + logln("PASS: inDaylightTime = " + time_zone.inDaylightTime(d)); + else + errln("FAIL: inDaylightTime = " + time_zone.inDaylightTime(d)); + + if (time_zone.useDaylightTime() == expUseDaylightTime) + logln("PASS: useDaylightTime = " + time_zone.useDaylightTime()); + else + errln("FAIL: useDaylightTime = " + time_zone.useDaylightTime()); + + if (time_zone.getRawOffset() == expZoneOffset) + logln("PASS: getRawOffset() = " + expZoneOffset/(double)ONE_HOUR); + else + errln("FAIL: getRawOffset() = " + time_zone.getRawOffset()/(double)ONE_HOUR + + "; expected " + expZoneOffset/(double)ONE_HOUR); + + GregorianCalendar gc = new GregorianCalendar(time_zone); + gc.setTime(d); + int offset = time_zone.getOffset(gc.get(gc.ERA), gc.get(gc.YEAR), gc.get(gc.MONTH), + gc.get(gc.DAY_OF_MONTH), gc.get(gc.DAY_OF_WEEK), + ((gc.get(gc.HOUR_OF_DAY) * 60 + + gc.get(gc.MINUTE)) * 60 + + gc.get(gc.SECOND)) * 1000 + + gc.get(gc.MILLISECOND)); + if (offset == expDSTOffset) + logln("PASS: getOffset() = " + offset/(double)ONE_HOUR); + else + errln("FAIL: getOffset() = " + offset/(double)ONE_HOUR + + "; expected " + expDSTOffset/(double)ONE_HOUR); + } + + @SuppressWarnings("deprecation") + public void TestBoundaries() + { + TimeZone pst = TimeZone.getTimeZone("PST"); + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(pst); + + // DST changeover for PST is 4/6/1997 at 2 hours past midnight + Date d = new Date(97,Calendar.APRIL,6); + + // i is minutes past midnight standard time + for (int i=60; i<=180; i+=15) + { + boolean inDST = (i >= 120); + Date e = new Date(d.getTime() + i*60*1000); + verifyDST(e, pst, true, inDST, -8*ONE_HOUR, + inDST ? -7*ONE_HOUR : -8*ONE_HOUR); + } + + logln("========================================"); + findDaylightBoundaryUsingDate(new Date(97,0,1), "PST", PST_1997_BEG); + logln("========================================"); + findDaylightBoundaryUsingDate(new Date(97,6,1), "PDT", PST_1997_END); + + // Southern hemisphere test + logln("========================================"); + TimeZone z = TimeZone.getTimeZone(AUSTRALIA); + findDaylightBoundaryUsingTimeZone(new Date(97,0,1), true, AUSTRALIA_1997_END, z); + + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,0,1), false, PST_1997_BEG); + logln("========================================"); + findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true, PST_1997_END); + } finally { + TimeZone.setDefault(save); + } + } + + void testUsingBinarySearch(SimpleTimeZone tz, Date d, long expectedBoundary) + { + // Given a date with a year start, find the Daylight onset + // and end. The given date should be 1/1/xx in some year. + + // Use a binary search, assuming that we have a Standard + // time at the midpoint. + long min = d.getTime(); + long max = min + (long)(365.25 / 2 * ONE_DAY); + + // First check the boundaries + boolean startsInDST = tz.inDaylightTime(d); + + if (tz.inDaylightTime(new Date(max)) == startsInDST) + { + logln("Error: inDaylightTime(" + (new Date(max)) + ") != " + (!startsInDST)); + } + + while ((max - min) > INTERVAL) + { + long mid = (min + max) >> 1; + if (tz.inDaylightTime(new Date(mid)) == startsInDST) + { + min = mid; + } + else + { + max = mid; + } + } + + logln("Binary Search Before: " + showDate(min)); + logln("Binary Search After: " + showDate(max)); + + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && mindelta <= INTERVAL && + mindelta >= 0 && mindelta <= INTERVAL) + logln("PASS: Expected boundary at " + expectedBoundary); + else + errln("FAIL: Expected boundary at " + expectedBoundary); + } + + /* + static void testUsingMillis(Date d, boolean startsInDST) + { + long millis = d.getTime(); + long max = millis + (long)(370 * ONE_DAY); // A year plus extra + + boolean lastDST = startsInDST; + while (millis < max) + { + cal.setTime(new Date(millis)); + boolean inDaylight = cal.inDaylightTime(); + + if (inDaylight != lastDST) + { + logln("Switch " + (inDaylight ? "into" : "out of") + + " DST at " + (new Date(millis))); + lastDST = inDaylight; + } + + millis += 15*ONE_MINUTE; + } + } + */ + + /** + * Test new rule formats. + */ + @SuppressWarnings("deprecation") + public void TestNewRules() + { + //logln(Locale.getDefault().getDisplayName()); + //logln(TimeZone.getDefault().getID()); + //logln(new Date(0)); + + if (true) + { + // Doesn't matter what the default TimeZone is here, since we + // are creating our own TimeZone objects. + + SimpleTimeZone tz; + + logln("-----------------------------------------------------------------"); + logln("Aug 2ndTues .. Mar 15"); + tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_1", + Calendar.AUGUST, 2, Calendar.TUESDAY, 2*ONE_HOUR, + Calendar.MARCH, 15, 0, 2*ONE_HOUR); + //logln(tz.toString()); + logln("========================================"); + testUsingBinarySearch(tz, new Date(97,0,1), 858416400000L); + logln("========================================"); + testUsingBinarySearch(tz, new Date(97,6,1), 871380000000L); + + logln("-----------------------------------------------------------------"); + logln("Apr Wed>=14 .. Sep Sun<=20"); + tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_2", + Calendar.APRIL, 14, -Calendar.WEDNESDAY, 2*ONE_HOUR, + Calendar.SEPTEMBER, -20, -Calendar.SUNDAY, 2*ONE_HOUR); + //logln(tz.toString()); + logln("========================================"); + testUsingBinarySearch(tz, new Date(97,0,1), 861184800000L); + logln("========================================"); + testUsingBinarySearch(tz, new Date(97,6,1), 874227600000L); + } + + /* + if (true) + { + logln("========================================"); + logln("Stepping using millis"); + testUsingMillis(new Date(97,0,1), false); + } + + if (true) + { + logln("========================================"); + logln("Stepping using fields"); + testUsingFields(1997, false); + } + + if (false) + { + cal.clear(); + cal.set(1997, 3, 5, 10, 0); + // cal.inDaylightTime(); + logln("Date = " + cal.getTime()); + logln("Millis = " + cal.getTime().getTime()/3600000); + } + */ + } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + // Long Bug + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + //public void Test3() + //{ + // findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true); + //} + + /** + * Find boundaries by stepping. + */ + @SuppressWarnings("deprecation") + void findBoundariesStepwise(int year, long interval, TimeZone z, int expectedChanges) + { + Date d = new Date(year - 1900, Calendar.JANUARY, 1); + long time = d.getTime(); // ms + long limit = time + ONE_YEAR + ONE_DAY; + boolean lastState = z.inDaylightTime(d); + int changes = 0; + logln("-- Zone " + z.getID() + " starts in " + year + " with DST = " + lastState); + logln("useDaylightTime = " + z.useDaylightTime()); + while (time < limit) + { + d.setTime(time); + boolean state = z.inDaylightTime(d); + if (state != lastState) + { + logln((state ? "Entry " : "Exit ") + + "at " + d); + lastState = state; + ++changes; + } + time += interval; + } + if (changes == 0) + { + if (!lastState && !z.useDaylightTime()) logln("No DST"); + else errln("FAIL: Timezone<" + z.getID() + "> DST all year, or no DST with true useDaylightTime"); + } + else if (changes != 2) + { + errln("FAIL: Timezone<" + z.getID() + "> " + changes + " changes seen; should see 0 or 2"); + } + else if (!z.useDaylightTime()) + { + errln("FAIL: Timezone<" + z.getID() + "> useDaylightTime false but 2 changes seen"); + } + if (changes != expectedChanges) + { + errln("FAIL: Timezone<" + z.getID() + "> " + changes + " changes seen; expected " + expectedChanges); + } + } + + public void TestStepwise() + { + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("ACT"), 0); + // "EST" is disabled because its behavior depends on the mapping property. (6466476). + //findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("EST"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("HST"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("PST"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("PST8PDT"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("SystemV/PST"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("SystemV/PST8PDT"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Japan"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Europe/Paris"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("America/Los_Angeles"), 2); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone(AUSTRALIA), 2); + } +} diff --git a/jdk/test/java/util/TimeZone/TimeZoneRegression.java b/jdk/test/java/util/TimeZone/TimeZoneRegression.java new file mode 100644 index 00000000000..8b9e2f4a22a --- /dev/null +++ b/jdk/test/java/util/TimeZone/TimeZoneRegression.java @@ -0,0 +1,995 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429 + * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960 + * 4966229 6433179 6851214 8007520 8008577 + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression + */ + +import java.util.*; +import java.io.*; +import java.text.*; + +public class TimeZoneRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new TimeZoneRegression().run(args); + } + + public void Test4052967() { + logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***"); + String id = TimeZone.getDefault().getID(); + logln("user.timezone: " + System.getProperty("user.timezone", "")); + logln("TimeZone.getDefault().getID(): " + id); + logln(new Date().toString()); + logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***"); + } + + public void Test4073209() { + TimeZone z1 = TimeZone.getTimeZone("PST"); + TimeZone z2 = TimeZone.getTimeZone("PST"); + if (z1 == z2) { + errln("Fail: TimeZone should return clones"); + } + } + + @SuppressWarnings("deprecation") + public void Test4073215() { + SimpleTimeZone z = new SimpleTimeZone(0, "GMT"); + if (z.useDaylightTime()) { + errln("Fail: Fix test to start with non-DST zone"); + } + z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0); + z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0); + if (!z.useDaylightTime()) { + errln("Fail: DST not active"); + } + if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) || + !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) || + z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) { + errln("Fail: DST not working as expected"); + } + } + + /** + * The expected behavior of TimeZone around the boundaries is: + * (Assume transition time of 2:00 AM) + * day of onset 1:59 AM STD = display name 1:59 AM ST + * 2:00 AM STD = display name 3:00 AM DT + * day of end 0:59 AM STD = display name 1:59 AM DT + * 1:00 AM STD = display name 1:00 AM ST + */ + public void Test4084933() { + // test both SimpleTimeZone and ZoneInfo objects. + // @since 1.4 + sub4084933(getPST()); + sub4084933(TimeZone.getTimeZone("PST")); + } + + private void sub4084933(TimeZone tz) { + long offset1 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)); + long offset2 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1); + + long offset3 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)); + long offset4 = tz.getOffset(1, + 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1); + + /* + * The following was added just for consistency. It shows that going *to* Daylight + * Savings Time (PDT) does work at 2am. + */ + + long offset5 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)); + long offset6 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1); + + long offset7 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)); + long offset8 = tz.getOffset(1, + 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1); + + long SToffset = -8 * 60*60*1000L; + long DToffset = -7 * 60*60*1000L; + if (offset1 != SToffset || offset2 != SToffset || + offset3 != SToffset || offset4 != DToffset || + offset5 != DToffset || offset6 != SToffset || + offset7 != SToffset || offset8 != SToffset) + errln("Fail: TimeZone misbehaving"); { + } + } + + public void Test4096952() { + String[] ZONES = { "GMT", "MET", "IST" }; + boolean pass = true; + try { + for (int i=0; i= ONE_DAY) { + millis -= ONE_DAY; + ++date; + dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7); + } + + tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA), + testCal.get(Calendar.YEAR), + testCal.get(Calendar.MONTH), + date, + dow, + millis); + tzRawOffset = testTZ.getRawOffset(); + tzOffsetFloat = new Float((float)tzOffset/(float)3600000); + tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000); + + Date testDate = testCal.getTime(); + + boolean inDaylightTime = testTZ.inDaylightTime(testDate); + SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm"); + sdf.setCalendar(testCal); + String inDaylightTimeString; + + boolean passed; + + if (inDaylightTime) + { + inDaylightTimeString = " DST "; + passed = (tzOffset == (tzRawOffset + 3600000)); + } + else + { + inDaylightTimeString = " "; + passed = (tzOffset == tzRawOffset); + } + + String output = testTZ.getID() + " " + sdf.format(testDate) + + " Offset(" + tzOffsetFloat + ")" + + " RawOffset(" + tzRawOffsetFloat + ")" + + " " + millis/(float)3600000 + " " + + inDaylightTimeString; + + if (passed) + output += " "; + else + output += "ERROR"; + + if (passed) logln(output); else errln(output); + return passed; + } + + /** + * CANNOT REPRODUDE + * + * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never + * should have been made public. It's simply too hard to use correctly. + * + * The original test code failed to do the following: + * (1) Call Calendar.setTime() before getting the fields! + * (2) Use the right millis (as usual) for getOffset(); they were passing + * in the MILLIS field, instead of the STANDARD MILLIS IN DAY. + * When you fix these two problems, the test passes, as expected. + */ + public void Test4126678() { + // Note: this test depends on the PST time zone. + TimeZone initialZone = TimeZone.getDefault(); + + // test both SimpleTimeZone and ZoneInfo objects. + // @since 1.4 + sub4126678(getPST()); + sub4126678(TimeZone.getTimeZone("PST")); + + // restore the initial time zone so that this test case + // doesn't affect the others. + TimeZone.setDefault(initialZone); + } + + @SuppressWarnings("deprecation") + private void sub4126678(TimeZone tz) { + Calendar cal = Calendar.getInstance(); + TimeZone.setDefault(tz); + cal.setTimeZone(tz); + + Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0); + // the dt value is local time in PST. + if (!tz.inDaylightTime(dt)) + errln("We're not in Daylight Savings Time and we should be.\n"); + + cal.setTime(dt); + int era = cal.get(Calendar.ERA); + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH); + int day = cal.get(Calendar.DATE); + int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); + int millis = cal.get(Calendar.MILLISECOND) + + (cal.get(Calendar.SECOND) + + (cal.get(Calendar.MINUTE) + + (cal.get(Calendar.HOUR) * 60) * 60) * 1000) - + cal.get(Calendar.DST_OFFSET); + + long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis); + long raw_offset = tz.getRawOffset(); + if (offset == raw_offset) { + errln("Offsets should not match when in DST"); + } + } + + /** + * TimeZone.getAvailableIDs(int) throws exception for certain values, + * due to a faulty constant in TimeZone.java. + */ + public void Test4151406() { + int max = 0; + for (int h=-28; h<=30; ++h) { + // h is in half-hours from GMT; rawoffset is in millis + int rawoffset = h * 1800000; + int hh = (h<0) ? -h : h; + String hname = ((h<0) ? "GMT-" : "GMT+") + + ((hh/2 < 10) ? "0" : "") + + (hh/2) + ':' + + ((hh%2==0) ? "00" : "30"); + try { + String[] ids = TimeZone.getAvailableIDs(rawoffset); + if (ids.length > max) max = ids.length; + logln(hname + ' ' + ids.length + + ((ids.length > 0) ? (" e.g. " + ids[0]) : "")); + } catch (Exception e) { + errln(hname + ' ' + "Fail: " + e); + } + } + logln("Maximum zones per offset = " + max); + } + + public void Test4151429() { + try { + TimeZone tz = TimeZone.getTimeZone("GMT"); + String name = tz.getDisplayName(true, Integer.MAX_VALUE, + Locale.getDefault()); + errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()"); + } catch(IllegalArgumentException e) {} + } + + /** + * SimpleTimeZone accepts illegal DST savings values. These values + * must be non-zero. There is no upper limit at this time. + */ + public void Test4154525() { + final int GOOD = 1, BAD = 0; + int[] DATA = { + 1, GOOD, + 0, BAD, + -1, BAD, + 60*60*1000, GOOD, + Integer.MIN_VALUE, BAD, + // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time + }; + for (int i=0; i) should work but throws " + ex) + : ", ) should fail but doesn't")); + } + + ex = null; + try { + SimpleTimeZone temp = new SimpleTimeZone(0, "Z", + GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME, + month, day, dayOfWeek, time); + } catch (IllegalArgumentException e) { + ex = e; + } + if ((ex == null) != shouldBeGood) { + errln("SimpleTimeZone(, month=" + month + ", day=" + day + + ", dayOfWeek=" + dayOfWeek + ", time=" + time + + (shouldBeGood ? (") should work but throws " + ex) + : ") should fail but doesn't")); + } + } + } + + /** + * SimpleTimeZone.getOffset accepts illegal arguments. + */ + public void Test4154650() { + final int GOOD=1, BAD=0; + final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST; + final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000; + int[] DATA = { + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME, + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME, + + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0, + GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1, + BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000, + }; + + TimeZone tz = TimeZone.getDefault(); + for (int i=0; i " + DATA[i+1] + ", exp " + DATA[i+2]); + } + } + } + + /** + * SimpleTimeZone allows invalid DOM values. + */ + public void Test4184229() { + SimpleTimeZone zone = null; + try { + zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 startDay"); + } catch(IllegalArgumentException e) { + logln("(a) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 endDay"); + } catch(IllegalArgumentException e) { + logln("(b) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000); + errln("Failed. No exception has been thrown for DOM -1 startDay +savings"); + } catch(IllegalArgumentException e) { + logln("(c) " + e.getMessage()); + } + try { + zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000); + errln("Failed. No exception has been thrown for DOM -1 endDay +savings"); + } catch(IllegalArgumentException e) { + logln("(d) " + e.getMessage()); + } + // Make a valid constructor call for subsequent tests. + zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0); + try { + zone.setStartRule(0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings"); + } catch(IllegalArgumentException e) { + logln("(e) " + e.getMessage()); + } + try { + zone.setStartRule(0, -1, 0); + errln("Failed. No exception has been thrown for DOM -1 setStartRule"); + } catch(IllegalArgumentException e) { + logln("(f) " + e.getMessage()); + } + try { + zone.setEndRule(0, -1, 0, 0); + errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings"); + } catch(IllegalArgumentException e) { + logln("(g) " + e.getMessage()); + } + try { + zone.setEndRule(0, -1, 0); + errln("Failed. No exception has been thrown for DOM -1 setEndRule"); + } catch(IllegalArgumentException e) { + logln("(h) " + e.getMessage()); + } + } + + /** + * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get + * of 2/29/1996 (leap day). + */ + public void Test4208960 () { + // test both SimpleTimeZone and ZoneInfo objects. + // @since 1.4 + sub4208960(getPST()); + sub4208960(TimeZone.getTimeZone("PST")); + } + + private void sub4208960(TimeZone tz) { + try { + int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29, + Calendar.THURSDAY, 0); + } catch (IllegalArgumentException e) { + errln("FAILED: to get TimeZone.getOffset(2/29/96)"); + } + try { + int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29, + Calendar.THURSDAY, 0); + errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception."); + } catch (IllegalArgumentException e) { + logln("got IllegalArgumentException"); + } + } + + /** + * 4966229: java.util.Date methods may works incorrect. + * sun.util.calendar.ZoneInfo doesn't clone properly. + */ + @SuppressWarnings("deprecation") + public void Test4966229() { + TimeZone savedTZ = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Date d = new Date(2100-1900, 5, 1); // specify year >2037 + TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); + + Calendar cal = new GregorianCalendar(tz); + cal.setTime(d); + + // Change the raw offset in tz + int offset = tz.getRawOffset(); + tz.setRawOffset(0); + + TimeZone tz2 = (TimeZone) tz.clone(); + Calendar cal2 = new GregorianCalendar(tz2); + cal2.setTime(d); + int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY); + + // Restore the GMT offset in tz which shouldn't affect tz2 + tz.setRawOffset(offset); + cal2.setTime(d); + int hourOfDay = cal2.get(cal.HOUR_OF_DAY); + if (hourOfDay != expectedHourOfDay) { + errln("wrong hour of day: got: " + hourOfDay + + ", expected: " + expectedHourOfDay); + } + } finally { + TimeZone.setDefault(savedTZ); + } + } + + /** + * 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+ + */ + public void Test6433179() { + // Use the old America/Winnipeg rule for testing. Note that + // startMode is WALL_TIME for testing. It's actually + // STANDARD_TIME, though. + //Rule Winn 1966 2005 - Oct lastSun 2:00s 0 S + //Rule Winn 1987 2005 - Apr Sun>=1 2:00s 1:00 D + TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg", + Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, + 1*ONE_HOUR); + Calendar cal = Calendar.getInstance(tz, Locale.US); + cal.clear(); + cal.set(2039, Calendar.OCTOBER, 1); + cal.getTime(); + cal.set(cal.DAY_OF_WEEK, cal.SUNDAY); + cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1); + cal.add(Calendar.HOUR_OF_DAY, 2); + if (cal.get(cal.DST_OFFSET) == 0) { + errln("Should still be in DST."); + } + } + + private static final int ONE_HOUR = 60 * 60 * 1000; + /** + * Returns an instance of SimpleTimeZone for + * "PST". (TimeZone.getTimeZone() no longer returns a + * SimpleTimeZone object.) + * @since 1.4 + */ + private SimpleTimeZone getPST() { + return new SimpleTimeZone(-8*ONE_HOUR, "PST", + Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, + 1*ONE_HOUR); + } +} +//eof diff --git a/jdk/test/java/util/TimeZone/TimeZoneTest.java b/jdk/test/java/util/TimeZone/TimeZoneTest.java new file mode 100644 index 00000000000..2413d15e8f5 --- /dev/null +++ b/jdk/test/java/util/TimeZone/TimeZoneTest.java @@ -0,0 +1,737 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483 + * 8008577 8077685 8098547 8133321 8138716 8148446 + * @modules java.base/sun.util.resources + * @library /java/text/testlib + * @summary test TimeZone + */ + +import java.io.*; +import java.text.*; +import java.util.*; +import sun.util.resources.LocaleData; + +public class TimeZoneTest extends IntlTest +{ + static final int millisPerHour = 3600000; + + public static void main(String[] args) throws Exception { + new TimeZoneTest().run(args); + } + + /** + * Bug 4130885 + * Certain short zone IDs, used since 1.1.x, are incorrect. + * + * The worst of these is: + * + * "CAT" (Central African Time) should be GMT+2:00, but instead returns a + * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, + * or AZOST, depending on which zone is meant, but in no case is it CAT. + * + * Other wrong zone IDs: + * + * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, + * GMT-5:00. European Central time is abbreviated CEST. + * + * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, + * GMT-11:00. Solomon Island time is SBT. + * + * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for + * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. + * + * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in + * another bug.] It should be "AKST". AST is Atlantic Standard Time, + * GMT-4:00. + * + * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, + * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct + * from MST with daylight savings. + * + * In addition to these problems, a number of zones are FAKE. That is, they + * don't match what people use in the real world. + * + * FAKE zones: + * + * EET (should be EEST) + * ART (should be EET) + * MET (should be IRST) + * NET (should be AMST) + * PLT (should be PKT) + * BST (should be BDT) + * VST (should be ICT) + * CTT (should be CST) + + * ACT (should be CST) + + * AET (should be EST) + + * MIT (should be WST) + + * IET (should be EST) + + * PRT (should be AST) + + * CNT (should be NST) + * AGT (should be ARST) + * BET (should be EST) + + * + * + A zone with the correct name already exists and means something + * else. E.g., EST usually indicates the US Eastern zone, so it cannot be + * used for Brazil (BET). + */ + public void TestShortZoneIDs() throws Exception { + + ZoneDescriptor[] JDK_116_REFERENCE_LIST = { + new ZoneDescriptor("MIT", 780, true), + new ZoneDescriptor("HST", -600, false), + new ZoneDescriptor("AST", -540, true), + new ZoneDescriptor("PST", -480, true), + new ZoneDescriptor("PNT", -420, false), + new ZoneDescriptor("MST", -420, false), + new ZoneDescriptor("CST", -360, true), + new ZoneDescriptor("IET", -300, true), + new ZoneDescriptor("EST", -300, false), + new ZoneDescriptor("PRT", -240, false), + new ZoneDescriptor("CNT", -210, true), + new ZoneDescriptor("AGT", -180, false), + new ZoneDescriptor("BET", -180, true), + // new ZoneDescriptor("CAT", -60, false), // Wrong: + // As of bug 4130885, fix CAT (Central Africa) + new ZoneDescriptor("CAT", 120, false), // Africa/Harare + new ZoneDescriptor("GMT", 0, false), + new ZoneDescriptor("UTC", 0, false), + new ZoneDescriptor("ECT", 60, true), + new ZoneDescriptor("ART", 120, false), + new ZoneDescriptor("EET", 120, true), + new ZoneDescriptor("EAT", 180, false), + new ZoneDescriptor("MET", 60, true), + new ZoneDescriptor("NET", 240, false), + new ZoneDescriptor("PLT", 300, false), + new ZoneDescriptor("IST", 330, false), + new ZoneDescriptor("BST", 360, false), + new ZoneDescriptor("VST", 420, false), + new ZoneDescriptor("CTT", 480, false), + new ZoneDescriptor("JST", 540, false), + new ZoneDescriptor("ACT", 570, false), + new ZoneDescriptor("AET", 600, true), + new ZoneDescriptor("SST", 660, false), + // new ZoneDescriptor("NST", 720, false), + // As of bug 4130885, fix NST (New Zealand) + new ZoneDescriptor("NST", 720, true), // Pacific/Auckland + }; + + Map hash = new HashMap<>(); + + String[] ids = TimeZone.getAvailableIDs(); + for (String id : ids) { + if (id.length() == 3) { + hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id))); + } + } + + for (int i = 0; i < JDK_116_REFERENCE_LIST.length; ++i) { + ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i]; + ZoneDescriptor currentZone = hash.get(referenceZone.getID()); + if (referenceZone.equals(currentZone)) { + logln("ok " + referenceZone); + } + else { + errln("Fail: Expected " + referenceZone + + "; got " + currentZone); + } + } + } + + /** + * A descriptor for a zone; used to regress the short zone IDs. + */ + static class ZoneDescriptor { + String id; + int offset; // In minutes + boolean daylight; + + ZoneDescriptor(TimeZone zone) { + this.id = zone.getID(); + this.offset = zone.getRawOffset() / 60000; + this.daylight = zone.useDaylightTime(); + } + + ZoneDescriptor(String id, int offset, boolean daylight) { + this.id = id; + this.offset = offset; + this.daylight = daylight; + } + + public String getID() { return id; } + + @Override + public boolean equals(Object o) { + ZoneDescriptor that = (ZoneDescriptor)o; + return that != null && + id.equals(that.id) && + offset == that.offset && + daylight == that.daylight; + } + + @Override + public int hashCode() { + return id.hashCode() ^ offset | (daylight ? 1 : 0); + } + + @Override + public String toString() { + int min = offset; + char sign = '+'; + if (min < 0) { sign = '-'; min = -min; } + + return "Zone[\"" + id + "\", GMT" + sign + (min/60) + ':' + + (min%60<10?"0":"") + (min%60) + ", " + + (daylight ? "Daylight" : "Standard") + "]"; + } + + public static int compare(Object o1, Object o2) { + ZoneDescriptor i1 = (ZoneDescriptor)o1; + ZoneDescriptor i2 = (ZoneDescriptor)o2; + if (i1.offset > i2.offset) return 1; + if (i1.offset < i2.offset) return -1; + if (i1.daylight && !i2.daylight) return 1; + if (!i1.daylight && i2.daylight) return -1; + return i1.id.compareTo(i2.id); + } + } + + static final String formatMinutes(int min) { + char sign = '+'; + if (min < 0) { sign = '-'; min = -min; } + int h = min/60; + min = min%60; + return "" + sign + h + ":" + ((min<10) ? "0" : "") + min; + } + /** + * As part of the VM fix (see CCC approved RFE 4028006, bug + * 4044013), TimeZone.getTimeZone() has been modified to recognize + * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and + * GMT[+-]hh. Test this behavior here. + * + * Bug 4044013 + * + * ID "Custom" is no longer used for TimeZone objects created with + * a custom time zone ID, such as "GMT-8". See 4322313. + */ + public void TestCustomParse() throws Exception { + Object[] DATA = { + // ID Expected offset in minutes + "GMT", null, + "GMT+0", new Integer(0), + "GMT+1", new Integer(60), + "GMT-0030", new Integer(-30), + "GMT+15:99", null, + "GMT+", null, + "GMT-", null, + "GMT+0:", null, + "GMT-:", null, + "GMT+0010", new Integer(10), // Interpret this as 00:10 + "GMT-10", new Integer(-10*60), + "GMT+30", null, + "GMT-3:30", new Integer(-(3*60+30)), + "GMT-230", new Integer(-(2*60+30)), + }; + for (int i=0; i generic GMT"); + // When TimeZone.getTimeZone() can't parse the id, it + // returns GMT -- a dubious practice, but required for + // backward compatibility. + if (exp != null) { + throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + + " for " + id + ", got parse failure"); + } + } + else { + int ioffset = zone.getRawOffset()/60000; + String offset = formatMinutes(ioffset); + logln(id + " -> " + zone.getID() + " GMT" + offset); + if (exp == null) { + throw new Exception("Expected parse failure for " + id + + ", got offset of " + offset + + ", id " + zone.getID()); + } + else if (ioffset != exp.intValue()) { + throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + + ", id Custom, for " + id + + ", got offset of " + offset + + ", id " + zone.getID()); + } + } + } + } + + /** + * Test the basic functionality of the getDisplayName() API. + * + * Bug 4112869 + * Bug 4028006 + * + * See also API change request A41. + * + * 4/21/98 - make smarter, so the test works if the ext resources + * are present or not. + */ + public void TestDisplayName() { + TimeZone zone = TimeZone.getTimeZone("PST"); + String name = zone.getDisplayName(Locale.ENGLISH); + logln("PST->" + name); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected \"Pacific Standard Time\""); + + //***************************************************************** + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES + //***************************************************************** + Object[] DATA = { + new Boolean(false), new Integer(TimeZone.SHORT), "PST", + new Boolean(true), new Integer(TimeZone.SHORT), "PDT", + new Boolean(false), new Integer(TimeZone.LONG), "Pacific Standard Time", + new Boolean(true), new Integer(TimeZone.LONG), "Pacific Daylight Time", + }; + + for (int i=0; i" + zone2.inDaylightTime(new Date())); + name = zone2.getDisplayName(Locale.ENGLISH); + logln("Modified PST->" + name); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected \"Pacific Standard Time\""); + + // Make sure we get the default display format for Locales + // with no display name data. + Locale zh_CN = Locale.SIMPLIFIED_CHINESE; + name = zone.getDisplayName(zh_CN); + //***************************************************************** + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES + //***************************************************************** + logln("PST(zh_CN)->" + name); + + // Now be smart -- check to see if zh resource is even present. + // If not, we expect the en fallback behavior. + ResourceBundle enRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames", + Locale.ENGLISH); + ResourceBundle zhRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames", + zh_CN); + + boolean noZH = enRB == zhRB; + + if (noZH) { + logln("Warning: Not testing the zh_CN behavior because resource is absent"); + if (!name.equals("Pacific Standard Time")) + errln("Fail: Expected Pacific Standard Time"); + } + else if (!name.equals("Pacific Standard Time") && + !name.equals("\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") && + !name.equals("GMT-08:00") && + !name.equals("GMT-8:00") && + !name.equals("GMT-0800") && + !name.equals("GMT-800")) { + errln("Fail: Expected GMT-08:00 or something similar"); + errln("************************************************************"); + errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED"); + errln("************************************************************"); + } + + // Now try a non-existent zone + zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); + name = zone2.getDisplayName(Locale.ENGLISH); + logln("GMT+90min->" + name); + if (!name.equals("GMT+01:30") && + !name.equals("GMT+1:30") && + !name.equals("GMT+0130") && + !name.equals("GMT+130")) + errln("Fail: Expected GMT+01:30 or something similar"); + } + + public void TestGenericAPI() { + String id = "NewGMT"; + int offset = 12345; + + SimpleTimeZone zone = new SimpleTimeZone(offset, id); + if (zone.useDaylightTime()) { + errln("FAIL: useDaylightTime should return false"); + } + + TimeZone zoneclone = (TimeZone)zone.clone(); + if (!zoneclone.equals(zone)) { + errln("FAIL: clone or operator== failed"); + } + zoneclone.setID("abc"); + if (zoneclone.equals(zone)) { + errln("FAIL: clone or operator!= failed"); + } + + zoneclone = (TimeZone)zone.clone(); + if (!zoneclone.equals(zone)) { + errln("FAIL: clone or operator== failed"); + } + zoneclone.setRawOffset(45678); + if (zoneclone.equals(zone)) { + errln("FAIL: clone or operator!= failed"); + } + + TimeZone saveDefault = TimeZone.getDefault(); + try { + TimeZone.setDefault(zone); + TimeZone defaultzone = TimeZone.getDefault(); + if (defaultzone == zone) { + errln("FAIL: Default object is identical, not clone"); + } + if (!defaultzone.equals(zone)) { + errln("FAIL: Default object is not equal"); + } + } + finally { + TimeZone.setDefault(saveDefault); + } + } + + @SuppressWarnings("deprecation") + public void TestRuleAPI() + { + // ErrorCode status = ZERO_ERROR; + + int offset = (int)(60*60*1000*1.75); // Pick a weird offset + SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); + if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); + + // Establish our expected transition times. Do this with a non-DST + // calendar with the (above) declared local offset. + GregorianCalendar gc = new GregorianCalendar(zone); + gc.clear(); + gc.set(1990, Calendar.MARCH, 1); + long marchOneStd = gc.getTime().getTime(); // Local Std time midnight + gc.clear(); + gc.set(1990, Calendar.JULY, 1); + long julyOneStd = gc.getTime().getTime(); // Local Std time midnight + + // Starting and ending hours, WALL TIME + int startHour = (int)(2.25 * 3600000); + int endHour = (int)(3.5 * 3600000); + + zone.setStartRule(Calendar.MARCH, 1, 0, startHour); + zone.setEndRule (Calendar.JULY, 1, 0, endHour); + + gc = new GregorianCalendar(zone); + // if (failure(status, "new GregorianCalendar")) return; + + long marchOne = marchOneStd + startHour; + long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time + + long expMarchOne = 636251400000L; + if (marchOne != expMarchOne) + { + errln("FAIL: Expected start computed as " + marchOne + + " = " + new Date(marchOne)); + logln(" Should be " + expMarchOne + + " = " + new Date(expMarchOne)); + } + + long expJulyOne = 646793100000L; + if (julyOne != expJulyOne) + { + errln("FAIL: Expected start computed as " + julyOne + + " = " + new Date(julyOne)); + logln(" Should be " + expJulyOne + + " = " + new Date(expJulyOne)); + } + + testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(), + new Date(90, Calendar.JUNE, 15).getTime(), marchOne); + testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(), + new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne); + + if (zone.inDaylightTime(new Date(marchOne - 1000)) || + !zone.inDaylightTime(new Date(marchOne))) + errln("FAIL: Start rule broken"); + if (!zone.inDaylightTime(new Date(julyOne - 1000)) || + zone.inDaylightTime(new Date(julyOne))) + errln("FAIL: End rule broken"); + + zone.setStartYear(1991); + if (zone.inDaylightTime(new Date(marchOne)) || + zone.inDaylightTime(new Date(julyOne - 1000))) + errln("FAIL: Start year broken"); + + // failure(status, "TestRuleAPI"); + // delete gc; + // delete zone; + } + + void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) + { + // ErrorCode status = ZERO_ERROR; + boolean startsInDST = tz.inDaylightTime(new Date(min)); + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + if (tz.inDaylightTime(new Date(max)) == startsInDST) { + logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); + return; + } + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + while ((max - min) > INTERVAL) { + long mid = (min + max) / 2; + if (tz.inDaylightTime(new Date(mid)) == startsInDST) { + min = mid; + } + else { + max = mid; + } + // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; + } + logln("Binary Search Before: " + min + " = " + new Date(min)); + logln("Binary Search After: " + max + " = " + new Date(max)); + long mindelta = expectedBoundary - min; + long maxdelta = max - expectedBoundary; + if (mindelta >= 0 && + mindelta <= INTERVAL && + mindelta >= 0 && + mindelta <= INTERVAL) + logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); + else + errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); + } + + static final int INTERVAL = 100; + + // Bug 006; verify the offset for a specific zone. + public void TestPRTOffset() + { + TimeZone tz = TimeZone.getTimeZone( "PRT" ); + if( tz == null ) { + errln( "FAIL: TimeZone(PRT) is null" ); + } + else{ + if (tz.getRawOffset() != (-4*millisPerHour)) + errln("FAIL: Offset for PRT should be -4"); + } + + } + + // Test various calls + @SuppressWarnings("deprecation") + public void TestVariousAPI518() + { + TimeZone time_zone = TimeZone.getTimeZone("PST"); + Date d = new Date(97, Calendar.APRIL, 30); + + logln("The timezone is " + time_zone.getID()); + + if (time_zone.inDaylightTime(d) != true) + errln("FAIL: inDaylightTime returned false"); + + if (time_zone.useDaylightTime() != true) + errln("FAIL: useDaylightTime returned false"); + + if (time_zone.getRawOffset() != -8*millisPerHour) + errln( "FAIL: getRawOffset returned wrong value"); + + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(d); + if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH), + gc.get(gc.DAY_OF_MONTH), + gc.get(gc.DAY_OF_WEEK), 0) + != -7*millisPerHour) + errln("FAIL: getOffset returned wrong value"); + } + + // Test getAvailableID API + public void TestGetAvailableIDs913() + { + StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); + String[] s = TimeZone.getAvailableIDs(); + for (int i=0; i 0) buf.append(", "); + buf.append(s[i]); + } + buf.append(" };"); + logln(buf.toString()); + + buf.setLength(0); + buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); + s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); + for (int i=0; i 0) buf.append(", "); + buf.append(s[i]); + } + buf.append(" };"); + logln(buf.toString()); + + TimeZone tz = TimeZone.getTimeZone("PST"); + if (tz != null) + logln("getTimeZone(PST) = " + tz.getID()); + else + errln("FAIL: getTimeZone(PST) = null"); + + tz = TimeZone.getTimeZone("America/Los_Angeles"); + if (tz != null) + logln("getTimeZone(America/Los_Angeles) = " + tz.getID()); + else + errln("FAIL: getTimeZone(PST) = null"); + + // Bug 4096694 + tz = TimeZone.getTimeZone("NON_EXISTENT"); + if (tz == null) + errln("FAIL: getTimeZone(NON_EXISTENT) = null"); + else if (!tz.getID().equals("GMT")) + errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); + } + + /** + * Bug 4107276 + */ + public void TestDSTSavings() { + // It might be better to find a way to integrate this test into the main TimeZone + // tests above, but I don't have time to figure out how to do this (or if it's + // even really a good idea). Let's consider that a future. --rtg 1/27/98 + SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", + Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, + (int)(0.5 * millisPerHour)); + + if (tz.getRawOffset() != -5 * millisPerHour) + errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + + " hours instead of -5 hours."); + if (!tz.useDaylightTime()) + errln("Test time zone should use DST but claims it doesn't."); + if (tz.getDSTSavings() != 0.5 * millisPerHour) + errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / + millisPerHour) + " hours instead."); + + int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, + 10 * millisPerHour); + if (offset != -4.5 * millisPerHour) + errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + tz.setDSTSavings(millisPerHour); + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, + 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + } + + /** + * Bug 4107570 + */ + public void TestAlternateRules() { + // Like TestDSTSavings, this test should probably be integrated somehow with the main + // test at the top of this class, but I didn't have time to figure out how to do that. + // --rtg 1/28/98 + + SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); + + // test the day-of-month API + tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); + tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); + + int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, + Calendar.SUNDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, + Calendar.SUNDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + // test the day-of-week-after-day-in-month API + tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); + tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, + Calendar.WEDNESDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, + Calendar.SATURDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, + Calendar.THURSDAY, 10 * millisPerHour); + if (offset != -4 * millisPerHour) + errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + + (offset / millisPerHour) + " hours."); + + offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, + Calendar.SATURDAY, 10 * millisPerHour); + if (offset != -5 * millisPerHour) + errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " + + (offset / millisPerHour) + " hours."); + } +} + +//eof diff --git a/jdk/test/java/util/TimeZone/TransitionTest.java b/jdk/test/java/util/TimeZone/TransitionTest.java new file mode 100644 index 00000000000..5f012d09d72 --- /dev/null +++ b/jdk/test/java/util/TimeZone/TransitionTest.java @@ -0,0 +1,287 @@ +/* + * 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 4278609 4761696 + * @library /java/text/testlib + * @summary Make sure to handle DST transition ending at 0:00 January 1. + */ + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.SimpleTimeZone; +import java.util.TimeZone; + +public class TransitionTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new TransitionTest().run(args); + } + + public void Test4278609() { + SimpleTimeZone tz = new SimpleTimeZone(0, "MyTimeZone", + /* DST start day: August, 1, 0:00 */ + Calendar.AUGUST, 1, 0, 0, + /* DST end day: January, 1, 0:00 (wall-clock)*/ + Calendar.JANUARY, 1, 0, 0, + 60 * 60 * 1000); + + Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + + // setting a date using GMT zone just after the end rule of tz zone + cal.clear(); + cal.set(Calendar.ERA, GregorianCalendar.AD); + cal.set(1998, Calendar.DECEMBER, 31, 23, 01, 00); + + Date date = cal.getTime(); + + int millis = cal.get(Calendar.HOUR_OF_DAY) * 3600000 + + cal.get(Calendar.MINUTE) * 60000 + + cal.get(Calendar.SECOND) * 1000 + + cal.get(Calendar.MILLISECOND); + /* we must use standard local time */ + millis += tz.getRawOffset(); + + int offset = tz.getOffset(cal.get(Calendar.ERA), + cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH), + cal.get(Calendar.DATE), + cal.get(Calendar.DAY_OF_WEEK), + millis); + + if (offset != 0) { + SimpleDateFormat format = new SimpleDateFormat("dd MMM HH:mm:ss zzz", + Locale.US); + format.setTimeZone(tz); + errln("Wrong DST transition: " + tz + + "\na date just after DST = " + format.format(date) + + "\ngetOffset = " + offset); + } + } + + /* + * 4761696: Rewrite SimpleTimeZone to support correct DST transitions + * + * Derived from JCK test cases some of which specify wrong day of week values. + */ + public void Test4761696() { + GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + + // test#1 + int rawOffset = -43200000; + int saving = 1800000; + int timeOfDay = 84600001; + SimpleTimeZone tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.JULY, 1, 0, 0, + Calendar.JANUARY, 1, 0, 0, + saving); + int year = Integer.MIN_VALUE; + tz.setStartYear(year); + int offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.DECEMBER, + 31, + 1, // should be SATURDAY + timeOfDay); + int y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(cal.ERA, cal.AD); + cal.set(y, Calendar.DECEMBER, 31); + cal.set(cal.MILLISECOND, timeOfDay); + long localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(cal.ERA, cal.AD); + cal.set(y + 1, Calendar.JANUARY, 1); + cal.set(cal.MILLISECOND, -saving); + long endTime = cal.getTimeInMillis() + rawOffset; + long expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#1: wrong offset: got "+offset+", expected="+expectedOffset); + } + + // test#2 + saving = 1; + timeOfDay = 0; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.JULY, 1, 0, 0, + Calendar.JANUARY, 1, 0, 0, + saving); + tz.setStartYear(year); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.AUGUST, + 15, + 1, // should be MONDAY + timeOfDay); + y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(y, Calendar.AUGUST, 15); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(y + 1, Calendar.JANUARY, 1); + cal.set(cal.MILLISECOND, -saving); + endTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("Wrong offset: got "+offset+", expected="+expectedOffset); + } + + rawOffset = 43200000; + saving = 1; + timeOfDay = 3599998; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.JULY, 1, 0, 3600000, + Calendar.JANUARY, 1, 0, 3600000, + saving); + tz.setStartYear(year); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.JANUARY, + 1, + 1, + timeOfDay); + y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(y, Calendar.JANUARY, 1); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(y + 1, Calendar.JANUARY, 1); + cal.set(cal.MILLISECOND, 3600000-saving); + endTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#2: wrong offset: got "+offset+", expected="+expectedOffset); + } + + // test#3 + rawOffset = -43200000; + saving = 1800000; + timeOfDay = 84600001; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.SEPTEMBER, 1, 0, 0, + Calendar.MARCH, 1, 0, 0, + saving); + tz.setStartYear(year); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.FEBRUARY, + 28, + 1, + timeOfDay); + y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(y, Calendar.FEBRUARY, 28); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(y, Calendar.MARCH, 1); + cal.set(cal.MILLISECOND, -saving); + endTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#3: wrong offset: got "+offset+", expected="+expectedOffset); + } + + // test#4 + rawOffset = -43200000; + saving = 1; + timeOfDay = 0; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.JANUARY, -4, 1, 3600000, + Calendar.JULY, -4, 1, 3600000, + saving); + tz.setStartYear(year); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.JANUARY, + 10, + 2, // should be 1 (SUNDAY) + timeOfDay); + y = (int) mod((long)year, 28L); // 28-year cycle + cal.clear(); + cal.set(y, Calendar.JANUARY, 10); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(cal.YEAR, y); + cal.set(cal.MONTH, Calendar.JANUARY); + cal.set(cal.DAY_OF_MONTH, 8); + cal.set(cal.WEEK_OF_MONTH, cal.getActualMaximum(cal.WEEK_OF_MONTH)-4+1); + cal.set(cal.DAY_OF_WEEK, 1); + cal.set(cal.MILLISECOND, 3600000-saving); + long startTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime >= startTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#4: wrong offset: got "+offset+", expected="+expectedOffset); + } + + // test#5 + rawOffset = 0; + saving = 3600000; + timeOfDay = 7200000; + year = 1982; + tz = new SimpleTimeZone(rawOffset, "stz", + Calendar.APRIL, 1, 0, 7200000, + Calendar.OCTOBER, 10, 0, 7200000, + saving); + offset = tz.getOffset(GregorianCalendar.AD, + year, + Calendar.OCTOBER, + 10, + 1, + timeOfDay); + cal.clear(); + cal.set(year, Calendar.OCTOBER, 10); + cal.set(cal.MILLISECOND, timeOfDay); + localtime = cal.getTimeInMillis() + rawOffset; // local standard time + + cal.clear(); + cal.set(year, Calendar.OCTOBER, 10); + cal.set(cal.MILLISECOND, 7200000-saving); + endTime = cal.getTimeInMillis() + rawOffset; + expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset; + if (offset != expectedOffset) { + errln("test#5: wrong offset: got "+offset+", expected="+expectedOffset); + } + } + + public static final long floorDivide(long n, long d) { + return ((n >= 0) ? + (n / d) : (((n + 1L) / d) - 1L)); + } + + public static final long mod(long x, long y) { + return (x - y * floorDivide(x, y)); + } +} diff --git a/jdk/test/java/util/TimeZone/UTCAliasTest.java b/jdk/test/java/util/TimeZone/UTCAliasTest.java new file mode 100644 index 00000000000..aa7079326c0 --- /dev/null +++ b/jdk/test/java/util/TimeZone/UTCAliasTest.java @@ -0,0 +1,52 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6282072 + * @summary Make sure that "UTC" is an alias of "Etc/UTC" as defined in the tzdata backward. + * @modules java.base/sun.util.calendar + * @compile -XDignore.symbol.file UTCAliasTest.java + */ + +import java.util.*; +import sun.util.calendar.ZoneInfo; + +public class UTCAliasTest { + public static void main(String[] args) { + Map map = ZoneInfo.getAliasTable(); + String alias = map.get("UTC"); + if (!alias.equals("Etc/UTC")) { + throw new RuntimeException("got " + alias + ", expected Etc/UTC"); + } + TimeZone GMT = TimeZone.getTimeZone("GMT"); + TimeZone UTC = TimeZone.getTimeZone("UTC"); + if (!GMT.hasSameRules(UTC)) { + throw new RuntimeException("GMT and UTC have different rules"); + } + TimeZone EtcUTC = TimeZone.getTimeZone("Etc/UTC"); + if (!UTC.hasSameRules(EtcUTC)) { + throw new RuntimeException("UTC and Etc/UTC have different rules"); + } + } +} diff --git a/jdk/test/java/util/TimeZone/bug4096952.java b/jdk/test/java/util/TimeZone/bug4096952.java new file mode 100644 index 00000000000..20ccc685ac6 --- /dev/null +++ b/jdk/test/java/util/TimeZone/bug4096952.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4096952 + * @summary simple serialization/deserialization test + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.TimeZone; + +public class bug4096952 { + + public static void main(String[] args) { + int errors = 0; + String[] ZONES = { "GMT", "MET", "IST" }; + for (String id : ZONES) { + TimeZone zone = TimeZone.getTimeZone(id); + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream ostream = new ObjectOutputStream(baos)) { + ostream.writeObject(zone); + } + try (ObjectInputStream istream + = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + if (!zone.equals(istream.readObject())) { + errors++; + System.out.println("Time zone " + id + " are not equal to serialized/deserialized one."); + } else { + System.out.println("Time zone " + id + " ok."); + } + } + } catch (IOException | ClassNotFoundException e) { + errors++; + System.out.println(e); + } + } + if (errors > 0) { + throw new RuntimeException("test failed"); + } + } +} diff --git a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java index 82f9ead09f5..913aea78c46 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java +++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java @@ -25,13 +25,10 @@ * @test * @bug 6503247 6574123 * @summary Test resilience to tryAcquire methods that throw - * @library /lib/testlibrary/ * @author Martin Buchholz */ -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -39,7 +36,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; -import jdk.testlibrary.Utils; /** * This uses a variant of the standard Mutex demo, except with a @@ -48,22 +44,10 @@ import jdk.testlibrary.Utils; */ @SuppressWarnings("serial") public class FlakyMutex implements Lock { - static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static class MyError extends Error {} static class MyException extends Exception {} static class MyRuntimeException extends RuntimeException {} - static final Random rnd = new Random(); - - static void maybeThrow() { - switch (rnd.nextInt(10)) { - case 0: throw new MyError(); - case 1: throw new MyRuntimeException(); - case 2: FlakyMutex.uncheckedThrow(new MyException()); - default: /* Do nothing */ break; - } - } - static void checkThrowable(Throwable t) { check((t instanceof MyError) || (t instanceof MyException) || @@ -72,31 +56,35 @@ public class FlakyMutex implements Lock { static void realMain(String[] args) throws Throwable { final int nThreads = 3; - final CyclicBarrier barrier = new CyclicBarrier(nThreads + 1); - final FlakyMutex m = new FlakyMutex(); + final int iterations = 10_000; + final CyclicBarrier startingGate = new CyclicBarrier(nThreads); + final FlakyMutex mutex = new FlakyMutex(); final ExecutorService es = Executors.newFixedThreadPool(nThreads); - for (int i = 0; i < nThreads; i++) { - es.submit(new Runnable() { public void run() { - try { - barrier.await(); - for (int i = 0; i < 10000; i++) { - for (;;) { - try { m.lock(); break; } - catch (Throwable t) { checkThrowable(t); } - } - - try { check(! m.tryLock()); } + final Runnable task = () -> { + try { + startingGate.await(); + for (int i = 0; i < iterations; i++) { + for (;;) { + try { mutex.lock(); break; } catch (Throwable t) { checkThrowable(t); } - - try { check(! m.tryLock(1, TimeUnit.MICROSECONDS)); } - catch (Throwable t) { checkThrowable(t); } - - m.unlock(); } - } catch (Throwable t) { unexpected(t); }}});} - barrier.await(); + + try { check(! mutex.tryLock()); } + catch (Throwable t) { checkThrowable(t); } + + try { check(! mutex.tryLock(1, TimeUnit.MICROSECONDS)); } + catch (Throwable t) { checkThrowable(t); } + + mutex.unlock(); + } + } catch (Throwable t) { unexpected(t); } + }; + + for (int i = 0; i < nThreads; i++) + es.submit(task); es.shutdown(); - check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + // Let test harness handle timeout + check(es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)); } private static class FlakySync extends AbstractQueuedLongSynchronizer { @@ -116,8 +104,12 @@ public class FlakyMutex implements Lock { do {} while (hasQueuedPredecessors() != hasQueuedThreads()); } - maybeThrow(); - return compareAndSetState(0, 1); + switch (ThreadLocalRandom.current().nextInt(10)) { + case 0: throw new MyError(); + case 1: throw new MyRuntimeException(); + case 2: FlakyMutex.uncheckedThrow(new MyException()); + default: return compareAndSetState(0, 1); + } } public boolean tryRelease(long releases) { diff --git a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java index 7d6da0b255e..630f3796b8c 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java +++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, 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 @@ -167,7 +167,7 @@ public class TimedAcquireLeak { final String childPid, final String className) { final String regex = - "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E$"; + "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E(?:$| )"; final Callable objectsInUse = new Callable() { public Integer call() { Integer i = Integer.parseInt( diff --git a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java index 5ad9d068a2a..2d82c455574 100644 --- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java +++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java @@ -35,16 +35,10 @@ * @test * @bug 8074773 * @summary Stress test looks for lost unparks - * @library /lib/testlibrary/ - * @modules java.management - * @run main/timeout=1200 ParkLoops */ -import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; import java.util.SplittableRandom; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -52,11 +46,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.LockSupport; -import jdk.testlibrary.Utils; public final class ParkLoops { - static final long TEST_TIMEOUT_SECONDS = Utils.adjustTimeout(1000); - static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final int THREADS = 4; static final int ITERS = 30_000; @@ -126,28 +117,13 @@ public final class ParkLoops { final AtomicReferenceArray threads = new AtomicReferenceArray<>(THREADS); final CountDownLatch done = new CountDownLatch(THREADS); - final Runnable parker = new Parker(threads, done, rnd.split()); - final Runnable unparker = new Unparker(threads, done, rnd.split()); for (int i = 0; i < THREADS; i++) { - pool.submit(parker); - pool.submit(unparker); - } - try { - if (!done.await(TEST_TIMEOUT_SECONDS, SECONDS)) { - dumpAllStacks(); - throw new AssertionError("lost unpark"); - } - } finally { - pool.shutdown(); - pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS); - } - } - - static void dumpAllStacks() { - ThreadInfo[] threadInfos = - ManagementFactory.getThreadMXBean().dumpAllThreads(true, true); - for (ThreadInfo threadInfo : threadInfos) { - System.err.print(threadInfo); + pool.submit(new Parker(threads, done, rnd.split())); + pool.submit(new Unparker(threads, done, rnd.split())); } + // Let test harness handle timeout + done.await(); + pool.shutdown(); + pool.awaitTermination(Long.MAX_VALUE, SECONDS); } } diff --git a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java index 340e7f972a4..4149559adad 100644 --- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java +++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java @@ -3322,7 +3322,7 @@ public class CompletableFutureTest extends JSR166TestCase { () -> f.obtrudeException(null), () -> CompletableFuture.delayedExecutor(1L, SECONDS, null), - () -> CompletableFuture.delayedExecutor(1L, null, new ThreadExecutor()), + () -> CompletableFuture.delayedExecutor(1L, null, exec), () -> CompletableFuture.delayedExecutor(1L, null), () -> f.orTimeout(1L, null), @@ -3552,7 +3552,7 @@ public class CompletableFutureTest extends JSR166TestCase { long timeoutMillis = timeoutMillis(); CompletableFuture f = new CompletableFuture<>(); long startTime = System.nanoTime(); - f.orTimeout(timeoutMillis, MILLISECONDS); + assertSame(f, f.orTimeout(timeoutMillis, MILLISECONDS)); checkCompletedWithTimeoutException(f); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); } @@ -3567,8 +3567,8 @@ public class CompletableFutureTest extends JSR166TestCase { CompletableFuture g = new CompletableFuture<>(); long startTime = System.nanoTime(); f.complete(v1); - f.orTimeout(LONG_DELAY_MS, MILLISECONDS); - g.orTimeout(LONG_DELAY_MS, MILLISECONDS); + assertSame(f, f.orTimeout(LONG_DELAY_MS, MILLISECONDS)); + assertSame(g, g.orTimeout(LONG_DELAY_MS, MILLISECONDS)); g.complete(v1); checkCompletedNormally(f, v1); checkCompletedNormally(g, v1); @@ -3583,11 +3583,14 @@ public class CompletableFutureTest extends JSR166TestCase { () -> testCompleteOnTimeout_timesOut(null)); } + /** + * completeOnTimeout completes with given value if not complete + */ public void testCompleteOnTimeout_timesOut(Integer v) { long timeoutMillis = timeoutMillis(); CompletableFuture f = new CompletableFuture<>(); long startTime = System.nanoTime(); - f.completeOnTimeout(v, timeoutMillis, MILLISECONDS); + assertSame(f, f.completeOnTimeout(v, timeoutMillis, MILLISECONDS)); assertSame(v, f.join()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); f.complete(99); // should have no effect @@ -3604,8 +3607,8 @@ public class CompletableFutureTest extends JSR166TestCase { CompletableFuture g = new CompletableFuture<>(); long startTime = System.nanoTime(); f.complete(v1); - f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS); - g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS); + assertSame(f, f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS)); + assertSame(g, g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS)); g.complete(v1); checkCompletedNormally(f, v1); checkCompletedNormally(g, v1); diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java new file mode 100644 index 00000000000..8169d5fa5f6 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java @@ -0,0 +1,137 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.HashSet; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ExecutorCompletionService9Test extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ExecutorCompletionService9Test.class); + } + + void solveAll(Executor e, + Collection> solvers) + throws InterruptedException, ExecutionException { + CompletionService cs + = new ExecutorCompletionService<>(e); + solvers.forEach(cs::submit); + for (int i = solvers.size(); i > 0; i--) { + Integer r = cs.take().get(); + if (r != null) + use(r); + } + } + + void solveAny(Executor e, + Collection> solvers) + throws InterruptedException { + CompletionService cs + = new ExecutorCompletionService<>(e); + int n = solvers.size(); + List> futures = new ArrayList<>(n); + Integer result = null; + try { + solvers.forEach((solver) -> futures.add(cs.submit(solver))); + for (int i = n; i > 0; i--) { + try { + Integer r = cs.take().get(); + if (r != null) { + result = r; + break; + } + } catch (ExecutionException ignore) {} + } + } finally { + futures.forEach((future) -> future.cancel(true)); + } + + if (result != null) + use(result); + } + + HashSet results; + + void use(Integer x) { + if (results == null) results = new HashSet(); + results.add(x); + } + + /** + * The first "solvers" sample code in the class javadoc works. + */ + public void testSolveAll() + throws InterruptedException, ExecutionException { + Set> solvers = Set.of( + () -> null, + () -> 1, + () -> 2, + () -> 3, + () -> null); + solveAll(cachedThreadPool, solvers); + assertEquals(Set.of(1, 2, 3), results); + } + + /** + * The second "solvers" sample code in the class javadoc works. + */ + public void testSolveAny() + throws InterruptedException { + Set> solvers = Set.of( + () -> { throw new ArithmeticException(); }, + () -> null, + () -> 1, + () -> 2); + solveAny(cachedThreadPool, solvers); + assertEquals(1, results.size()); + Integer elt = results.iterator().next(); + assertTrue(elt.equals(1) || elt.equals(2)); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java index 29db17a7a0d..6e4d00f3d0f 100644 --- a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java @@ -37,8 +37,11 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; @@ -59,7 +62,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { } /** - * Creating a new ECS with null Executor throw NPE + * new ExecutorCompletionService(null) throws NullPointerException */ public void testConstructorNPE() { try { @@ -69,111 +72,147 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { } /** - * Creating a new ECS with null queue throw NPE + * new ExecutorCompletionService(e, null) throws NullPointerException */ public void testConstructorNPE2() { try { - ExecutorService e = Executors.newCachedThreadPool(); - new ExecutorCompletionService(e, null); + new ExecutorCompletionService(cachedThreadPool, null); shouldThrow(); } catch (NullPointerException success) {} } /** - * Submitting a null callable throws NPE + * ecs.submit(null) throws NullPointerException */ - public void testSubmitNPE() { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = null; - try { - ecs.submit(c); - shouldThrow(); - } catch (NullPointerException success) {} - } + public void testSubmitNullCallable() { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + try { + cs.submit((Callable) null); + shouldThrow(); + } catch (NullPointerException success) {} } /** - * Submitting a null runnable throws NPE + * ecs.submit(null, val) throws NullPointerException */ - public void testSubmitNPE2() { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Runnable r = null; - try { - ecs.submit(r, Boolean.TRUE); - shouldThrow(); - } catch (NullPointerException success) {} - } + public void testSubmitNullRunnable() { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + try { + cs.submit((Runnable) null, Boolean.TRUE); + shouldThrow(); + } catch (NullPointerException success) {} } /** * A taken submitted task is completed */ - public void testTake() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = new StringTask(); - ecs.submit(c); - Future f = ecs.take(); - assertTrue(f.isDone()); - } + public void testTake() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + cs.submit(new StringTask()); + Future f = cs.take(); + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); } /** * Take returns the same future object returned by submit */ public void testTake2() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - Callable c = new StringTask(); - Future f1 = ecs.submit(c); - Future f2 = ecs.take(); - assertSame(f1, f2); - } + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + Future f1 = cs.submit(new StringTask()); + Future f2 = cs.take(); + assertSame(f1, f2); } /** - * If poll returns non-null, the returned task is completed + * poll returns non-null when the returned task is completed */ - public void testPoll1() throws Exception { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); - Callable c = new StringTask(); - ecs.submit(c); + public void testPoll1() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + assertNull(cs.poll()); + cs.submit(new StringTask()); - long startTime = System.nanoTime(); - Future f; - while ((f = ecs.poll()) == null) { - if (millisElapsedSince(startTime) > LONG_DELAY_MS) - fail("timed out"); - Thread.yield(); + long startTime = System.nanoTime(); + Future f; + while ((f = cs.poll()) == null) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); + } + + /** + * timed poll returns non-null when the returned task is completed + */ + public void testPoll2() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + assertNull(cs.poll()); + cs.submit(new StringTask()); + + long startTime = System.nanoTime(); + Future f; + while ((f = cs.poll(SHORT_DELAY_MS, MILLISECONDS)) == null) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); + } + + /** + * poll returns null before the returned task is completed + */ + public void testPollReturnsNull() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + final CountDownLatch proceed = new CountDownLatch(1); + cs.submit(new Callable() { public String call() throws Exception { + proceed.await(); + return TEST_STRING; + }}); + assertNull(cs.poll()); + assertNull(cs.poll(0L, MILLISECONDS)); + assertNull(cs.poll(Long.MIN_VALUE, MILLISECONDS)); + long startTime = System.nanoTime(); + assertNull(cs.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + proceed.countDown(); + assertSame(TEST_STRING, cs.take().get()); + } + + /** + * successful and failed tasks are both returned + */ + public void testTaskAssortment() + throws InterruptedException, ExecutionException { + CompletionService cs = new ExecutorCompletionService(cachedThreadPool); + ArithmeticException ex = new ArithmeticException(); + for (int i = 0; i < 2; i++) { + cs.submit(new StringTask()); + cs.submit(callableThrowing(ex)); + cs.submit(runnableThrowing(ex), null); + } + int normalCompletions = 0; + int exceptionalCompletions = 0; + for (int i = 0; i < 3 * 2; i++) { + try { + if (cs.take().get() == TEST_STRING) + normalCompletions++; + } + catch (ExecutionException expected) { + assertTrue(expected.getCause() instanceof ArithmeticException); + exceptionalCompletions++; } - assertTrue(f.isDone()); - assertSame(TEST_STRING, f.get()); - } - } - - /** - * If timed poll returns non-null, the returned task is completed - */ - public void testPoll2() throws InterruptedException { - final ExecutorService e = Executors.newCachedThreadPool(); - final ExecutorCompletionService ecs = new ExecutorCompletionService(e); - try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); - Callable c = new StringTask(); - ecs.submit(c); - Future f = ecs.poll(SHORT_DELAY_MS, MILLISECONDS); - if (f != null) - assertTrue(f.isDone()); } + assertEquals(2 * 1, normalCompletions); + assertEquals(2 * 2, exceptionalCompletions); + assertNull(cs.poll()); } /** @@ -184,7 +223,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { final AtomicBoolean done = new AtomicBoolean(false); class MyCallableFuture extends FutureTask { MyCallableFuture(Callable c) { super(c); } - protected void done() { done.set(true); } + @Override protected void done() { done.set(true); } } final ExecutorService e = new ThreadPoolExecutor(1, 1, @@ -193,15 +232,14 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { protected RunnableFuture newTaskFor(Callable c) { return new MyCallableFuture(c); }}; - ExecutorCompletionService ecs = - new ExecutorCompletionService(e); + CompletionService cs = new ExecutorCompletionService<>(e); try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); + assertNull(cs.poll()); Callable c = new StringTask(); - Future f1 = ecs.submit(c); + Future f1 = cs.submit(c); assertTrue("submit must return MyCallableFuture", f1 instanceof MyCallableFuture); - Future f2 = ecs.take(); + Future f2 = cs.take(); assertSame("submit and take must return same objects", f1, f2); assertTrue("completed task must have set done", done.get()); } @@ -215,7 +253,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { final AtomicBoolean done = new AtomicBoolean(false); class MyRunnableFuture extends FutureTask { MyRunnableFuture(Runnable t, V r) { super(t, r); } - protected void done() { done.set(true); } + @Override protected void done() { done.set(true); } } final ExecutorService e = new ThreadPoolExecutor(1, 1, @@ -224,15 +262,14 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase { protected RunnableFuture newTaskFor(Runnable t, T r) { return new MyRunnableFuture(t, r); }}; - final ExecutorCompletionService ecs = - new ExecutorCompletionService(e); + CompletionService cs = new ExecutorCompletionService<>(e); try (PoolCleaner cleaner = cleaner(e)) { - assertNull(ecs.poll()); + assertNull(cs.poll()); Runnable r = new NoOpRunnable(); - Future f1 = ecs.submit(r, null); + Future f1 = cs.submit(r, null); assertTrue("submit must return MyRunnableFuture", f1 instanceof MyRunnableFuture); - Future f2 = ecs.take(); + Future f2 = cs.take(); assertSame("submit and take must return same objects", f1, f2); assertTrue("completed task must have set done", done.get()); } diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java index b189ce6b128..14907badc6f 100644 --- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -39,6 +39,7 @@ * @modules java.management * @build * * @run junit/othervm/timeout=1000 -Djsr166.testImplementationDetails=true JSR166TestCase + * @run junit/othervm/timeout=1000 -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 -Djsr166.testImplementationDetails=true JSR166TestCase */ import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -85,6 +86,7 @@ import java.util.concurrent.RecursiveAction; import java.util.concurrent.RecursiveTask; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.Semaphore; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeoutException; @@ -546,7 +548,7 @@ public class JSR166TestCase extends TestCase { // Java9+ test classes if (atLeastJava9()) { String[] java9TestClassNames = { - // Currently empty, but expecting varhandle tests + "ExecutorCompletionService9Test", }; addNamedTestClasses(suite, java9TestClassNames); } @@ -1860,4 +1862,19 @@ public class JSR166TestCase extends TestCase { } catch (NoSuchElementException success) {} assertFalse(it.hasNext()); } + + public Callable callableThrowing(final Exception ex) { + return new Callable() { public T call() throws Exception { throw ex; }}; + } + + public Runnable runnableThrowing(final RuntimeException ex) { + return new Runnable() { public void run() { throw ex; }}; + } + + /** A reusable thread pool to be shared by tests. */ + static final ExecutorService cachedThreadPool = + new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 1000L, MILLISECONDS, + new SynchronousQueue()); + } diff --git a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java index e6dd04c23af..54b889f9427 100644 --- a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java +++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8132734 + * @bug 8132734 8144062 * @summary Test the extended API and the aliasing additions in JarFile that * support multi-release jar files * @library /lib/testlibrary/java/util/jar @@ -39,7 +39,6 @@ import java.util.Arrays; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import jdk.Version; import static java.util.jar.JarFile.Release; @@ -51,7 +50,7 @@ import org.testng.annotations.Test; public class MultiReleaseJarAPI { - static final int MAJOR_VERSION = Version.current().major(); + static final int MAJOR_VERSION = Runtime.version().major(); String userdir = System.getProperty("user.dir","."); CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); diff --git a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarIterators.java b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarIterators.java index 59900cf3f7a..60d5063ba71 100644 --- a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarIterators.java +++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarIterators.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8132734 + * @bug 8132734 8144062 * @summary Test the extended API and the aliasing additions in JarFile that * support multi-release jar files * @library /lib/testlibrary/java/util/jar @@ -42,7 +42,6 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; import java.util.zip.ZipFile; -import jdk.Version; import static java.util.jar.JarFile.Release; @@ -54,7 +53,7 @@ import org.testng.annotations.Test; public class MultiReleaseJarIterators { - static final int MAJOR_VERSION = Version.current().major(); + static final int MAJOR_VERSION = Runtime.version().major(); String userdir = System.getProperty("user.dir", "."); File unversioned = new File(userdir, "unversioned.jar"); diff --git a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java index 6bf059fb8ea..d729c438a66 100644 --- a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java +++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8132734 + * @bug 8132734 8144062 * @summary Test the System properties for JarFile that support multi-release jar files * @library /lib/testlibrary/java/util/jar * @build Compiler JarBuilder CreateMultiReleaseTestJars @@ -54,7 +54,6 @@ import java.net.URLClassLoader; import java.nio.file.Files; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import jdk.Version; import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -63,7 +62,7 @@ import org.testng.annotations.Test; public class MultiReleaseJarProperties { - static final int MAJOR_VERSION = Version.current().major(); + static final int MAJOR_VERSION = Runtime.version().major(); final static int ROOTVERSION = 8; // magic number from knowledge of internals final static String userdir = System.getProperty("user.dir", "."); diff --git a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java index 348194a3be3..538742ce192 100644 --- a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java +++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8132734 + * @bug 8132734 8144062 * @summary Test potential security related issues * @library /lib/testlibrary/java/util/jar * @build Compiler JarBuilder CreateMultiReleaseTestJars @@ -40,7 +40,6 @@ import java.util.Arrays; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.zip.ZipFile; -import jdk.Version; import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -49,7 +48,7 @@ import org.testng.annotations.Test; public class MultiReleaseJarSecurity { - static final int MAJOR_VERSION = Version.current().major(); + static final int MAJOR_VERSION = Runtime.version().major(); String userdir = System.getProperty("user.dir","."); File multirelease = new File(userdir, "multi-release.jar"); diff --git a/jdk/test/java/util/logging/XMLFormatterDate.java b/jdk/test/java/util/logging/XMLFormatterDate.java index 28eb1246694..ee0eeb98b57 100644 --- a/jdk/test/java/util/logging/XMLFormatterDate.java +++ b/jdk/test/java/util/logging/XMLFormatterDate.java @@ -21,10 +21,18 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import java.util.Calendar; -import java.util.GregorianCalendar; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.time.Month; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.util.Locale; +import java.util.Properties; +import java.util.function.Supplier; import java.util.logging.Level; +import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.XMLFormatter; @@ -33,9 +41,25 @@ import java.util.logging.XMLFormatter; * @bug 8028185 * @summary XMLFormatter.format emits incorrect year (year + 1900) * @author dfuchs + * @run main/othervm XMLFormatterDate */ public class XMLFormatterDate { + static final class TimeStamp { + + final ZonedDateTime zdt; + TimeStamp(ZoneId zoneId) { + zdt = ZonedDateTime.now(zoneId); + } + int getYear() { + return zdt.getYear(); + } + boolean isJanuaryFirst() { + return zdt.getMonth() == Month.JANUARY && zdt.getDayOfMonth() == 1; + } + } + + /** * Before the fix, JDK8 prints: {@code * @@ -64,39 +88,62 @@ public class XMLFormatterDate { try { Locale.setDefault(Locale.ENGLISH); - final GregorianCalendar cal1 = new GregorianCalendar(); - final int year1 = cal1.get(Calendar.YEAR); + // Test with default format: by default date is in UTC. + System.out.println("Testing with UTC"); + test(() -> new TimeStamp(ZoneOffset.UTC)); - LogRecord record = new LogRecord(Level.INFO, "test"); - XMLFormatter formatter = new XMLFormatter(); - final String formatted = formatter.format(record); - System.out.println(formatted); - - final GregorianCalendar cal2 = new GregorianCalendar(); - final int year2 = cal2.get(Calendar.YEAR); - if (year2 < 1900) { - throw new Error("Invalid system year: " + year2); + // Change LogManager configuration so that new + // XMLFormatter prints date in the pre Java 9 local zone format + try { + Properties props = new Properties(); + props.setProperty("java.util.logging.XMLFormatter.useInstant", "false"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + props.store(baos, ""); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + LogManager.getLogManager().updateConfiguration(bais, (k) -> (o,n) -> n!=null?n:o); + } catch (IOException io) { + throw new RuntimeException(io); } - StringBuilder buf2 = new StringBuilder() - .append("").append(year2).append("-"); - if (!formatted.contains(buf2.toString())) { - StringBuilder buf1 = new StringBuilder() - .append("").append(year1).append("-"); - if (formatted.contains(buf1) - && year2 == year1 + 1 - && cal2.get(Calendar.MONTH) == Calendar.JANUARY - && cal2.get(Calendar.DAY_OF_MONTH) == 1) { - // Oh! The year just switched in the midst of the test... - System.out.println("Happy new year!"); - } else { - throw new Error("Expected year " + year2 - + " not found in log:\n" + formatted); - } - } + // re test with the old format: date will be in the local time zone. + System.out.println("Testing with old format"); + test(() -> new TimeStamp(ZoneId.systemDefault())); + } finally { Locale.setDefault(locale); } } + static void test(Supplier timeStampSupplier) { + + TimeStamp t1 = timeStampSupplier.get(); + int year1 = t1.getYear(); + + LogRecord record = new LogRecord(Level.INFO, "test"); + XMLFormatter formatter = new XMLFormatter(); + final String formatted = formatter.format(record); + System.out.println(formatted); + + final TimeStamp t2 = timeStampSupplier.get(); + final int year2 = t2.getYear(); + if (year2 < 1900) { + throw new Error("Invalid system year: " + year2); + } + + final StringBuilder buf2 = new StringBuilder() + .append("").append(year2).append("-"); + if (!formatted.contains(buf2.toString())) { + StringBuilder buf1 = new StringBuilder() + .append("").append(year1).append("-"); + if (formatted.contains(buf1) && year2 == year1 + 1 + && t2.isJanuaryFirst()) { + // Oh! The year just switched in the midst of the test... + System.out.println("Happy new year!"); + } else { + throw new Error("Expected year " + year2 + + " not found in log:\n" + formatted); + } + } + } + } diff --git a/jdk/test/java/util/regex/RegExTest.java b/jdk/test/java/util/regex/RegExTest.java index 815cb99104e..34f9cdbfc60 100644 --- a/jdk/test/java/util/regex/RegExTest.java +++ b/jdk/test/java/util/regex/RegExTest.java @@ -34,7 +34,7 @@ * 7067045 7014640 7189363 8007395 8013252 8013254 8012646 8023647 6559590 * 8027645 8035076 8039124 8035975 8074678 6854417 8143854 8147531 7071819 * 8151481 4867170 7080302 6728861 6995635 6736245 4916384 - * 6328855 6192895 6345469 6988218 6693451 7006761 8140212 + * 6328855 6192895 6345469 6988218 6693451 7006761 8140212 8143282 * * @library /lib/testlibrary * @build jdk.testlibrary.* @@ -4345,12 +4345,13 @@ public class RegExTest { Matcher definedP = Pattern.compile("\\p{IsAssigned}").matcher(""); Matcher nonCCPP = Pattern.compile("\\p{IsNoncharacterCodePoint}").matcher(""); Matcher joinCrtl = Pattern.compile("\\p{IsJoinControl}").matcher(""); - // javaMethod Matcher lowerJ = Pattern.compile("\\p{javaLowerCase}").matcher(""); Matcher upperJ = Pattern.compile("\\p{javaUpperCase}").matcher(""); Matcher alphaJ = Pattern.compile("\\p{javaAlphabetic}").matcher(""); Matcher ideogJ = Pattern.compile("\\p{javaIdeographic}").matcher(""); + // GC/C + Matcher gcC = Pattern.compile("\\p{C}").matcher(""); for (int cp = 1; cp < 0x30000; cp++) { String str = new String(Character.toChars(cp)); @@ -4416,8 +4417,14 @@ public class RegExTest { Character.isIdeographic(cp) != ideogJ.reset(str).matches() || (Character.UNASSIGNED == type) == definedP.reset(str).matches() || POSIX_Unicode.isNoncharacterCodePoint(cp) != nonCCPP.reset(str).matches() || - POSIX_Unicode.isJoinControl(cp) != joinCrtl.reset(str).matches()) + POSIX_Unicode.isJoinControl(cp) != joinCrtl.reset(str).matches() || + // gc_C + (Character.CONTROL == type || Character.FORMAT == type || + Character.PRIVATE_USE == type || Character.SURROGATE == type || + Character.UNASSIGNED == type) + != gcC.reset(str).matches()) { failCount++; + } } // bounds/word align diff --git a/jdk/test/javax/accessibility/8017112/AccessibleIndexInParentTest.java b/jdk/test/javax/accessibility/8017112/AccessibleIndexInParentTest.java new file mode 100644 index 00000000000..87f35b40da9 --- /dev/null +++ b/jdk/test/javax/accessibility/8017112/AccessibleIndexInParentTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Component; +import javax.swing.JLabel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +/* + * @test + * @bug 8017112 + * @summary JTabbedPane components have inconsistent accessibility tree + * @run main AccessibleIndexInParentTest + */ + +public class AccessibleIndexInParentTest { + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(AccessibleIndexInParentTest::test); + } + + private static void test() { + + int N = 5; + JTabbedPane tabbedPane = new JTabbedPane(); + + for (int i = 0; i < N; i++) { + tabbedPane.addTab("Title: " + i, new JLabel("Component: " + i)); + } + + for (int i = 0; i < tabbedPane.getTabCount(); i++) { + Component child = tabbedPane.getComponentAt(i); + + AccessibleContext ac = child.getAccessibleContext(); + if (ac == null) { + throw new RuntimeException("Accessible Context is null!"); + } + + int index = ac.getAccessibleIndexInParent(); + Accessible parent = ac.getAccessibleParent(); + + if (parent.getAccessibleContext().getAccessibleChild(index) != child) { + throw new RuntimeException("Wrong getAccessibleIndexInParent!"); + } + } + } +} \ No newline at end of file diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java b/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java index 6592555706d..35f35a5c410 100644 --- a/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java +++ b/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,8 +47,16 @@ import sun.security.util.HexDumpEncoder; * An example to show the way to use SSLEngine in datagram connections. */ public class DTLSOverDatagram { + + static { + System.setProperty("javax.net.debug", "ssl"); + } + private static int MAX_HANDSHAKE_LOOPS = 200; private static int MAX_APP_READ_LOOPS = 60; + private static int SOCKET_TIMEOUT = 10 * 1000; // in millis + private static int BUFFER_SIZE = 1024; + private static int MAXIMUM_PACKET_SIZE = 1024; /* * The following is to set up the keystores. @@ -84,37 +92,33 @@ public class DTLSOverDatagram { /* * Define the server side of the test. */ - void doServerSide() throws Exception { - DatagramSocket socket = serverDatagramSocket; - socket.setSoTimeout(10000); // 10 second + void doServerSide(DatagramSocket socket, InetSocketAddress clientSocketAddr) + throws Exception { // create SSLEngine SSLEngine engine = createSSLEngine(false); // handshaking - handshake(engine, socket, clientSocketAddr); + handshake(engine, socket, clientSocketAddr, "Server"); // read client application data receiveAppData(engine, socket, clientApp); // write server application data deliverAppData(engine, socket, serverApp, clientSocketAddr); - - socket.close(); } /* * Define the client side of the test. */ - void doClientSide() throws Exception { - DatagramSocket socket = clientDatagramSocket; - socket.setSoTimeout(1000); // 1 second read timeout + void doClientSide(DatagramSocket socket, InetSocketAddress serverSocketAddr) + throws Exception { // create SSLEngine SSLEngine engine = createSSLEngine(true); // handshaking - handshake(engine, socket, serverSocketAddr); + handshake(engine, socket, serverSocketAddr, "Client"); // write client application data deliverAppData(engine, socket, clientApp, serverSocketAddr); @@ -132,7 +136,7 @@ public class DTLSOverDatagram { SSLEngine engine = context.createSSLEngine(); SSLParameters paras = engine.getSSLParameters(); - paras.setMaximumPacketSize(1024); + paras.setMaximumPacketSize(MAXIMUM_PACKET_SIZE); engine.setUseClientMode(isClient); engine.setSSLParameters(paras); @@ -142,7 +146,7 @@ public class DTLSOverDatagram { // handshake void handshake(SSLEngine engine, DatagramSocket socket, - SocketAddress peerAddr) throws Exception { + SocketAddress peerAddr, String side) throws Exception { boolean endLoops = false; int loops = MAX_HANDSHAKE_LOOPS; @@ -159,39 +163,60 @@ public class DTLSOverDatagram { if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP || hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) { + log(side, "Receive DTLS records, handshake status is " + hs); + ByteBuffer iNet; ByteBuffer iApp; if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) { - // receive ClientHello request and other SSL/TLS records - byte[] buf = new byte[1024]; + byte[] buf = new byte[BUFFER_SIZE]; DatagramPacket packet = new DatagramPacket(buf, buf.length); try { socket.receive(packet); } catch (SocketTimeoutException ste) { - List packets = - onReceiveTimeout(engine, peerAddr); + log(side, "Warning: " + ste); + + List packets = new ArrayList<>(); + boolean finished = onReceiveTimeout( + engine, peerAddr, side, packets); + for (DatagramPacket p : packets) { socket.send(p); } + if (finished) { + log(side, "Handshake status is FINISHED " + + "after calling onReceiveTimeout(), " + + "finish the loop"); + endLoops = true; + } + + log(side, "New handshake status is " + + engine.getHandshakeStatus()); + continue; } iNet = ByteBuffer.wrap(buf, 0, packet.getLength()); - iApp = ByteBuffer.allocate(1024); + iApp = ByteBuffer.allocate(BUFFER_SIZE); } else { iNet = ByteBuffer.allocate(0); - iApp = ByteBuffer.allocate(1024); + iApp = ByteBuffer.allocate(BUFFER_SIZE); } SSLEngineResult r = engine.unwrap(iNet, iApp); SSLEngineResult.Status rs = r.getStatus(); hs = r.getHandshakeStatus(); - if (rs == SSLEngineResult.Status.BUFFER_OVERFLOW) { + if (rs == SSLEngineResult.Status.OK) { + // OK + } else if (rs == SSLEngineResult.Status.BUFFER_OVERFLOW) { + log(side, "BUFFER_OVERFLOW, handshake status is " + hs); + // the client maximum fragment size config does not work? throw new Exception("Buffer overflow: " + "incorrect client maximum fragment size"); } else if (rs == SSLEngineResult.Status.BUFFER_UNDERFLOW) { + log(side, "BUFFER_UNDERFLOW, handshake status is " + hs); + // bad packet, or the client maximum fragment size // config does not work? if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { @@ -199,31 +224,64 @@ public class DTLSOverDatagram { "incorrect client maximum fragment size"); } // otherwise, ignore this packet } else if (rs == SSLEngineResult.Status.CLOSED) { - endLoops = true; - } // otherwise, SSLEngineResult.Status.OK: + throw new Exception( + "SSL engine closed, handshake status is " + hs); + } else { + throw new Exception("Can't reach here, result is " + rs); + } - if (rs != SSLEngineResult.Status.OK) { - continue; + if (hs == SSLEngineResult.HandshakeStatus.FINISHED) { + log(side, "Handshake status is FINISHED, finish the loop"); + endLoops = true; } } else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP) { - List packets = - produceHandshakePackets(engine, peerAddr); + List packets = new ArrayList<>(); + boolean finished = produceHandshakePackets( + engine, peerAddr, side, packets); + for (DatagramPacket p : packets) { socket.send(p); } + + if (finished) { + log(side, "Handshake status is FINISHED " + + "after producing handshake packets, " + + "finish the loop"); + endLoops = true; + } } else if (hs == SSLEngineResult.HandshakeStatus.NEED_TASK) { runDelegatedTasks(engine); } else if (hs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { - // OK, time to do application data exchange. + log(side, "Handshake status is NOT_HANDSHAKING, finish the loop"); endLoops = true; } else if (hs == SSLEngineResult.HandshakeStatus.FINISHED) { - endLoops = true; + throw new Exception( + "Unexpected status, SSLEngine.getHandshakeStatus() " + + "shouldn't return FINISHED"); + } else { + throw new Exception("Can't reach here, handshake status is " + hs); } } SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); + log(side, "Handshake finished, status is " + hs); + + if (engine.getHandshakeSession() != null) { + throw new Exception( + "Handshake finished, but handshake session is not null"); + } + + SSLSession session = engine.getSession(); + if (session == null) { + throw new Exception("Handshake finished, but session is null"); + } + log(side, "Negotiated protocol is " + session.getProtocol()); + log(side, "Negotiated cipher suite is " + session.getCipherSuite()); + + // handshake status should be NOT_HANDSHAKING + // according to the spec, SSLEngine.getHandshakeStatus() can't return FINISHED if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { - throw new Exception("Not ready for application data yet"); + throw new Exception("Unexpected handshake status " + hs); } } @@ -251,11 +309,11 @@ public class DTLSOverDatagram { "Too much loops to receive application data"); } - byte[] buf = new byte[1024]; + byte[] buf = new byte[BUFFER_SIZE]; DatagramPacket packet = new DatagramPacket(buf, buf.length); socket.receive(packet); ByteBuffer netBuffer = ByteBuffer.wrap(buf, 0, packet.getLength()); - ByteBuffer recBuffer = ByteBuffer.allocate(1024); + ByteBuffer recBuffer = ByteBuffer.allocate(BUFFER_SIZE); SSLEngineResult rs = engine.unwrap(netBuffer, recBuffer); recBuffer.flip(); if (recBuffer.remaining() != 0) { @@ -270,10 +328,9 @@ public class DTLSOverDatagram { } // produce handshake packets - List produceHandshakePackets( - SSLEngine engine, SocketAddress socketAddr) throws Exception { + boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, + String side, List packets) throws Exception { - List packets = new ArrayList<>(); boolean endLoops = false; int loops = MAX_HANDSHAKE_LOOPS; while (!endLoops && @@ -296,6 +353,8 @@ public class DTLSOverDatagram { throw new Exception("Buffer overflow: " + "incorrect server maximum fragment size"); } else if (rs == SSLEngineResult.Status.BUFFER_UNDERFLOW) { + log(side, "Produce handshake packets: BUFFER_UNDERFLOW occured"); + log(side, "Produce handshake packets: Handshake status: " + hs); // bad packet, or the client maximum fragment size // config does not work? if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { @@ -304,7 +363,11 @@ public class DTLSOverDatagram { } // otherwise, ignore this packet } else if (rs == SSLEngineResult.Status.CLOSED) { throw new Exception("SSLEngine has closed"); - } // otherwise, SSLEngineResult.Status.OK + } else if (rs == SSLEngineResult.Status.OK) { + // OK + } else { + throw new Exception("Can't reach here, result is " + rs); + } // SSLEngineResult.Status.OK: if (oNet.hasRemaining()) { @@ -313,25 +376,39 @@ public class DTLSOverDatagram { DatagramPacket packet = createHandshakePacket(ba, socketAddr); packets.add(packet); } + + if (hs == SSLEngineResult.HandshakeStatus.FINISHED) { + log(side, "Produce handshake packets: " + + "Handshake status is FINISHED, finish the loop"); + return true; + } + boolean endInnerLoop = false; SSLEngineResult.HandshakeStatus nhs = hs; while (!endInnerLoop) { if (nhs == SSLEngineResult.HandshakeStatus.NEED_TASK) { runDelegatedTasks(engine); - nhs = engine.getHandshakeStatus(); - } else if ((nhs == SSLEngineResult.HandshakeStatus.FINISHED) || - (nhs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) || - (nhs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)) { + } else if (nhs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP || + nhs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN || + nhs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { endInnerLoop = true; endLoops = true; } else if (nhs == SSLEngineResult.HandshakeStatus.NEED_WRAP) { endInnerLoop = true; + } else if (nhs == SSLEngineResult.HandshakeStatus.FINISHED) { + throw new Exception( + "Unexpected status, SSLEngine.getHandshakeStatus() " + + "shouldn't return FINISHED"); + } else { + throw new Exception("Can't reach here, handshake status is " + + nhs); } + nhs = engine.getHandshakeStatus(); } } - return packets; + return false; } DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) { @@ -358,7 +435,11 @@ public class DTLSOverDatagram { throw new Exception("Buffer underflow during wraping"); } else if (rs == SSLEngineResult.Status.CLOSED) { throw new Exception("SSLEngine has closed"); - } // otherwise, SSLEngineResult.Status.OK + } else if (rs == SSLEngineResult.Status.OK) { + // OK + } else { + throw new Exception("Can't reach here, result is " + rs); + } // SSLEngineResult.Status.OK: if (appNet.hasRemaining()) { @@ -386,15 +467,15 @@ public class DTLSOverDatagram { } // retransmission if timeout - List onReceiveTimeout( - SSLEngine engine, SocketAddress socketAddr) throws Exception { + boolean onReceiveTimeout(SSLEngine engine, SocketAddress socketAddr, + String side, List packets) throws Exception { SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); if (hs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { - return new ArrayList(); + return false; } else { // retransmission of handshake messages - return produceHandshakePackets(engine, socketAddr); + return produceHandshakePackets(engine, socketAddr, side, packets); } } @@ -405,8 +486,13 @@ public class DTLSOverDatagram { char[] passphrase = "passphrase".toCharArray(); - ks.load(new FileInputStream(keyFilename), passphrase); - ts.load(new FileInputStream(trustFilename), passphrase); + try (FileInputStream fis = new FileInputStream(keyFilename)) { + ks.load(fis, passphrase); + } + + try (FileInputStream fis = new FileInputStream(trustFilename)) { + ts.load(fis, passphrase); + } KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); @@ -427,94 +513,84 @@ public class DTLSOverDatagram { * The remainder is support stuff to kickstart the testing. */ - // the server side SocketAddress - volatile static SocketAddress serverSocketAddr = null; - - // the client side SocketAddress - volatile static SocketAddress clientSocketAddr = null; - - // the server side DatagramSocket instance - volatile static DatagramSocket serverDatagramSocket = null; - - // the server side DatagramSocket instance - volatile static DatagramSocket clientDatagramSocket = null; - - // get server side SocketAddress object - public SocketAddress getServerSocketAddress() { - return serverSocketAddr; - } - - // get client side SocketAddress object - public SocketAddress getClientSocketAddress() { - return clientSocketAddr; - } - - // get server side DatagramSocket object - public DatagramSocket getServerDatagramSocket() { - return serverDatagramSocket; - } - - // get client side DatagramSocket object - public DatagramSocket getClientDatagramSocket() { - return clientDatagramSocket; - } - // Will the handshaking and application data exchange succeed? public boolean isGoodJob() { return true; } public final void runTest(DTLSOverDatagram testCase) throws Exception { - serverDatagramSocket = new DatagramSocket(); - serverSocketAddr = new InetSocketAddress( - InetAddress.getLocalHost(), serverDatagramSocket.getLocalPort()); + try (DatagramSocket serverSocket = new DatagramSocket(); + DatagramSocket clientSocket = new DatagramSocket()) { - clientDatagramSocket = new DatagramSocket(); - clientSocketAddr = new InetSocketAddress( - InetAddress.getLocalHost(), clientDatagramSocket.getLocalPort()); + serverSocket.setSoTimeout(SOCKET_TIMEOUT); + clientSocket.setSoTimeout(SOCKET_TIMEOUT); - ExecutorService pool = Executors.newFixedThreadPool(2); - List> list = new ArrayList>(); + InetSocketAddress serverSocketAddr = new InetSocketAddress( + InetAddress.getLocalHost(), serverSocket.getLocalPort()); - try { - list.add(pool.submit(new ServerCallable(testCase))); // server task - list.add(pool.submit(new ClientCallable(testCase))); // client task - } finally { - pool.shutdown(); - } + InetSocketAddress clientSocketAddr = new InetSocketAddress( + InetAddress.getLocalHost(), clientSocket.getLocalPort()); + + ExecutorService pool = Executors.newFixedThreadPool(2); + Future server, client; - Exception reserved = null; - for (Future fut : list) { try { - System.out.println(fut.get()); - } catch (CancellationException | - InterruptedException | ExecutionException cie) { - if (reserved != null) { - cie.addSuppressed(reserved); - reserved = cie; - } else { - reserved = cie; - } + server = pool.submit(new ServerCallable( + testCase, serverSocket, clientSocketAddr)); + client = pool.submit(new ClientCallable( + testCase, clientSocket, serverSocketAddr)); + } finally { + pool.shutdown(); } - } - if (reserved != null) { - throw reserved; + boolean failed = false; + + // wait for client to finish + try { + System.out.println("Client finished: " + client.get()); + } catch (CancellationException | InterruptedException + | ExecutionException e) { + System.out.println("Exception on client side: "); + e.printStackTrace(System.out); + failed = true; + } + + // wait for server to finish + try { + System.out.println("Client finished: " + server.get()); + } catch (CancellationException | InterruptedException + | ExecutionException e) { + System.out.println("Exception on server side: "); + e.printStackTrace(System.out); + failed = true; + } + + if (failed) { + throw new RuntimeException("Test failed"); + } } } final static class ServerCallable implements Callable { - DTLSOverDatagram testCase; - ServerCallable(DTLSOverDatagram testCase) { + private final DTLSOverDatagram testCase; + private final DatagramSocket socket; + private final InetSocketAddress clientSocketAddr; + + ServerCallable(DTLSOverDatagram testCase, DatagramSocket socket, + InetSocketAddress clientSocketAddr) { + this.testCase = testCase; + this.socket = socket; + this.clientSocketAddr = clientSocketAddr; } @Override public String call() throws Exception { try { - testCase.doServerSide(); + testCase.doServerSide(socket, clientSocketAddr); } catch (Exception e) { + System.out.println("Exception in ServerCallable.call():"); e.printStackTrace(System.out); serverException = e; @@ -523,10 +599,6 @@ public class DTLSOverDatagram { } else { return "Well done, server!"; } - } finally { - if (serverDatagramSocket != null) { - serverDatagramSocket.close(); - } } if (testCase.isGoodJob()) { @@ -538,28 +610,33 @@ public class DTLSOverDatagram { } final static class ClientCallable implements Callable { - DTLSOverDatagram testCase; - ClientCallable(DTLSOverDatagram testCase) { + private final DTLSOverDatagram testCase; + private final DatagramSocket socket; + private final InetSocketAddress serverSocketAddr; + + ClientCallable(DTLSOverDatagram testCase, DatagramSocket socket, + InetSocketAddress serverSocketAddr) { + this.testCase = testCase; + this.socket = socket; + this.serverSocketAddr = serverSocketAddr; } @Override public String call() throws Exception { try { - testCase.doClientSide(); + testCase.doClientSide(socket, serverSocketAddr); } catch (Exception e) { + System.out.println("Exception in ClientCallable.call():"); e.printStackTrace(System.out); clientException = e; + if (testCase.isGoodJob()) { throw e; } else { return "Well done, client!"; } - } finally { - if (clientDatagramSocket != null) { - clientDatagramSocket.close(); - } } if (testCase.isGoodJob()) { @@ -600,4 +677,8 @@ public class DTLSOverDatagram { System.out.flush(); } } + + static void log(String side, String message) { + System.out.println(side + ": " + message); + } } diff --git a/jdk/test/javax/net/ssl/DTLS/Reordered.java b/jdk/test/javax/net/ssl/DTLS/Reordered.java index 9e91979a909..25053d221bb 100644 --- a/jdk/test/javax/net/ssl/DTLS/Reordered.java +++ b/jdk/test/javax/net/ssl/DTLS/Reordered.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,16 +51,17 @@ public class Reordered extends DTLSOverDatagram { } @Override - List produceHandshakePackets( - SSLEngine engine, SocketAddress socketAddr) throws Exception { - List packets = - super.produceHandshakePackets(engine, socketAddr); + boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, + String side, List packets) throws Exception { + + boolean finished = super.produceHandshakePackets( + engine, socketAddr, side, packets); if (needPacketReorder && (!engine.getUseClientMode())) { needPacketReorder = false; Collections.reverse(packets); } - return packets; + return finished; } } diff --git a/jdk/test/javax/net/ssl/DTLS/Retransmission.java b/jdk/test/javax/net/ssl/DTLS/Retransmission.java index 75aecab22fb..840b08a7d7d 100644 --- a/jdk/test/javax/net/ssl/DTLS/Retransmission.java +++ b/jdk/test/javax/net/ssl/DTLS/Retransmission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,13 +52,14 @@ public class Retransmission extends DTLSOverDatagram { } @Override - List produceHandshakePackets( - SSLEngine engine, SocketAddress socketAddr) throws Exception { - List packets = - super.produceHandshakePackets(engine, socketAddr); + boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, + String side, List packets) throws Exception { + + boolean finished = super.produceHandshakePackets( + engine, socketAddr, side, packets); if (!needPacketLoss || (!engine.getUseClientMode())) { - return packets; + return finished; } List parts = new ArrayList<>(); @@ -75,6 +76,9 @@ public class Retransmission extends DTLSOverDatagram { parts.add(packet); } - return parts; + packets.clear(); + packets.addAll(parts); + + return finished; } } diff --git a/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java b/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java index 0a482f31b90..0e40e52ce9b 100644 --- a/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java +++ b/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /** * @test * @library /lib/testlibrary + * @modules jdk.httpserver * @build jdk.testlibrary.SimpleSSLContext * @run main Equals * @bug 8055299 diff --git a/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java index ba3e5f10e50..bda0710f61e 100644 --- a/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java +++ b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java @@ -34,9 +34,6 @@ */ import java.io.*; -import java.nio.*; -import java.nio.channels.*; -import java.util.*; import java.net.*; import javax.net.ssl.*; @@ -197,6 +194,7 @@ public class BestEffortOnLazyConnected { hostname); // Ignore the test if the hostname does not sound like a domain name. if ((hostname == null) || hostname.isEmpty() || + !hostname.contains(".") || hostname.endsWith(".") || hostname.startsWith("localhost") || Character.isDigit(hostname.charAt(hostname.length() - 1))) { diff --git a/jdk/test/javax/net/ssl/TLS/CipherTestUtils.java b/jdk/test/javax/net/ssl/TLS/CipherTestUtils.java index a86b10abd26..04020bc6f03 100644 --- a/jdk/test/javax/net/ssl/TLS/CipherTestUtils.java +++ b/jdk/test/javax/net/ssl/TLS/CipherTestUtils.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it under @@ -202,6 +202,8 @@ public class CipherTestUtils { @Override public abstract void run(); + abstract int getPort(); + void handleRequest(InputStream in, OutputStream out) throws IOException { boolean newline = false; @@ -528,9 +530,9 @@ public class CipherTestUtils { return ks; } - public static void main(PeerFactory peerFactory, String mode, - String expectedException) - throws Exception { + public static int mainServer(PeerFactory peerFactory, + String expectedException) throws Exception { + long time = System.currentTimeMillis(); setTestedArguments(peerFactory.getTestedProtocol(), peerFactory.getTestedCipher()); @@ -540,33 +542,49 @@ public class CipherTestUtils { secureRandom.nextInt(); CipherTestUtils cipherTest = CipherTestUtils.getInstance(); - if (mode.equalsIgnoreCase("Server")) { // server mode - Thread serverThread = new Thread(peerFactory.newServer(cipherTest), - "Server"); - serverThread.start(); - } else if (mode.equalsIgnoreCase("Client")) { - peerFactory.newClient(cipherTest).run(); - cipherTest.checkResult(expectedException); - JSSEServer.closeServer = true; - } else { - throw new RuntimeException("unsupported mode"); - } + Server server = peerFactory.newServer(cipherTest, PeerFactory.FREE_PORT); + Thread serverThread = new Thread(server, "Server"); + serverThread.start(); + time = System.currentTimeMillis() - time; System.out.println("Elapsed time " + time); + return server.getPort(); + } + + public static void mainClient(PeerFactory peerFactory, int port, + String expectedException) throws Exception { + + long time = System.currentTimeMillis(); + setTestedArguments(peerFactory.getTestedProtocol(), + peerFactory.getTestedCipher()); + + System.out.print( + " Initializing test '" + peerFactory.getName() + "'..."); + secureRandom.nextInt(); + + CipherTestUtils cipherTest = CipherTestUtils.getInstance(); + peerFactory.newClient(cipherTest, port).run(); + cipherTest.checkResult(expectedException); + JSSEServer.closeServer = true; + + time = System.currentTimeMillis() - time; + System.out.println("Elapsed time " + time); } public static abstract class PeerFactory { + public static final int FREE_PORT = 0; + abstract String getName(); abstract String getTestedProtocol(); abstract String getTestedCipher(); - abstract Client newClient(CipherTestUtils cipherTest) throws Exception; + abstract Client newClient(CipherTestUtils cipherTest, int testPort) throws Exception; - abstract Server newServer(CipherTestUtils cipherTest) throws Exception; + abstract Server newServer(CipherTestUtils cipherTest, int testPort) throws Exception; boolean isSupported(String cipherSuite) { return true; diff --git a/jdk/test/javax/net/ssl/TLS/JSSEServer.java b/jdk/test/javax/net/ssl/TLS/JSSEServer.java index f6e55a31706..1ece6f0f8b8 100644 --- a/jdk/test/javax/net/ssl/TLS/JSSEServer.java +++ b/jdk/test/javax/net/ssl/TLS/JSSEServer.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it under @@ -77,4 +77,8 @@ public class JSSEServer extends CipherTestUtils.Server { } } } + + int getPort() { + return serverSocket.getLocalPort(); + } } diff --git a/jdk/test/javax/net/ssl/TLS/TestJSSE.java b/jdk/test/javax/net/ssl/TLS/TestJSSE.java index d4c41480c0b..d477e4facdf 100644 --- a/jdk/test/javax/net/ssl/TLS/TestJSSE.java +++ b/jdk/test/javax/net/ssl/TLS/TestJSSE.java @@ -27,10 +27,8 @@ import java.security.Security; /** * @test * @bug 8049429 - * @library ../../../../lib/testlibrary/ * @modules java.management * jdk.crypto.ec/sun.security.ec - * @build jdk.testlibrary.Utils * @compile CipherTestUtils.java JSSEClient.java JSSEServer.java * @summary Test that all cipher suites work in all versions and all client * authentication types. The way this is setup the server is stateless and @@ -86,7 +84,6 @@ public class TestJSSE { String serverProtocol = System.getProperty("SERVER_PROTOCOL"); String clientProtocol = System.getProperty("CLIENT_PROTOCOL"); - int port = jdk.testlibrary.Utils.getFreePort(); String cipher = System.getProperty("CIPHER"); if (serverProtocol == null || clientProtocol == null @@ -97,7 +94,7 @@ public class TestJSSE { out.println("ServerProtocol =" + serverProtocol); out.println("ClientProtocol =" + clientProtocol); out.println("Cipher =" + cipher); - server(serverProtocol, cipher, port, args); + int port = server(serverProtocol, cipher, args); client(port, clientProtocol, cipher, args); } @@ -112,28 +109,30 @@ public class TestJSSE { out.println(" Testing - Protocol : " + testProtocols); out.println(" Testing - Cipher : " + testCipher); try { - CipherTestUtils.main(new JSSEFactory(LOCAL_IP, - testPort, testProtocols, - testCipher, "client JSSE"), - "client", expectedException); + CipherTestUtils.mainClient(new JSSEFactory(LOCAL_IP, testProtocols, + testCipher, "Client JSSE"), + testPort, expectedException); } catch (Exception e) { throw new RuntimeException(e); } } - public static void server(String testProtocol, String testCipher, - int testPort, + public static int server(String testProtocol, String testCipher, String... exception) throws Exception { + String expectedException = exception.length >= 1 ? exception[0] : null; out.println(" This is Server"); out.println(" Testing Protocol: " + testProtocol); out.println(" Testing Cipher: " + testCipher); - out.println(" Testing Port: " + testPort); + try { - CipherTestUtils.main(new JSSEFactory(null, testPort, - testProtocol, testCipher, "Server JSSE"), - "Server", expectedException); + int port = CipherTestUtils.mainServer(new JSSEFactory( + null, testProtocol, testCipher, "Server JSSE"), + expectedException); + + out.println(" Testing Port: " + port); + return port; } catch (Exception e) { throw new RuntimeException(e); } @@ -142,15 +141,13 @@ public class TestJSSE { private static class JSSEFactory extends CipherTestUtils.PeerFactory { final String testedCipherSuite, testedProtocol, testHost; - final int testPort; final String name; - JSSEFactory(String testHost, int testPort, String testedProtocol, + JSSEFactory(String testHost, String testedProtocol, String testedCipherSuite, String name) { this.testedCipherSuite = testedCipherSuite; this.testedProtocol = testedProtocol; this.testHost = testHost; - this.testPort = testPort; this.name = name; } @@ -170,14 +167,14 @@ public class TestJSSE { } @Override - CipherTestUtils.Client newClient(CipherTestUtils cipherTest) + CipherTestUtils.Client newClient(CipherTestUtils cipherTest, int testPort) throws Exception { return new JSSEClient(cipherTest, testHost, testPort, testedProtocol, testedCipherSuite); } @Override - CipherTestUtils.Server newServer(CipherTestUtils cipherTest) + CipherTestUtils.Server newServer(CipherTestUtils cipherTest, int testPort) throws Exception { return new JSSEServer(cipherTest, testPort, testedProtocol, testedCipherSuite); diff --git a/jdk/test/javax/net/ssl/etc/README b/jdk/test/javax/net/ssl/etc/README new file mode 100644 index 00000000000..0ac6a844a86 --- /dev/null +++ b/jdk/test/javax/net/ssl/etc/README @@ -0,0 +1,94 @@ +Keystores used for the JSSE regression test suite. + +keystore +truststore +========== + +These are the primary two keystores and contain entries for testing most +of the JSSE regression test files. There are three entries, one RSA-based, +one DSA-based and one EC-based. If they expire, simply recreate them +using keytool and most of the test cases should work. + +The password on both files is: + + passphrase + +There are no individual key entry passwords at this time. + + +keystore entries +================ + +Alias name: dummy +----------------- +Creation date: May 16, 2016 +Entry type: PrivateKeyEntry +Certificate chain length: 1 +Certificate[1]: +Owner: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US +Issuer: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US +Serial number: 57399b87 +Valid from: Mon May 16 10:06:38 UTC 2016 until: Sat May 16 10:06:38 UTC 2026 +Signature algorithm name: SHA256withRSA +Version: 1 + +This can be generated using hacked (update the keytool source code so that +it can be used for version 1 X.509 certificate) keytool command: +% keytool -genkeypair -alias dummy -keyalg RSA -keysize 2048 \ + -sigalg SHA256withRSA \ + -dname "CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US" \ + -validity 3652 -keypass passphrase -keystore keystore -storepass passphrase + + +Alias name: dummyecdsa +---------------------- +Creation date: May 16, 2016 +Entry type: PrivateKeyEntry +Certificate chain length: 1 +Certificate[1]: +Owner: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US +Issuer: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US +Serial number: 57399c1d +Valid from: Mon May 16 10:09:01 UTC 2016 until: Sat May 16 10:09:01 UTC 2026 +Signature algorithm name: SHA256withECDSA +Version: 1 + +This can be generated using hacked (update the keytool source code so that +it can be used for version 1 X.509 certificate) keytool command: +% keytool -genkeypair -alias dummy -keyalg EC -keysize 256 \ + -sigalg SHA256withECDSA \ + -dname "CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US" \ + -validity 3652 -keypass passphrase -keystore keystore -storepass passphrase + +Alias name: dummydsa +-------------------- +Creation date: Mar 11, 2007 +Entry type: PrivateKeyEntry +Certificate chain length: 1 +Certificate[1]: +Owner: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US +Issuer: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US +Serial number: 45f3a314 +Valid from: Sun Mar 11 06:35:00 UTC 2007 until: Wed Mar 08 06:35:00 UTC 2017 +Certificate fingerprints: +Signature algorithm name: SHA1withDSA +Version: 1 + +This can be generated using hacked (update the keytool source code so that +it can be used for version 1 X.509 certificate) keytool command: +% keytool -genkeypair -alias dummy -keyalg DSA -keysize 1024 \ + -sigalg SHA1withDSA \ + -dname "CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US" \ + -validity 3652 -keypass passphrase -keystore keystore -storepass passphrase + + +truststore entries +================== +This key store contains only trusted certificate entries. The same +certificates are used in both keystore and truststore. + + +unknown_keystore +================ +A keystore you can use when you don't want things to be verified. +Use this with keystore/truststore, and you'll never get a match. diff --git a/jdk/test/javax/net/ssl/etc/keystore b/jdk/test/javax/net/ssl/etc/keystore index 2eb1993f3af..4062e1798c5 100644 Binary files a/jdk/test/javax/net/ssl/etc/keystore and b/jdk/test/javax/net/ssl/etc/keystore differ diff --git a/jdk/test/javax/net/ssl/etc/truststore b/jdk/test/javax/net/ssl/etc/truststore index 65a140d7732..12da39e66a5 100644 Binary files a/jdk/test/javax/net/ssl/etc/truststore and b/jdk/test/javax/net/ssl/etc/truststore differ diff --git a/jdk/test/javax/rmi/TEST.properties b/jdk/test/javax/rmi/TEST.properties new file mode 100644 index 00000000000..d4bbfc905b9 --- /dev/null +++ b/jdk/test/javax/rmi/TEST.properties @@ -0,0 +1 @@ +modules = java.rmi diff --git a/jdk/test/javax/script/ProviderTest.sh b/jdk/test/javax/script/ProviderTest.sh index 1db161dfcf6..24b4120912c 100644 --- a/jdk/test/javax/script/ProviderTest.sh +++ b/jdk/test/javax/script/ProviderTest.sh @@ -43,8 +43,18 @@ $JAR ${TESTTOOLVMOPTS} -cf ${TESTCLASSES}/dummy.jar \ -C ${TESTCLASSES} DummyScriptEngineFactory.class \ -C "${TESTSRC}" META-INF/services/javax.script.ScriptEngineFactory -echo "Running test ..." +echo "Running test with security manager ..." +$JAVA ${TESTVMOPTS} -Djava.security.manager -classpath \ + "${TESTCLASSES}${PS}${TESTCLASSES}/dummy.jar" \ + ProviderTest +ret=$? +if [ $ret -ne 0 ] +then + exit $ret +fi + +echo "Running test without security manager ..." $JAVA ${TESTVMOPTS} -classpath \ "${TESTCLASSES}${PS}${TESTCLASSES}/dummy.jar" \ ProviderTest diff --git a/jdk/test/javax/script/TEST.properties b/jdk/test/javax/script/TEST.properties new file mode 100644 index 00000000000..3bb100c3fad --- /dev/null +++ b/jdk/test/javax/script/TEST.properties @@ -0,0 +1 @@ +modules = java.scripting diff --git a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAiffFiles.java b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAiffFiles.java new file mode 100644 index 00000000000..c0899484328 --- /dev/null +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAiffFiles.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 6729836 + */ +public final class RecognizeHugeAiffFiles { + + /** + * The maximum number of sample frames per AIFF specification. + */ + private static final /* unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL; + + /** + * The supported aiff sample size in bits. + */ + private static final byte[] aiffBits = { + 1, 2, 4, 8, 11, 16, 20, 24, 27, 32 + }; + + /** + * The list of supported sample rates. + */ + private static final int[] sampleRates = { + 8000, 11025, 16000, 22050, 32000, 37800, 44056, 44100, 47250, 48000, + 50000, 50400, 88200, 96000, 176400, 192000, 352800, 2822400, + 5644800, Integer.MAX_VALUE + }; + + /** + * The list of supported channels. + */ + private static final int[] channels = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + }; + + /** + * The list of supported number of frames. + *

    + * The {@code MAX_UNSIGNED_INT} is a maximum. + */ + private static final long[] numberOfFrames = { + 0, 1, 2, 3, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, + (long) Integer.MAX_VALUE + 1, MAX_UNSIGNED_INT - 1, MAX_UNSIGNED_INT + }; + + public static void main(final String[] args) throws Exception { + for (final byte bits : aiffBits) { + for (final int sampleRate : sampleRates) { + for (final int channel : channels) { + for (final long dataSize : numberOfFrames) { + testAFF(bits, sampleRate, channel, dataSize); + testAIS(bits, sampleRate, channel, dataSize); + } + } + } + } + } + + /** + * Tests the {@code AudioFileFormat} fetched from the fake header. + *

    + * Note that the frameLength and byteLength are stored as int which means + * that {@code AudioFileFormat} will store the data above {@code MAX_INT} as + * NOT_SPECIFIED. + */ + private static void testAFF(final byte bits, final int rate, + final int channel, final long frameLength) + throws Exception { + final byte[] header = createHeader(bits, rate, channel, frameLength); + final ByteArrayInputStream fake = new ByteArrayInputStream(header); + final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake); + + if (aff.getType() != AudioFileFormat.Type.AIFF) { + throw new RuntimeException("Error"); + } + + if (frameLength <= Integer.MAX_VALUE) { + if (aff.getFrameLength() != frameLength) { + System.err.println("Expected: " + frameLength); + System.err.println("Actual: " + aff.getFrameLength()); + throw new RuntimeException(); + } + } else { + if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) { + System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED); + System.err.println("Actual: " + aff.getFrameLength()); + throw new RuntimeException(); + } + } + validateFormat(bits, rate, channel, aff.getFormat()); + } + + /** + * Tests the {@code AudioInputStream} fetched from the fake header. + *

    + * Note that the frameLength is stored as long which means that {@code + * AudioInputStream} must store all possible data from aiff file. + */ + private static void testAIS(final byte bits, final int rate, + final int channel, final long frameLength) + throws Exception { + final byte[] header = createHeader(bits, rate, channel, frameLength); + final ByteArrayInputStream fake = new ByteArrayInputStream(header); + final AudioInputStream ais = AudioSystem.getAudioInputStream(fake); + final AudioFormat format = ais.getFormat(); + + if (frameLength != ais.getFrameLength()) { + System.err.println("Expected: " + frameLength); + System.err.println("Actual: " + ais.getFrameLength()); + throw new RuntimeException(); + } + if (ais.available() < 0) { + System.err.println("available should be >=0: " + ais.available()); + throw new RuntimeException(); + } + + validateFormat(bits, rate, channel, format); + } + + /** + * Tests that format contains the same data as were provided to the fake + * stream. + */ + private static void validateFormat(final byte bits, final int rate, + final int channel, + final AudioFormat format) { + + if (Float.compare(format.getSampleRate(), rate) != 0) { + System.err.println("Expected: " + rate); + System.err.println("Actual: " + format.getSampleRate()); + throw new RuntimeException(); + } + if (format.getChannels() != channel) { + System.err.println("Expected: " + channel); + System.err.println("Actual: " + format.getChannels()); + throw new RuntimeException(); + } + int frameSize = ((bits + 7) / 8) * channel; + if (format.getFrameSize() != frameSize) { + System.out.println("Expected: " + frameSize); + System.err.println("Actual: " + format.getFrameSize()); + throw new RuntimeException(); + } + } + + private static final int DOUBLE_MANTISSA_LENGTH = 52; + private static final int DOUBLE_EXPONENT_LENGTH = 11; + private static final long DOUBLE_SIGN_MASK = 0x8000000000000000L; + private static final long DOUBLE_EXPONENT_MASK = 0x7FF0000000000000L; + private static final long DOUBLE_MANTISSA_MASK = 0x000FFFFFFFFFFFFFL; + private static final int DOUBLE_EXPONENT_OFFSET = 1023; + + private static final int EXTENDED_EXPONENT_OFFSET = 16383; + private static final int EXTENDED_MANTISSA_LENGTH = 63; + private static final int EXTENDED_EXPONENT_LENGTH = 15; + private static final long EXTENDED_INTEGER_MASK = 0x8000000000000000L; + + /** + * Creates the custom header of the AIFF file. It is expected that all + * passed data are supported. + */ + private static byte[] createHeader(final byte bits, final int rate, + final int channel, final long frameLength) { + long doubleBits = Double.doubleToLongBits(rate); + + long sign = (doubleBits & DOUBLE_SIGN_MASK) + >> (DOUBLE_EXPONENT_LENGTH + DOUBLE_MANTISSA_LENGTH); + long doubleExponent = (doubleBits & DOUBLE_EXPONENT_MASK) + >> DOUBLE_MANTISSA_LENGTH; + long doubleMantissa = doubleBits & DOUBLE_MANTISSA_MASK; + + long extendedExponent = doubleExponent - DOUBLE_EXPONENT_OFFSET + + EXTENDED_EXPONENT_OFFSET; + long extendedMantissa = doubleMantissa + << (EXTENDED_MANTISSA_LENGTH - DOUBLE_MANTISSA_LENGTH); + long extendedSign = sign << EXTENDED_EXPONENT_LENGTH; + short extendedBits79To64 = (short) (extendedSign | extendedExponent); + long extendedBits63To0 = EXTENDED_INTEGER_MASK | extendedMantissa; + + return new byte[]{ + // AIFF_MAGIC + 0x46, 0x4f, 0x52, 0x4d, + // fileLength (will use the number of frames for testing) + (byte) (frameLength >> 24), (byte) (frameLength >> 16), + (byte) (frameLength >> 8), (byte) frameLength, + // form aiff + 0x41, 0x49, 0x46, 0x46, + // COMM_MAGIC + 0x43, 0x4f, 0x4d, 0x4d, + // comm chunk size + 0, 0, 0, 18, + // channels + (byte) (channel >> 8),(byte) channel, + // numSampleFrames + (byte) (frameLength >> 24), (byte) (frameLength >> 16), + (byte) (frameLength >> 8), (byte) (frameLength), + // samplesize + (byte) (bits >> 8),(byte) (bits), + // samplerate + (byte) (extendedBits79To64 >> 8), + (byte) extendedBits79To64, + (byte) (extendedBits63To0 >> 56), + (byte) (extendedBits63To0 >> 48), + (byte) (extendedBits63To0 >> 40), + (byte) (extendedBits63To0 >> 32), (byte) (extendedBits63To0 >> 24), + (byte) (extendedBits63To0 >> 16), (byte) (extendedBits63To0 >> 8), + (byte) extendedBits63To0, + // SND_MAGIC + 0x53, 0x53, 0x4e, 0x44, + // data chunk size + 0, 0, 0, 0, + // dataOffset + 0, 0, 0, 0, + // blocksize + 0, 0, 0, 0, + }; + } +} diff --git a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAuFiles.java b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAuFiles.java new file mode 100644 index 00000000000..ba908667299 --- /dev/null +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAuFiles.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 6729836 + */ +public final class RecognizeHugeAuFiles { + + /** + * The size of the header's data. + */ + private static final byte AU_HEADER = 44; + + /** + * This value should be used if the size in bytes is unknown. + */ + private static final /* unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL; + + /** + * The list of supported au formats and sample size in bits per format. + */ + private static final byte[][] auTypeBits = { + {1, 8}, {2, 8}, {3, 16}, {4, 24}, {5, 32}, {6, 32}, {27, 8} + }; + + /** + * The list of supported sample rates(stored as unsigned int). + */ + private static final int[] sampleRates = { + 8000, 11025, 16000, 22050, 32000, 37800, 44056, 44100, 47250, 48000, + 50000, 50400, 88200, 96000, 176400, 192000, 352800, 2822400, + 5644800, Integer.MAX_VALUE + }; + + /** + * The list of supported channels (stored as unsigned int). + */ + private static final int[] channels = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + }; + + /** + * The list of supported size of data (stored as unsigned int). + *

    + * The {@code MAX_UNSIGNED_INT} used if the size in bytes is unknown. + */ + private static final long[] dataSizes = { + 0, 1, 2, 3, Integer.MAX_VALUE - AU_HEADER, Integer.MAX_VALUE - 1, + Integer.MAX_VALUE, (long) Integer.MAX_VALUE + 1, + (long) Integer.MAX_VALUE + AU_HEADER, MAX_UNSIGNED_INT - AU_HEADER, + MAX_UNSIGNED_INT - 1, MAX_UNSIGNED_INT + }; + + public static void main(final String[] args) throws Exception { + for (final byte[] type : auTypeBits) { + for (final int sampleRate : sampleRates) { + for (final int channel : channels) { + for (final long dataSize : dataSizes) { + testAFF(type, sampleRate, channel, dataSize); + testAIS(type, sampleRate, channel, dataSize); + } + } + } + } + } + + /** + * Tests the {@code AudioFileFormat} fetched from the fake header. + *

    + * Note that the frameLength and byteLength are stored as int which means + * that {@code AudioFileFormat} will store the data above {@code MAX_INT} + * as NOT_SPECIFIED. + */ + private static void testAFF(final byte[] type, final int rate, + final int channel, final long size) + throws Exception { + final byte[] header = createHeader(type, rate, channel, size); + final ByteArrayInputStream fake = new ByteArrayInputStream(header); + final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake); + final AudioFormat format = aff.getFormat(); + + if (aff.getType() != AudioFileFormat.Type.AU) { + throw new RuntimeException("Error"); + } + + final long frameLength = size / format.getFrameSize(); + if (size != MAX_UNSIGNED_INT && frameLength <= Integer.MAX_VALUE) { + if (aff.getFrameLength() != frameLength) { + System.err.println("Expected: " + frameLength); + System.err.println("Actual: " + aff.getFrameLength()); + throw new RuntimeException(); + } + } else { + if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) { + System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED); + System.err.println("Actual: " + aff.getFrameLength()); + throw new RuntimeException(); + } + } + + final long byteLength = size + AU_HEADER; + if (byteLength <= Integer.MAX_VALUE) { + if (aff.getByteLength() != byteLength) { + System.err.println("Expected: " + byteLength); + System.err.println("Actual: " + aff.getByteLength()); + throw new RuntimeException(); + } + } else { + if (aff.getByteLength() != AudioSystem.NOT_SPECIFIED) { + System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED); + System.err.println("Actual: " + aff.getByteLength()); + throw new RuntimeException(); + } + } + validateFormat(type[1], rate, channel, aff.getFormat()); + } + + /** + * Tests the {@code AudioInputStream} fetched from the fake header. + *

    + * Note that the frameLength is stored as long which means + * that {@code AudioInputStream} must store all possible data from au file. + */ + private static void testAIS(final byte[] type, final int rate, + final int channel, final long size) + throws Exception { + final byte[] header = createHeader(type, rate, channel, size); + final ByteArrayInputStream fake = new ByteArrayInputStream(header); + final AudioInputStream ais = AudioSystem.getAudioInputStream(fake); + final AudioFormat format = ais.getFormat(); + final long frameLength = size / format.getFrameSize(); + if (size != MAX_UNSIGNED_INT) { + if (frameLength != ais.getFrameLength()) { + System.err.println("Expected: " + frameLength); + System.err.println("Actual: " + ais.getFrameLength()); + throw new RuntimeException(); + } + } else { + if (ais.getFrameLength() != AudioSystem.NOT_SPECIFIED) { + System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED); + System.err.println("Actual: " + ais.getFrameLength()); + throw new RuntimeException(); + } + } + if (ais.available() < 0) { + System.err.println("available should be >=0: " + ais.available()); + throw new RuntimeException(); + } + validateFormat(type[1], rate, channel, format); + } + + /** + * Tests that format contains the same data as were provided to the fake + * stream. + */ + private static void validateFormat(final byte bits, final int rate, + final int channel, + final AudioFormat format) { + + if (Float.compare(format.getSampleRate(), rate) != 0) { + System.out.println("Expected: " + rate); + System.out.println("Actual: " + format.getSampleRate()); + throw new RuntimeException(); + } + if (format.getChannels() != channel) { + System.out.println("Expected: " + channel); + System.out.println("Actual: " + format.getChannels()); + throw new RuntimeException(); + } + int frameSize = ((bits + 7) / 8) * channel; + if (format.getFrameSize() != frameSize) { + System.out.println("Expected: " + frameSize); + System.out.println("Actual: " + format.getFrameSize()); + throw new RuntimeException(); + } + } + + /** + * Creates the custom header of the AU file. It is expected that all passed + * data are supported. + */ + private static byte[] createHeader(final byte[] type, final int rate, + final int channel, final long size) { + return new byte[]{ + // AU_SUN_MAGIC + 0x2e, 0x73, 0x6e, 0x64, + // headerSize + 0, 0, 0, AU_HEADER, + // dataSize + (byte) (size >> 24), (byte) (size >> 16), (byte) (size >> 8), + (byte) size, + // encoding + 0, 0, 0, type[0], + // sampleRate + (byte) (rate >> 24), (byte) (rate >> 16), (byte) (rate >> 8), + (byte) (rate), + // channels + (byte) (channel >> 24), (byte) (channel >> 16), + (byte) (channel >> 8), (byte) (channel), + // data + 0, 0, 0, 0, 0, 0 + }; + } +} diff --git a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveExtFiles.java b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveExtFiles.java index 88b231d62d7..ca8d17e3e78 100644 --- a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveExtFiles.java +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveExtFiles.java @@ -125,7 +125,7 @@ public final class RecognizeHugeWaveExtFiles { * Tests the {@code AudioInputStream} fetched from the fake header. *

    * Note that the frameLength is stored as long which means that {@code - * AudioInputStream} must store all possible data from au file. + * AudioInputStream} must store all possible data from wave file. */ private static void testAIS(final int[] type, final int rate, final int channel, final long size) @@ -166,8 +166,9 @@ public final class RecognizeHugeWaveExtFiles { System.err.println("Actual: " + format.getChannels()); throw new RuntimeException(); } - if (format.getFrameSize() != ((bits + 7) / 8) * channel) { - System.err.println("Expected: " + (bits * channel + 1) / 8); + int frameSize = ((bits + 7) / 8) * channel; + if (format.getFrameSize() != frameSize) { + System.err.println("Expected: " + frameSize); System.err.println("Actual: " + format.getFrameSize()); throw new RuntimeException(); } diff --git a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFloatFiles.java b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFiles.java similarity index 91% rename from jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFloatFiles.java rename to jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFiles.java index e36a7e2b180..191290a128e 100644 --- a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFloatFiles.java +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFiles.java @@ -30,9 +30,9 @@ import javax.sound.sampled.AudioSystem; /** * @test - * @bug 8132782 + * @bug 8132782 6729836 */ -public final class RecognizeHugeWaveFloatFiles { +public final class RecognizeHugeWaveFiles { /** * The maximum size in bytes per WAVE specification. @@ -43,7 +43,17 @@ public final class RecognizeHugeWaveFloatFiles { * The supported wave pcm_float format and sample size in bits. */ private static final byte[][] waveTypeBits = { - {0x0003/*WAVE_FORMAT_IEEE_FLOAT*/, 32} + {0x0001/*WAVE_FORMAT_PCM*/,1}, + {0x0001/*WAVE_FORMAT_PCM*/,2}, + {0x0001/*WAVE_FORMAT_PCM*/,4}, + {0x0001/*WAVE_FORMAT_PCM*/,8}, + {0x0001/*WAVE_FORMAT_PCM*/,16}, + {0x0001/*WAVE_FORMAT_PCM*/,20}, + {0x0001/*WAVE_FORMAT_PCM*/,24}, + {0x0001/*WAVE_FORMAT_PCM*/,32}, + {0x0003/*WAVE_FORMAT_IEEE_FLOAT*/, 32}, + {0x0006/*WAVE_FORMAT_ALAW*/, 8}, + {0x0007/*WAVE_FORMAT_MULAW*/, 8} }; /** @@ -125,7 +135,7 @@ public final class RecognizeHugeWaveFloatFiles { * Tests the {@code AudioInputStream} fetched from the fake header. *

    * Note that the frameLength is stored as long which means that {@code - * AudioInputStream} must store all possible data from au file. + * AudioInputStream} must store all possible data from wave file. */ private static void testAIS(final byte[] type, final int rate, final int channel, final long size) @@ -166,8 +176,9 @@ public final class RecognizeHugeWaveFloatFiles { System.err.println("Actual: " + format.getChannels()); throw new RuntimeException(); } - if (format.getFrameSize() != ((bits + 7) / 8) * channel) { - System.err.println("Expected: " + (bits * channel + 1) / 8); + int frameSize = ((bits + 7) / 8) * channel; + if (format.getFrameSize() != frameSize) { + System.err.println("Expected: " + frameSize); System.err.println("Actual: " + format.getFrameSize()); throw new RuntimeException(); } diff --git a/jdk/test/javax/swing/JFileChooser/8152677/SelectAllFilesFilterTest.java b/jdk/test/javax/swing/JFileChooser/8152677/SelectAllFilesFilterTest.java new file mode 100644 index 00000000000..bc17b04a306 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/8152677/SelectAllFilesFilterTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Component; +import java.awt.Container; +import java.awt.Robot; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; + +/* + * @test + * @bug 8152677 + * @requires (os.family == "mac") + * @summary [macosx] All files filter can't be selected in JFileChooser + * @run main SelectAllFilesFilterTest + */ + +public class SelectAllFilesFilterTest { + + private static final String LABEL_TEXT = "File Format:"; + private static volatile JFileChooser fileChooser; + private static JComboBox comboBox; + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeLater(SelectAllFilesFilterTest::createAndShowGUI); + + while (fileChooser == null) { + Thread.sleep(100); + } + + Robot robot = new Robot(); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> { + comboBox = findComboBox(fileChooser); + comboBox.setSelectedIndex(0); + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> { + int selectedIndex = comboBox.getSelectedIndex(); + fileChooser.setVisible(false); + + if (selectedIndex != 0) { + throw new RuntimeException("Select All file filter is not selected!"); + } + }); + } + + private static void createAndShowGUI() { + fileChooser = new JFileChooser(); + fileChooser.setAcceptAllFileFilterUsed(true); + fileChooser.setDialogType(JFileChooser.OPEN_DIALOG); + + FileFilter txtFilter = new FileNameExtensionFilter("Text files", "txt"); + fileChooser.addChoosableFileFilter(txtFilter); + fileChooser.setFileFilter(txtFilter); + fileChooser.showOpenDialog(null); + } + + private static JComboBox findComboBox(Component comp) { + + if (comp instanceof JLabel) { + JLabel label = (JLabel) comp; + if (LABEL_TEXT.equals(label.getText())) { + return (JComboBox) label.getLabelFor(); + } + } + + if (comp instanceof Container) { + Container cont = (Container) comp; + for (int i = 0; i < cont.getComponentCount(); i++) { + + JComboBox result = findComboBox(cont.getComponent(i)); + if (result != null) { + return result; + } + } + } + + return null; + } +} diff --git a/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java b/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java index 1a9f42120e2..589bb9b5744 100644 --- a/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java +++ b/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java @@ -21,23 +21,23 @@ * questions. */ -/* + /* * @test - * @bug 7160951 + * @bug 7160951 8152492 * @summary [macosx] ActionListener called twice for JMenuItem using ScreenMenuBar * @author vera.akulova@oracle.com * @library ../../../../lib/testlibrary * @build jdk.testlibrary.OSInfo * @run main ActionListenerCalledTwiceTest */ - import jdk.testlibrary.OSInfo; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ActionListenerCalledTwiceTest { - static String menuItems[] = { "Item1", "Item2", "Item3", "Item4", "Item5", "Item6" }; + + static String menuItems[] = {"Item1", "Item2", "Item3", "Item4", "Item5", "Item6"}; static KeyStroke keyStrokes[] = { KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.META_MASK), KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), @@ -46,8 +46,10 @@ public class ActionListenerCalledTwiceTest { KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK), KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.META_MASK) }; - + static JMenu menu; + static JFrame frame; static volatile int listenerCallCounter = 0; + public static void main(String[] args) throws Exception { if (OSInfo.getOSType() != OSInfo.OSType.MACOSX) { System.out.println("This test is for MacOS only. Automatically passed on other platforms."); @@ -82,33 +84,38 @@ public class ActionListenerCalledTwiceTest { robot.waitForIdle(); if (listenerCallCounter != 1) { - throw new Exception("Test failed: ActionListener for " + menuItems[i] + - " called " + listenerCallCounter + " times instead of 1!"); + throw new Exception("Test failed: ActionListener for " + menuItems[i] + + " called " + listenerCallCounter + " times instead of 1!"); } listenerCallCounter = 0; } + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.dispose(); + } + }); } private static void createAndShowGUI() { - JMenu menu = new JMenu("Menu"); + menu = new JMenu("Menu"); for (int i = 0; i < menuItems.length; ++i) { JMenuItem newItem = new JMenuItem(menuItems[i]); newItem.setAccelerator(keyStrokes[i]); newItem.addActionListener( - new ActionListener(){ - public void actionPerformed(ActionEvent e) { - listenerCallCounter++; - } + new ActionListener() { + public void actionPerformed(ActionEvent e) { + listenerCallCounter++; } + } ); menu.add(newItem); } JMenuBar bar = new JMenuBar(); bar.add(menu); - JFrame frame = new JFrame("Test"); + frame = new JFrame("Test"); frame.setJMenuBar(bar); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); diff --git a/jdk/test/javax/swing/JSpinner/6421058/bug6421058.java b/jdk/test/javax/swing/JSpinner/6421058/bug6421058.java new file mode 100644 index 00000000000..d67762b21d7 --- /dev/null +++ b/jdk/test/javax/swing/JSpinner/6421058/bug6421058.java @@ -0,0 +1,94 @@ +/* + * 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 6421058 + * @summary Verify font of the text field is changed to the font of + * JSpinner if the font of text field was NOT set by the user + * @run main bug6421058 + */ + +import java.awt.Font; +import javax.swing.JFrame; +import javax.swing.JSpinner; +import javax.swing.JSpinner.DefaultEditor; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.UIResource; +import static javax.swing.UIManager.getInstalledLookAndFeels; + +public class bug6421058 implements Runnable { + + public static void main(final String[] args) throws Exception { + for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + SwingUtilities.invokeAndWait(new bug6421058()); + } + } + + @Override + public void run() { + final JFrame mainFrame = new JFrame(); + try { + testDefaultFont(mainFrame); + } finally { + mainFrame.dispose(); + } + } + + private static void testDefaultFont(final JFrame frame) { + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JSpinner spinner = new JSpinner(); + frame.add(spinner); + frame.setSize(300, 100); + frame.setVisible(true); + + final DefaultEditor editor = (DefaultEditor) spinner.getEditor(); + final Font editorFont = editor.getTextField().getFont(); + + /* + * Validate that the font of the text field is changed to the + * font of JSpinner if the font of text field was not set by the + * user. + */ + + if (!(editorFont instanceof UIResource)) { + throw new RuntimeException("Font must be UIResource"); + } + if (!editorFont.equals(spinner.getFont())) { + throw new RuntimeException("Wrong FONT"); + } + } + + private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + UnsupportedLookAndFeelException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK.java b/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK.java new file mode 100644 index 00000000000..c1b7214e406 --- /dev/null +++ b/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK.java @@ -0,0 +1,71 @@ +/* + * 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 + @summary Tests that GTK LaF is supported on solaris + regardless of jdk.gtk.version flag values. + @bug 8156121 + @requires (os.name == "linux" | os.name == "solaris") + @run main/othervm -Djdk.gtk.version=2 DemandGTK + @run main/othervm -Djdk.gtk.version=3 DemandGTK +*/ + +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.SwingUtilities; +import java.awt.Robot; + +public class DemandGTK { + + static JFrame frame; + public static void createAndShow() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch(Exception cnf) { + cnf.printStackTrace(); + throw new RuntimeException("GTK LaF must be supported"); + } + frame = new JFrame("JFrame"); + frame.setSize(200, 200); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(DemandGTK::createAndShow); + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait( () -> { + frame.setVisible(false); + frame.dispose(); + }); + + } +} + diff --git a/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK2.sh b/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK2.sh new file mode 100644 index 00000000000..93de97904fd --- /dev/null +++ b/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK2.sh @@ -0,0 +1,89 @@ +#!/bin/ksh -p + +# +# 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 +# @summary Try to force GTK2. We must bail out to GTK3 (if any) if no 2 available. +# +# @compile ProvokeGTK.java +# @requires os.family == "linux" +# @run shell/timeout=400 DemandGTK2.sh + +# +# Note that we depend on +# strace in the PATH +# /sbin/ldconfig (which may be not in PATH) +# It is true for OEL 7 and Ubuntu 14, 16 +# but may fail in future. Save tomorrow for tomorrow. +# +# Read DemandGTK2.txt how to prepare GTK2-less machine. +# + +which strace +if [ $? -ne 0 ] +then + echo "Please provide strace: \"which strace\" failed." + exit 1 +fi + +HAVE_2=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-x11-2 | wc -l` +HAVE_3=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-3.so | wc -l` + + +if [ "${HAVE_2}" = "0" ] +then + + if [ "${HAVE_3}" = "0" ] + then + echo "Neither GTK2 nor GTK3 found: system misconfiguration. Exit." + exit 1 + fi + echo "No GTK 2 library found: we should bail out to 3" + strace -o strace.log -fe open ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=2 ProvokeGTK + EXECRES=$? + grep 'libgtk-3.*=\ *[0-9]*$' strace.log > logg +else + echo "There is GTK 2 library: we should use it" + strace -o strace.log -fe open ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=2 ProvokeGTK + EXECRES=$? + grep 'libgtk-x11.*=\ *[0-9]*$' strace.log > logg +fi + +if [ ${EXECRES} -ne 0 ] +then + echo "java execution failed for unknown reason, see logs" + exit 2 +fi + +cat logg +if [ -s logg ] +then + echo "Success." + exit 0 +else + echo "Failed. Examine logs." + exit 3 +fi + + diff --git a/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK2.txt b/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK2.txt new file mode 100644 index 00000000000..7313e3ee4a7 --- /dev/null +++ b/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK2.txt @@ -0,0 +1,36 @@ +How to prepare an Ubuntu machine for GTK-2-less test run. + +The test DemandGTK2.sh should work well without GTK-2 switching to version 3 +if there's no GTK-2 library available. +At the moment, it's not easy to find a system with GTK-3 and without GTK-2: +many programs still depend on version 2. +We can, however, rename GTK-2 library for a single test run and then restore +it back. + +(1) Find GTK2 library: run + /sbin/ldconfig -v 2>/dev/null | grep libgtk-x11-2 + +It will output one or two lines like +libgtk-x11-2.0.so.0 -> libgtk-x11-2.0.so.0.2400.23 +Search for the target of that symlink for instance with locate: +locate libgtk-x11-2.0.so.0.2400.23 +Finally, you'll find the libraries. On my current machine they are +/usr/lib/i386-linux-gnu/libgtk-x11-2.0.so.0.2400.23 +/usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 + +I'm running 64-bit JDK and need to tamper with x86_64 copy only. + +(2) Find running programs depending on this library. They probably would crash +if you rename it. Stop them for this test run. +That said, I'm afraid it would be impossible to do on a system older than Ubuntu 16.04. +On my Ubuntu 16.04 I have only hud-service using this library, and that's OK, it will restart +after a crash, if any. +To find these programs, run +lsof /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 + +(3) Now, +sudo mv /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 /usr/lib/x86_64-linux-gnu/bak.libgtk-x11-2.0.so.0.2400.23 +jtreg DemandGTK2.sh +sudo mv /usr/lib/x86_64-linux-gnu/bak.libgtk-x11-2.0.so.0.2400.23 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 + +Needless to say, you should substitute your own library path and however you run jtreg. diff --git a/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK3.sh b/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK3.sh new file mode 100644 index 00000000000..1a9038a4bef --- /dev/null +++ b/jdk/test/javax/swing/LookAndFeel/8145547/DemandGTK3.sh @@ -0,0 +1,81 @@ +#!/bin/ksh -p + +# +# 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 +# @summary Try to force GTK3. We must bail out to GTK2 if no 3 available. +# +# @compile ProvokeGTK.java +# @requires os.family == "linux" +# @run shell/timeout=400 DemandGTK3.sh + +# +# Note that we depend on +# strace in the PATH +# /sbin/ldconfig (which may be is not in PATH) +# It is true for OEL 7 and Ubuntu 14, 16 +# but may fail in future. Save tomorrow for tomorrow. +# + +which strace +if [ $? -ne 0 ] +then + echo "Please provide strace: \"which strace\" failed." + exit 1 +fi + +HAVE_3=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-3.so | wc -l` + + +if [ "${HAVE_3}" = "0" ] +then + + echo "No GTK 3 library found: we should bail out to 2" + strace -o strace.log -fe open ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=3 ProvokeGTK + EXECRES=$? + grep 'libgtk-x11.*=\ *[0-9]*$' strace.log > logg +else + echo "There is GTK 3 library: we should use it" + strace -o strace.log -fe open ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=3 ProvokeGTK + EXECRES=$? + grep 'libgtk-3.*=\ *[0-9]*$' strace.log > logg +fi + +if [ ${EXECRES} -ne 0 ] +then + echo "java execution failed for unknown reason, see logs" + exit 2 +fi + +cat logg +if [ -s logg ] +then + echo "Success." + exit 0 +else + echo "Failed. Examine logs." + exit 3 +fi + diff --git a/jdk/test/javax/swing/LookAndFeel/8145547/ProvokeGTK.java b/jdk/test/javax/swing/LookAndFeel/8145547/ProvokeGTK.java new file mode 100644 index 00000000000..485ea05beaa --- /dev/null +++ b/jdk/test/javax/swing/LookAndFeel/8145547/ProvokeGTK.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.SwingUtilities; + +public class ProvokeGTK { + + static JFrame frame; + public static void createAndShow() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch(Exception cnf) { + cnf.printStackTrace(); + } + frame = new JFrame("JFrame"); + frame.setSize(200, 200); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(ProvokeGTK::createAndShow); + Thread.sleep(1000); + SwingUtilities.invokeAndWait( () -> { + frame.setVisible(false); + frame.dispose(); + }); + + } +} + diff --git a/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java b/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java index 4a556efce13..9cc57cfcdae 100644 --- a/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java +++ b/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,47 +23,107 @@ /* * @test - * @bug 8032884 + * @bug 8032884 8072579 * @summary Globalbindings optionalProperty="primitive" does not work when minOccurs=0 - * @run shell compile-schema.sh - * @compile -addmods java.xml.bind XjcOptionalPropertyTest.java - * @run main/othervm XjcOptionalPropertyTest + * @library /lib/testlibrary + * @modules java.xml.bind + * @run testng/othervm XjcOptionalPropertyTest */ import java.io.IOException; import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import java.util.Arrays; +import jdk.testlibrary.JDKToolLauncher; +import org.testng.Assert; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; public class XjcOptionalPropertyTest { - public static void main(String[] args) throws IOException { - - generated.Foo foo = new generated.Foo(); - log("foo = " + foo); + @Test + public void optionalPropertyTest() throws Exception { + runXjc(); + compileXjcGeneratedClasses(); + URLClassLoader testClassLoader; + testClassLoader = URLClassLoader.newInstance(new URL[]{testWorkDirUrl}); + Class fooClass = testClassLoader.loadClass(CLASS_TO_TEST); + Object foo = fooClass.newInstance(); Method[] methods = foo.getClass().getMethods(); - log("Found [" + methods.length + "] methods"); + System.out.println("Found [" + methods.length + "] methods"); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals("setFoo")) { - log("Checking method [" + method.getName() + "]"); + System.out.println("Checking method [" + method.getName() + "]"); Class[] parameterTypes = method.getParameterTypes(); - if (parameterTypes.length != 1) - fail("more than 1 parameter"); - if (!parameterTypes[0].isPrimitive()) { - fail("Found [" + parameterTypes[0].getName() + "], but expected primitive!"); - } + Assert.assertEquals(parameterTypes.length, 1); + Assert.assertTrue(parameterTypes[0].isPrimitive()); break; } } - log("TEST PASSED."); - } - private static void fail(String message) { - throw new RuntimeException(message); + @BeforeTest + public void setUp() throws IOException { + // Create test directory inside scratch + testWorkDir = Paths.get(System.getProperty("user.dir", ".")); + // Save its URL + testWorkDirUrl = testWorkDir.toUri().toURL(); + // Get test source directory path + testSrcDir = Paths.get(System.getProperty("test.src", ".")); + // Get path of xjc result folder + xjcResultDir = testWorkDir.resolve(TEST_PACKAGE); + // Copy schema document file to scratch directory + Files.copy(testSrcDir.resolve(XSD_FILENAME), testWorkDir.resolve(XSD_FILENAME), REPLACE_EXISTING); } - private static void log(String msg) { - System.out.println(msg); + // Compile schema file into java classes definitions + void runXjc() throws Exception { + // Prepare process builder to run schemagen tool and save its output + JDKToolLauncher xjcLauncher = JDKToolLauncher.createUsingTestJDK("xjc"); + xjcLauncher.addToolArg(XSD_FILENAME); + System.out.println("Executing xjc command: " + Arrays.asList(xjcLauncher.getCommand())); + ProcessBuilder pb = new ProcessBuilder(xjcLauncher.getCommand()); + // Set xjc work directory with the input java file + pb.directory(testWorkDir.toFile()); + pb.inheritIO(); + Process p = pb.start(); + p.waitFor(); + p.destroy(); } + // Compile java classes with javac tool + void compileXjcGeneratedClasses() throws Exception { + JDKToolLauncher javacLauncher = JDKToolLauncher.createUsingTestJDK("javac"); + javacLauncher.addToolArg("-addmods"); + javacLauncher.addToolArg("java.xml.bind"); + javacLauncher.addToolArg(xjcResultDir.resolve("Foo.java").toString()); + System.out.println("Compiling xjc generated class: " + Arrays.asList(javacLauncher.getCommand())); + ProcessBuilder pb = new ProcessBuilder(javacLauncher.getCommand()); + pb.inheritIO(); + pb.directory(testWorkDir.toFile()); + Process p = pb.start(); + p.waitFor(); + p.destroy(); + } + + // Test schema filename + static final String XSD_FILENAME = "optional-property-schema.xsd"; + // Test package with generated class + static final String TEST_PACKAGE = "anamespace"; + // Name of generated java class + static final String CLASS_TO_TEST = TEST_PACKAGE+".Foo"; + // Test working directory + Path testWorkDir; + // Test working directory URL + URL testWorkDirUrl; + // Directory with test src + Path testSrcDir; + // Directory with java files generated by xjc + Path xjcResultDir; } diff --git a/jdk/test/javax/xml/bind/xjc/8145039/JaxbMarshallTest.java b/jdk/test/javax/xml/bind/xjc/8145039/JaxbMarshallTest.java index 37b817d0b4d..cc1be256343 100644 --- a/jdk/test/javax/xml/bind/xjc/8145039/JaxbMarshallTest.java +++ b/jdk/test/javax/xml/bind/xjc/8145039/JaxbMarshallTest.java @@ -23,10 +23,10 @@ /* * @test - * @bug 8145039 + * @bug 8145039 8157096 * @summary Check that marshalling of xjc generated class doesn't throw * ClassCast exception. - * @modules javax.xml.bind + * @modules java.xml.bind * @library /lib/testlibrary * @run testng/othervm JaxbMarshallTest */ @@ -127,6 +127,8 @@ public class JaxbMarshallTest { // Compile java classes with javac tool void compileXjcGeneratedClasses() throws Exception { JDKToolLauncher javacLauncher = JDKToolLauncher.createUsingTestJDK("javac"); + javacLauncher.addToolArg("-addmods"); + javacLauncher.addToolArg("java.xml.bind"); javacLauncher.addToolArg(xjcResultDir.resolve("ObjectFactory.java").toString()); javacLauncher.addToolArg(xjcResultDir.resolve("TypesLongList.java").toString()); javacLauncher.addToolArg(xjcResultDir.resolve("package-info.java").toString()); diff --git a/jdk/test/javax/xml/jaxp/TEST.properties b/jdk/test/javax/xml/jaxp/TEST.properties new file mode 100644 index 00000000000..fbf9f77ec10 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/TEST.properties @@ -0,0 +1 @@ +modules = java.xml diff --git a/jdk/test/jdk/internal/jimage/JImageOpenTest.java b/jdk/test/jdk/internal/jimage/JImageOpenTest.java new file mode 100644 index 00000000000..06c19937a41 --- /dev/null +++ b/jdk/test/jdk/internal/jimage/JImageOpenTest.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +import java.lang.reflect.Layer; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/* + * jimage shared open testing. + * @test + * @summary Test to see if thread interrupt handling interferes with other threads. + * @build JImageOpenTest.java + * @run main/othervm -Djdk.image.map.all=false JImageOpenTest + */ +public class JImageOpenTest { + private static final int NTHREADS = 10; + + public static void main(String[] args) throws Exception { + + final FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); + final Path root = fs.getPath("/modules"); + + final List names = Files.walk(root) + .filter(p -> p.getNameCount() > 2) + .filter(p -> Layer.boot().findModule(p.getName(1).toString()).isPresent()) + .map(p -> p.subpath(2, p.getNameCount())) + .map(p -> p.toString()) + .filter(s -> s.endsWith(".class") && !s.endsWith("module-info.class")) + .collect(Collectors.toList()); + + Runnable r = new Runnable() { + @Override + public void run() { + names.forEach(name -> { + String cn = name.substring(0, name.length() - 6).replace('/', '.'); + try { + Class.forName(cn, false, ClassLoader.getSystemClassLoader()); + } catch (Exception ex) { + System.err.println(Thread.currentThread() + " " + ex.getClass()); + } + }); + } + }; + + Thread[] threads = new Thread[NTHREADS]; + + for (int i = 0; i < NTHREADS; i++) { + Thread thread = new Thread(r); + threads[i] = thread; + thread.start(); + } + + Thread.sleep(1); + + for (int i = 0; i < NTHREADS; i++) { + Thread thread = threads[i]; + + if (thread.isAlive()) { + thread.interrupt(); + break; + } + } + + for (int i = 0; i < NTHREADS; i++) { + Thread thread = threads[i]; + thread.join(); + } + } +} diff --git a/jdk/test/jdk/internal/jline/extra/HistoryTest.java b/jdk/test/jdk/internal/jline/extra/HistoryTest.java new file mode 100644 index 00000000000..f8d3084b767 --- /dev/null +++ b/jdk/test/jdk/internal/jline/extra/HistoryTest.java @@ -0,0 +1,177 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 + * @summary Test Completion + * @modules jdk.internal.le/jdk.internal.jline + * jdk.internal.le/jdk.internal.jline.console + * jdk.internal.le/jdk.internal.jline.console.history + * jdk.internal.le/jdk.internal.jline.extra + * @build HistoryTest + * @run testng HistoryTest + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; + +import jdk.internal.jline.UnsupportedTerminal; +import jdk.internal.jline.console.ConsoleReader; +import jdk.internal.jline.console.history.MemoryHistory; +import jdk.internal.jline.extra.EditingHistory; + +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +@Test +public class HistoryTest { + + public void testHistory() throws IOException { + ConsoleReader in = new ConsoleReader(new ByteArrayInputStream(new byte[0]), new ByteArrayOutputStream(), new UnsupportedTerminal()); + AtomicBoolean complete = new AtomicBoolean(); + EditingHistory history = new EditingHistory(in, Collections.emptyList()) { + @Override + protected boolean isComplete(CharSequence input) { + return complete.get(); + } + }; + complete.set(false); history.add("void test() {"); + complete.set(false); history.add(" System.err.println(1);"); + complete.set(true); history.add("}"); + complete.set(true); history.add("/exit"); + + previousAndAssert(history, "/exit"); + + history.previous(); history.previous(); history.previous(); + + complete.set(false); history.add("void test() { /*changed*/"); + + complete.set(true); + previousAndAssert(history, "}"); + previousAndAssert(history, " System.err.println(1);"); + previousAndAssert(history, "void test() {"); + + assertFalse(history.previous()); + + nextAndAssert(history, " System.err.println(1);"); + nextAndAssert(history, "}"); + nextAndAssert(history, ""); + + complete.set(false); history.add(" System.err.println(2);"); + complete.set(true); history.add("} /*changed*/"); + + assertEquals(history.size(), 7); + + Collection persistentHistory = history.save(); + + history = new EditingHistory(in, persistentHistory) { + @Override + protected boolean isComplete(CharSequence input) { + return complete.get(); + } + }; + + previousSnippetAndAssert(history, "void test() { /*changed*/"); + previousSnippetAndAssert(history, "/exit"); + previousSnippetAndAssert(history, "void test() {"); + + assertFalse(history.previousSnippet()); + + nextSnippetAndAssert(history, "/exit"); + nextSnippetAndAssert(history, "void test() { /*changed*/"); + nextSnippetAndAssert(history, ""); + + assertFalse(history.nextSnippet()); + + complete.set(false); history.add("{"); + complete.set(true); history.add("}"); + + persistentHistory = history.save(); + + history = new EditingHistory(in, persistentHistory) { + @Override + protected boolean isComplete(CharSequence input) { + return complete.get(); + } + }; + + previousSnippetAndAssert(history, "{"); + previousSnippetAndAssert(history, "void test() { /*changed*/"); + previousSnippetAndAssert(history, "/exit"); + previousSnippetAndAssert(history, "void test() {"); + + while (history.next()); + + complete.set(true); history.add("/*current1*/"); + complete.set(true); history.add("/*current2*/"); + complete.set(true); history.add("/*current3*/"); + + assertEquals(history.currentSessionEntries(), Arrays.asList("/*current1*/", "/*current2*/", "/*current3*/")); + + history.remove(0); + + assertEquals(history.currentSessionEntries(), Arrays.asList("/*current1*/", "/*current2*/", "/*current3*/")); + + while (history.size() > 2) + history.remove(0); + + assertEquals(history.currentSessionEntries(), Arrays.asList("/*current2*/", "/*current3*/")); + + for (int i = 0; i < MemoryHistory.DEFAULT_MAX_SIZE * 2; i++) { + complete.set(true); history.add("/exit"); + } + + complete.set(false); history.add("void test() { /*after full*/"); + complete.set(false); history.add(" System.err.println(1);"); + complete.set(true); history.add("}"); + + previousSnippetAndAssert(history, "void test() { /*after full*/"); + } + + private void previousAndAssert(EditingHistory history, String expected) { + assertTrue(history.previous()); + assertEquals(history.current().toString(), expected); + } + + private void nextAndAssert(EditingHistory history, String expected) { + assertTrue(history.next()); + assertEquals(history.current().toString(), expected); + } + + private void previousSnippetAndAssert(EditingHistory history, String expected) { + assertTrue(history.previousSnippet()); + assertEquals(history.current().toString(), expected); + } + + private void nextSnippetAndAssert(EditingHistory history, String expected) { + assertTrue(history.nextSnippet()); + assertEquals(history.current().toString(), expected); + } + +} diff --git a/jdk/test/jdk/internal/jrtfs/Basic.java b/jdk/test/jdk/internal/jrtfs/Basic.java index 0af30c5e2f7..9c29d8c1428 100644 --- a/jdk/test/jdk/internal/jrtfs/Basic.java +++ b/jdk/test/jdk/internal/jrtfs/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -65,15 +65,31 @@ public class Basic { private FileSystem theFileSystem; private FileSystem fs; + private boolean isExplodedBuild = false; @BeforeClass public void setup() { + theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/")); + Path javaHomeDir = Paths.get(System.getProperty("java.home")); + Path jrtJarPath = javaHomeDir.resolve("jrt-fs.jar"); + Path modulesPath = javaHomeDir.resolve("lib/modules"); + isExplodedBuild = !Files.exists(jrtJarPath) + && !Files.exists(modulesPath); + if (Files.notExists(jrtJarPath) + && Files.notExists(modulesPath)) { + System.out.printf("Following files not exist: %s, %s", + jrtJarPath.toString(), modulesPath.toString()); + System.out.println(); + System.out.println("It is most probably an exploded build." + + " Skip non-default FileSystem testing."); + return; + } + + Map env = new HashMap<>(); + // set java.home property to be underlying java.home + // so that jrt-fs.jar loading is exercised. + env.put("java.home", System.getProperty("java.home")); try { - theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/")); - Map env = new HashMap<>(); - // set java.home property to be underlying java.home - // so that jrt-fs.jar loading is exercised. - env.put("java.home", System.getProperty("java.home")); fs = FileSystems.newFileSystem(URI.create("jrt:/"), env); } catch (IOException ioExp) { throw new RuntimeException(ioExp); @@ -131,6 +147,12 @@ public class Basic { @Test public void testNewFileSystemWithJavaHome() throws Exception { + if (isExplodedBuild) { + System.out.println("Skip testNewFileSystemWithJavaHome" + + " since this is an exploded build"); + return; + } + Map env = new HashMap<>(); // set java.home property to be underlying java.home // so that jrt-fs.jar loading is exercised. @@ -154,6 +176,11 @@ public class Basic { @Test(dataProvider = "knownClassFiles") public void testKnownClassFiles(String path, boolean theDefault) throws Exception { + if (isExplodedBuild && !theDefault) { + System.out.println("Skip testKnownClassFiles with non-default FileSystem"); + return; + } + FileSystem fs = selectFileSystem(theDefault); Path classFile = fs.getPath(path); @@ -201,6 +228,11 @@ public class Basic { @Test(dataProvider = "knownDirectories") public void testKnownDirectories(String path, boolean theDefault) throws Exception { + if (isExplodedBuild && !theDefault) { + System.out.println("Skip testKnownDirectories with non-default FileSystem"); + return; + } + FileSystem fs = selectFileSystem(theDefault); Path dir = fs.getPath(path); @@ -684,3 +716,4 @@ public class Basic { assertEquals(dirPrefixOkayCount, childCount); } } + diff --git a/jdk/test/jdk/modules/scenarios/container/src/container/container/Main.java b/jdk/test/jdk/modules/scenarios/container/src/container/container/Main.java index 4c86c6e549c..67f2416187f 100644 --- a/jdk/test/jdk/modules/scenarios/container/src/container/container/Main.java +++ b/jdk/test/jdk/modules/scenarios/container/src/container/container/Main.java @@ -72,7 +72,7 @@ public class Main { Configuration cf = Layer.boot().configuration() .resolveRequiresAndUses(finder, - ModuleFinder.empty(), + ModuleFinder.of(), Set.of(appModuleName)); System.out.println("Resolved"); diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/OverlappingPackagesTest.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/OverlappingPackagesTest.java index 826e282326a..529996e8e7d 100644 --- a/jdk/test/jdk/modules/scenarios/overlappingpackages/OverlappingPackagesTest.java +++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/OverlappingPackagesTest.java @@ -66,13 +66,7 @@ public class OverlappingPackagesTest { } Path srcMisc = SRC_DIR.resolve("misc"); Path modsMisc = MODS_DIR.resolve("misc"); - assertTrue(CompilerUtils.compile(srcMisc.resolve("sun") - .resolve("misc") - .resolve("Unsafe.java"), - modsMisc, - "-Xmodule:java.base")); - assertTrue(CompilerUtils.compile(srcMisc.resolve("module-info.java"), - modsMisc)); + assertTrue(CompilerUtils.compile(srcMisc, modsMisc)); } /** @@ -92,7 +86,7 @@ public class OverlappingPackagesTest { /** * Run the test with "-addmods misc", the misc module has package - * sun.misc and so should overlap with the base module. + * jdk.internal.misc and so should overlap with the base module. */ public void testOverlapWithBaseModule() throws Exception { int exitValue diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/sun/misc/Unsafe.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/jdk/internal/misc/Unsafe.java similarity index 97% rename from jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/sun/misc/Unsafe.java rename to jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/jdk/internal/misc/Unsafe.java index 135652ea9b7..0b4aa917ccd 100644 --- a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/sun/misc/Unsafe.java +++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/jdk/internal/misc/Unsafe.java @@ -21,7 +21,7 @@ * questions. */ -package sun.misc; +package jdk.internal.misc; public class Unsafe { private Unsafe() { } diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/module-info.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/module-info.java index 65cc15d749b..d4f3bd98b69 100644 --- a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/module-info.java +++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/module-info.java @@ -22,6 +22,6 @@ */ module misc { - exports sun.misc; + exports jdk.internal.misc; } diff --git a/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java index ca02ad931d6..f882e88e30a 100644 --- a/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java +++ b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java @@ -25,6 +25,7 @@ * @test * @bug 8765432 * @summary Basic test for SocketFlow API + * @modules jdk.net * @run testng SocketFlowBasic */ diff --git a/jdk/test/jdk/net/Sockets/SupportedOptions.java b/jdk/test/jdk/net/Sockets/SupportedOptions.java index 0ef21204629..caf4d025d67 100644 --- a/jdk/test/jdk/net/Sockets/SupportedOptions.java +++ b/jdk/test/jdk/net/Sockets/SupportedOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /* * @test * @bug 8062744 + * @modules jdk.net * @run main SupportedOptions */ diff --git a/jdk/test/jdk/net/Sockets/Test.java b/jdk/test/jdk/net/Sockets/Test.java index 8bb03c54919..bd76fff4e67 100644 --- a/jdk/test/jdk/net/Sockets/Test.java +++ b/jdk/test/jdk/net/Sockets/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,24 +25,35 @@ * @test * @bug 8032808 8044773 * @modules jdk.net + * @library /lib/testlibrary + * @build jdk.testlibrary.* * @run main/othervm -Xcheck:jni Test success * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail * @run main/othervm/policy=policy.success -Xcheck:jni Test success */ -import java.net.*; +import jdk.net.ExtendedSocketOptions; +import jdk.net.SocketFlow; +import jdk.net.Sockets; +import jdk.testlibrary.OSInfo; + import java.io.IOException; -import java.nio.channels.*; -import java.util.concurrent.*; -import java.util.Set; -import jdk.net.*; +import java.net.*; +import java.nio.channels.AsynchronousSocketChannel; +import java.nio.channels.DatagramChannel; +import java.nio.channels.SocketChannel; +import java.util.concurrent.Future; + import static java.lang.System.out; +import static jdk.net.ExtendedSocketOptions.SO_FLOW_SLA; public class Test { interface Runner { void run() throws Exception; } static boolean expectSuccess; + private static final boolean expectSupport = checkExpectedOptionSupport(); + private static final double solarisVersionToCheck = 11.2; public static void main(String[] args) throws Exception { @@ -54,9 +65,8 @@ public class Test { expectSuccess = args[0].equals("success"); // Main thing is to check for JNI problems - // Doesn't matter if current system does not support the option - // and currently setting the option with the loopback interface - // doesn't work either + // Doesn't matter if currently setting the option with the loopback + // interface doesn't work boolean sm = System.getSecurityManager() != null; out.println("Security Manager enabled: " + sm); @@ -75,56 +85,70 @@ public class Test { final int udp_port = dg.getLocalPort(); - // If option not available, end test - Set> options = dg.supportedOptions(); - if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) { - System.out.println("SO_FLOW_SLA not supported"); - return; - } - final Socket s = new Socket("127.0.0.1", tcp_port); final SocketChannel sc = SocketChannel.open(); sc.connect(new InetSocketAddress("127.0.0.1", tcp_port)); doTest("Sockets.setOption Socket", () -> { out.println(flowIn); - Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + if (s.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } + Sockets.setOption(s, SO_FLOW_SLA, flowIn); out.println(flowIn); }); - doTest("Sockets.getOption Socket",() -> { - Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA); + + doTest("Sockets.getOption Socket", () -> { + Sockets.getOption(s, SO_FLOW_SLA); out.println(flowIn); }); - doTest("Sockets.setOption SocketChannel",() -> - sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn) + + doTest("Sockets.setOption SocketChannel", () -> { + if (sc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } + sc.setOption(SO_FLOW_SLA, flowIn); + }); + doTest("Sockets.getOption SocketChannel", () -> + sc.getOption(SO_FLOW_SLA) ); - doTest("Sockets.getOption SocketChannel",() -> - sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA) - ); - doTest("Sockets.setOption DatagramSocket",() -> { + doTest("Sockets.setOption DatagramSocket", () -> { try (DatagramSocket dg1 = new DatagramSocket(0)) { + if (dg1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } + dg1.connect(loop, udp_port); - Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + Sockets.setOption(dg1, SO_FLOW_SLA, flowIn); } }); doTest("Sockets.setOption DatagramSocket 2", () -> { try (DatagramChannel dg2 = DatagramChannel.open()) { + if (dg2.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } dg2.bind(new InetSocketAddress(loop, 0)); dg2.connect(new InetSocketAddress(loop, udp_port)); - dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + dg2.setOption(SO_FLOW_SLA, flowIn); } }); doTest("Sockets.setOption MulticastSocket", () -> { try (MulticastSocket mc1 = new MulticastSocket(0)) { + if (mc1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } mc1.connect(loop, udp_port); - Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + Sockets.setOption(mc1, SO_FLOW_SLA, flowIn); } }); doTest("Sockets.setOption AsynchronousSocketChannel", () -> { try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) { + if (asc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) { + throw new RuntimeException("Unexpected supportedOptions()"); + } Future f = asc.connect(loopad); f.get(); - asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + asc.setOption(SO_FLOW_SLA, flowIn); } }); } @@ -144,14 +168,43 @@ public class Test { throw new RuntimeException("Unexpected SecurityException", e); } else { out.println("Caught expected: " + e); + return; } } catch (UnsupportedOperationException e) { - System.out.println(e); + if (expectSupport) { + throw new RuntimeException("Test failed: " + + "unexpected UnsupportedOperationException"); + } + out.println("UnsupportedOperationException as expected"); + return; } catch (IOException e) { // Probably a permission error, but we're not // going to check unless a specific permission exception // is defined. System.out.println(e); } + if (!expectSupport) { + throw new RuntimeException("Test failed: " + + "UnsupportedOperationException was not thrown"); + } } + + private static boolean checkExpectedOptionSupport() { + if (OSInfo.getOSType().equals(OSInfo.OSType.SOLARIS)) { + double solarisVersion = OSInfo.getSolarisVersion(); + if (solarisVersion >= solarisVersionToCheck) { + System.out.println("This Solaris version (" + solarisVersion + + ") should support SO_FLOW_SLA option"); + return true; + } else { + System.out.println("This Solaris version (" + solarisVersion + + ") should not support SO_FLOW_SLA option"); + } + } else { + System.out.println("Not Solaris, SO_FLOW_SLA should not be " + + "supported"); + } + return false; + } + } diff --git a/jdk/test/jdk/net/Sockets/policy.fail b/jdk/test/jdk/net/Sockets/policy.fail index 29d1215e708..1c9b57d90d7 100644 --- a/jdk/test/jdk/net/Sockets/policy.fail +++ b/jdk/test/jdk/net/Sockets/policy.fail @@ -1,4 +1,8 @@ grant { + permission java.util.PropertyPermission "os.name", "read"; + permission java.io.FilePermission "<>", "execute"; + permission java.util.PropertyPermission "line.separator", "read"; + permission java.io.FilePermission "/etc/release", "read"; permission java.net.SocketPermission "127.0.0.1", "connect,accept" ; permission java.net.SocketPermission "localhost", "listen" ; }; diff --git a/jdk/test/jdk/net/Sockets/policy.success b/jdk/test/jdk/net/Sockets/policy.success index 6f99151a38f..653b755b338 100644 --- a/jdk/test/jdk/net/Sockets/policy.success +++ b/jdk/test/jdk/net/Sockets/policy.success @@ -1,4 +1,8 @@ grant { + permission java.util.PropertyPermission "os.name", "read"; + permission java.io.FilePermission "<>", "execute"; + permission java.util.PropertyPermission "line.separator", "read"; + permission java.io.FilePermission "/etc/release", "read"; permission java.net.SocketPermission "127.0.0.1", "connect,accept" ; permission java.net.SocketPermission "localhost", "listen" ; permission jdk.net.NetworkPermission "setOption.SO_FLOW_SLA"; diff --git a/jdk/test/jdk/nio/zipfs/Basic.java b/jdk/test/jdk/nio/zipfs/Basic.java index f29e4bd123e..60ac2e7e0ad 100644 --- a/jdk/test/jdk/nio/zipfs/Basic.java +++ b/jdk/test/jdk/nio/zipfs/Basic.java @@ -31,6 +31,7 @@ import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.ProviderMismatchException; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; @@ -39,14 +40,15 @@ import java.net.URI; import java.io.IOException; import java.util.Collections; import java.util.Map; - +import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; /** * @test - * @bug 8038500 8040059 8150366 8150496 + * @bug 8038500 8040059 8150366 8150496 8147539 * @summary Basic test for zip provider * * @run main Basic * @run main/othervm/java.security.policy=test.policy Basic + * @modules jdk.zipfs */ public class Basic { @@ -89,7 +91,7 @@ public class Basic { found = false; try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("/"))) { for (Path entry: stream) { - found = entry.toString().equals("/META-INF/"); + found = entry.toString().equals("/META-INF"); if (found) break; } } @@ -117,6 +119,13 @@ public class Basic { if (!store.supportsFileAttributeView("basic")) throw new RuntimeException("BasicFileAttributeView should be supported"); + // Test: watch register should throw PME + try { + fs.getPath("/") + .register(FileSystems.getDefault().newWatchService(), ENTRY_CREATE); + throw new RuntimeException("watch service is not supported"); + } catch (ProviderMismatchException x) { } + // Test: ClosedFileSystemException fs.close(); if (fs.isOpen()) diff --git a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java index 6f87dc68813..6e483c6e21a 100644 --- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java +++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,28 +23,31 @@ /* * @test - * @bug 8144355 + * @bug 8144355 8144062 * @summary Test aliasing additions to ZipFileSystem for multi-release jar files * @library /lib/testlibrary/java/util/jar * @build Compiler JarBuilder CreateMultiReleaseTestJars * @run testng MultiReleaseJarTest + * @modules java.compiler + * jdk.jartool + * jdk.zipfs */ import java.io.IOException; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.Runtime.Version; import java.net.URI; import java.nio.file.*; import java.util.HashMap; import java.util.Map; -import jdk.Version; import org.testng.Assert; import org.testng.annotations.*; public class MultiReleaseJarTest { - final private int MAJOR_VERSION = Version.current().major(); + final private int MAJOR_VERSION = Runtime.version().major(); final private String userdir = System.getProperty("user.dir","."); final private Map stringEnv = new HashMap<>(); diff --git a/jdk/test/jdk/nio/zipfs/PathOps.java b/jdk/test/jdk/nio/zipfs/PathOps.java index 8f428515cbc..1bd72f7bf9c 100644 --- a/jdk/test/jdk/nio/zipfs/PathOps.java +++ b/jdk/test/jdk/nio/zipfs/PathOps.java @@ -31,11 +31,12 @@ import java.nio.file.Path; /** * * @test - * @bug 8038500 8040059 + * @bug 8038500 8040059 8139956 8146754 * @summary Tests path operations for zip provider. * * @run main PathOps * @run main/othervm/java.security.policy=test.policy PathOps + * @modules jdk.zipfs */ public class PathOps { @@ -424,6 +425,11 @@ public class PathOps { test("/") .relativize("/a", "a") .relativize("/a/c", "a/c"); + // 8146754 + test("/tmp/path") + .relativize("/tmp/path/a.txt", "a.txt"); + test("/tmp/path/") + .relativize("/tmp/path/a.txt", "a.txt"); // normalize test("/") @@ -486,7 +492,16 @@ public class PathOps { // isSameFile test("/fileDoesNotExist") .isSameFile("/fileDoesNotExist"); - } + + // 8139956 + out.println("check getNameCount"); + int nc = fs.getPath("/").relativize(fs.getPath("/")).getNameCount(); + if (nc != 1) { + out.format("\tExpected: 1\n"); + out.format("\tActual: %d\n", nc); + throw new RuntimeException("getNameCount of empty path failed"); + } + } static void npes() { header("NullPointerException"); diff --git a/jdk/test/jdk/nio/zipfs/ZFSTests.java b/jdk/test/jdk/nio/zipfs/ZFSTests.java index 8febcf2730d..d9542601afe 100644 --- a/jdk/test/jdk/nio/zipfs/ZFSTests.java +++ b/jdk/test/jdk/nio/zipfs/ZFSTests.java @@ -22,11 +22,12 @@ */ /* @test - * @bug 7156873 8040059 8028480 8034773 + * @bug 7156873 8040059 8028480 8034773 8153248 * @summary ZipFileSystem regression tests * * @run main ZFSTests * @run main/othervm/java.security.policy=test.policy ZFSTests + * @modules jdk.zipfs */ @@ -42,7 +43,7 @@ public class ZFSTests { public static void main(String[] args) throws Throwable { test7156873(); - testOpenOptions(); + tests(); } static void test7156873() throws Throwable { @@ -61,7 +62,7 @@ public class ZFSTests { } } - static void testOpenOptions() throws Throwable { + static void tests() throws Throwable { Path path = Paths.get("file.zip"); try { URI uri = URI.create("jar:" + path.toUri()); @@ -95,6 +96,18 @@ public class ZFSTests { } catch (IllegalArgumentException x) { // expected x.printStackTrace(); } + + //8153248 + Path dir = fs.getPath("/dir"); + Path subdir = fs.getPath("/dir/subdir"); + Files.createDirectory(dir); + Files.createDirectory(subdir); + Files.list(dir) + .forEach( child -> { + System.out.println("child:" + child); + if (child.toString().endsWith("/")) + throw new RuntimeException("subdir names ends with /"); + }); } } finally { Files.deleteIfExists(path); diff --git a/jdk/test/jdk/nio/zipfs/ZipFSTester.java b/jdk/test/jdk/nio/zipfs/ZipFSTester.java index 58389250e43..683bcae00b6 100644 --- a/jdk/test/jdk/nio/zipfs/ZipFSTester.java +++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java @@ -74,6 +74,7 @@ import static java.nio.file.StandardCopyOption.*; * @summary Test Zip filesystem provider * @run main ZipFSTester * @run main/othervm/java.security.policy=test.policy ZipFSTester + * @modules jdk.zipfs */ public class ZipFSTester { diff --git a/jdk/test/lib/testlibrary/CompilerUtils.java b/jdk/test/lib/testlibrary/CompilerUtils.java index 91ca9181340..261c2c8f930 100644 --- a/jdk/test/lib/testlibrary/CompilerUtils.java +++ b/jdk/test/lib/testlibrary/CompilerUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,13 +50,21 @@ public final class CompilerUtils { * * @return true if the compilation is successful * - * @throws IOException if there is an I/O error scanning the source tree or - * creating the destination directory + * @throws IOException + * if there is an I/O error scanning the source tree or + * creating the destination directory + * @throws UnsupportedOperationException + * if there is no system java compiler */ public static boolean compile(Path source, Path destination, String ... options) throws IOException { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + // no compiler available + throw new UnsupportedOperationException("Unable to get system java compiler. " + + "Perhaps, jdk.compiler module is not available."); + } StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null); List sources diff --git a/jdk/test/lib/testlibrary/JarUtils.java b/jdk/test/lib/testlibrary/JarUtils.java index 94905ccffed..8f0e97321f4 100644 --- a/jdk/test/lib/testlibrary/JarUtils.java +++ b/jdk/test/lib/testlibrary/JarUtils.java @@ -35,6 +35,7 @@ import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -49,12 +50,12 @@ public final class JarUtils { /** * Creates a JAR file. * - * Equivalent to {@code jar cf -C

    file...} + * Equivalent to {@code jar cfm -C file...} * * The input files are resolved against the given directory. Any input * files that are directories are processed recursively. */ - public static void createJarFile(Path jarfile, Path dir, Path... file) + public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... file) throws IOException { // create the target directory @@ -73,14 +74,36 @@ public final class JarUtils { try (OutputStream out = Files.newOutputStream(jarfile); JarOutputStream jos = new JarOutputStream(out)) { + if (man != null) { + JarEntry je = new JarEntry(JarFile.MANIFEST_NAME); + jos.putNextEntry(je); + man.write(jos); + jos.closeEntry(); + } + for (Path entry : entries) { String name = toJarEntryName(entry); jos.putNextEntry(new JarEntry(name)); Files.copy(dir.resolve(entry), jos); + jos.closeEntry(); } } } + /** + * Creates a JAR file. + * + * Equivalent to {@code jar cf -C file...} + * + * The input files are resolved against the given directory. Any input + * files that are directories are processed recursively. + */ + public static void createJarFile(Path jarfile, Path dir, Path... file) + throws IOException + { + createJarFile(jarfile, null, dir, file); + } + /** * Creates a JAR file. * diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java b/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java index f95fdeefc1b..7cdc714b0fd 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java @@ -28,6 +28,9 @@ package jdk.testlibrary; import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.InputStreamReader; import static jdk.testlibrary.OSInfo.OSType.*; @@ -147,6 +150,28 @@ public class OSInfo { } } + public static double getSolarisVersion() { + try { + OutputAnalyzer output = ProcessTools.executeProcess("uname", "-v"); + System.out.println("'uname -v' finished with code " + + output.getExitValue()); + return Double.parseDouble(output.getOutput()); + } catch (Exception e) { + System.out.println("First attempt failed with: " + e.getMessage()); + } + + //Try to get Solaris version from /etc/release + try (BufferedReader in = + new BufferedReader(new FileReader("/etc/release"))) { + String line = in.readLine().trim().split(" ")[2]; + return Double.parseDouble(line); + } catch (Exception e) { + System.out.println("Second attempt failed with: " + e.getMessage()); + } + + throw new RuntimeException("Unable to get Solaris version"); + } + public static class WindowsVersion implements Comparable { private final int major; diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java index 35cffc1c994..e2c2f110fc5 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java @@ -423,7 +423,7 @@ public final class ProcessTools { * @param cmds The command line to execute. * @return The output from the process. */ - public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { + public static OutputAnalyzer executeProcess(String... cmds) throws Exception { return executeProcess(new ProcessBuilder(cmds)); } diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java index 4fedb362c5c..17e50c70354 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,8 +23,6 @@ package jdk.testlibrary; -import com.sun.net.httpserver.*; - import java.util.*; import java.util.concurrent.*; import java.io.*; @@ -54,7 +52,7 @@ public class SimpleSSLContext { * loads default keystore from SimpleSSLContext * source directory */ - public SimpleSSLContext () throws IOException { + public SimpleSSLContext() throws IOException { String paths = System.getProperty("test.src.path"); StringTokenizer st = new StringTokenizer(paths, File.pathSeparator); boolean securityExceptions = false; @@ -63,8 +61,10 @@ public class SimpleSSLContext { try { File f = new File(path, "jdk/testlibrary/testkeys"); if (f.exists()) { - init (new FileInputStream(f)); - return; + try (FileInputStream fis = new FileInputStream(f)) { + init(fis); + return; + } } } catch (SecurityException e) { // catch and ignore because permission only required @@ -80,13 +80,14 @@ public class SimpleSSLContext { /** * loads default keystore from given directory */ - public SimpleSSLContext (String dir) throws IOException { + public SimpleSSLContext(String dir) throws IOException { String file = dir+"/testkeys"; - FileInputStream fis = new FileInputStream(file); - init(fis); + try (FileInputStream fis = new FileInputStream(file)) { + init(fis); + } } - private void init (InputStream i) throws IOException { + private void init(InputStream i) throws IOException { try { char[] passphrase = "passphrase".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS"); @@ -98,22 +99,22 @@ public class SimpleSSLContext { TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); - ssl = SSLContext.getInstance ("TLS"); + ssl = SSLContext.getInstance("TLS"); ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); } catch (KeyManagementException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } catch (KeyStoreException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } catch (UnrecoverableKeyException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } catch (CertificateException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } catch (NoSuchAlgorithmException e) { - throw new RuntimeException (e.getMessage()); + throw new RuntimeException(e.getMessage()); } } - public SSLContext get () { + public SSLContext get() { return ssl; } } diff --git a/jdk/test/sun/applet/DeprecatedAppletViewer/DeprecatedAppletViewer.java b/jdk/test/sun/applet/DeprecatedAppletViewer/DeprecatedAppletViewer.java index f3b43f83eee..27cf0330389 100644 --- a/jdk/test/sun/applet/DeprecatedAppletViewer/DeprecatedAppletViewer.java +++ b/jdk/test/sun/applet/DeprecatedAppletViewer/DeprecatedAppletViewer.java @@ -32,17 +32,18 @@ import java.io.PrintStream; */ public final class DeprecatedAppletViewer { - private static final String TEXT = "AppletViewer is deprecated."; + private static final String TEXT + = "Warning: Applet API and AppletViewer are deprecated."; public static void main(final String[] args) { - final PrintStream old = System.out; + final PrintStream old = System.err; final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000); final PrintStream ps = new PrintStream(baos); try { - System.setOut(ps); + System.setErr(ps); sun.applet.Main.main(new String[]{}); } finally { - System.setOut(old); + System.setErr(old); } final String text = new String(baos.toByteArray()); diff --git a/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh b/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh index b47a5efcf0c..a93f2652613 100644 --- a/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh +++ b/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -26,6 +26,7 @@ # @test # @bug 4763315 +# @modules java.naming # @build CanonicalName Lookup # @run shell/timeout=120 cname.sh # @summary Test DNS provider's handling of CNAME records diff --git a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java index 8791b4e27af..1d837841fb4 100644 --- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java +++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /** * @test * @bug 4333920 + * @modules jdk.httpserver * @run main ChunkedEncodingTest * @summary ChunkedEncodingTest unit test */ diff --git a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java index 35b76396930..6affe7a767c 100644 --- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java +++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,6 +26,7 @@ * @bug 4333920 4994372 * @summary ChunkedEncoding unit test; MeteredStream/ProgressData problem * @modules java.base/sun.net + * jdk.httpserver * @run main ChunkedEncodingWithProgressMonitorTest */ diff --git a/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java b/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java index 0423c81060f..a1737d79c23 100644 --- a/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java +++ b/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6446990 + * @modules jdk.httpserver * @run main/othervm TestAvailable * @summary HttpURLConnection#available() reads more and more data into memory */ diff --git a/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java b/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java index a017e6eca9e..82b4e36d01c 100644 --- a/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java +++ b/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /** * @test * @bug 5026745 6631048 + * @modules jdk.httpserver * @run main/othervm/timeout=500 Test * @summary Cannot flush output stream when writing to an HttpUrlConnection */ diff --git a/jdk/test/sun/net/www/http/ChunkedOutputStream/checkError.java b/jdk/test/sun/net/www/http/ChunkedOutputStream/checkError.java index 4575f91e93b..50435ea43c1 100644 --- a/jdk/test/sun/net/www/http/ChunkedOutputStream/checkError.java +++ b/jdk/test/sun/net/www/http/ChunkedOutputStream/checkError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /** * @test * @bug 5054016 + * @key intermittent * @run main/othervm/timeout=300 checkError * @summary get the failure immediately when writing individual chunks over socket fail */ diff --git a/jdk/test/sun/net/www/http/HttpClient/B7025238.java b/jdk/test/sun/net/www/http/HttpClient/B7025238.java index 313972594a4..1af7ec83d5f 100644 --- a/jdk/test/sun/net/www/http/HttpClient/B7025238.java +++ b/jdk/test/sun/net/www/http/HttpClient/B7025238.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -30,6 +30,7 @@ import java.util.concurrent.Executors; /* * @test * @bug 7025238 + * @modules jdk.httpserver * @summary HttpURLConnection does not handle URLs with an empty path component */ public class B7025238 { diff --git a/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java b/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java index 11d6729ae21..7eaa4f74ed4 100644 --- a/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java +++ b/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java @@ -41,6 +41,7 @@ import java.util.List; * @summary Tests for HTTP Digest auth * The impl maintains a cache for auth info, * the testcases run in a separate JVM to avoid cache hits + * @modules jdk.httpserver * @run main/othervm DigestAuth good * @run main/othervm DigestAuth only_nonce * @run main/othervm DigestAuth sha1 diff --git a/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java b/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java index d5dfde58233..6423de7e409 100644 --- a/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java +++ b/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ import sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback; * @test * @bug 8137174 * @modules java.base/sun.net.www.protocol.http.ntlm + * jdk.httpserver * @summary Checks if NTLM auth works fine if security manager set * @run main/othervm/java.security.policy=NTLMAuthWithSM.policy NTLMAuthWithSM */ diff --git a/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java b/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java index 07d353cba85..104be1d6d94 100644 --- a/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java +++ b/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -30,6 +30,7 @@ import java.net.*; /* * @test * @bug 7157360 + * @modules jdk.httpserver * @summary HttpURLConnection: HTTP method DELETE doesn't support output */ public class PostOnDelete { diff --git a/jdk/test/sun/net/www/protocol/http/6550798/test.java b/jdk/test/sun/net/www/protocol/http/6550798/test.java index 9bcf5f91548..95f70f58911 100644 --- a/jdk/test/sun/net/www/protocol/http/6550798/test.java +++ b/jdk/test/sun/net/www/protocol/http/6550798/test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6550798 * @summary Using InputStream.skip with ResponseCache will cause partial data to be cached + * @modules jdk.httpserver * @run main/othervm test */ diff --git a/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java b/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java index d052b018ffa..250557e9c55 100644 --- a/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java +++ b/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6358532 + * @modules jdk.httpserver * @run main/othervm AsyncDisconnect * @summary HttpURLConnection.disconnect doesn't really do the job */ diff --git a/jdk/test/sun/net/www/protocol/http/B5017051.java b/jdk/test/sun/net/www/protocol/http/B5017051.java index 8e1218d1a3a..1859be41a61 100644 --- a/jdk/test/sun/net/www/protocol/http/B5017051.java +++ b/jdk/test/sun/net/www/protocol/http/B5017051.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /* * @test * @bug 5017051 6360774 + * @modules jdk.httpserver * @run main/othervm B5017051 * @summary Tests CR 5017051 & 6360774 */ diff --git a/jdk/test/sun/net/www/protocol/http/B6299712.java b/jdk/test/sun/net/www/protocol/http/B6299712.java index cf7be47e3ef..24c78d64bfa 100644 --- a/jdk/test/sun/net/www/protocol/http/B6299712.java +++ b/jdk/test/sun/net/www/protocol/http/B6299712.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6299712 7150552 + * @modules jdk.httpserver * @run main/othervm B6299712 * @summary NullPointerException in sun.net.www.protocol.http.HttpURLConnection.followRedirect */ diff --git a/jdk/test/sun/net/www/protocol/http/B6369510.java b/jdk/test/sun/net/www/protocol/http/B6369510.java index 7757f091d7b..2068b04b5b2 100644 --- a/jdk/test/sun/net/www/protocol/http/B6369510.java +++ b/jdk/test/sun/net/www/protocol/http/B6369510.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6369510 + * @modules jdk.httpserver * @run main/othervm B6369510 * @summary HttpURLConnection sets Content-Type to application/x-www-form-urlencoded */ diff --git a/jdk/test/sun/net/www/protocol/http/B6518816.java b/jdk/test/sun/net/www/protocol/http/B6518816.java index d74db8ef2aa..929387c3e7b 100644 --- a/jdk/test/sun/net/www/protocol/http/B6518816.java +++ b/jdk/test/sun/net/www/protocol/http/B6518816.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6518816 + * @modules jdk.httpserver * @run main/othervm B6518816 */ diff --git a/jdk/test/sun/net/www/protocol/http/B6641309.java b/jdk/test/sun/net/www/protocol/http/B6641309.java index 9da4da3aef0..25952c65cd7 100644 --- a/jdk/test/sun/net/www/protocol/http/B6641309.java +++ b/jdk/test/sun/net/www/protocol/http/B6641309.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 6641309 + * @modules jdk.httpserver * @summary Wrong Cookie separator used in HttpURLConnection */ diff --git a/jdk/test/sun/net/www/protocol/http/B6660405.java b/jdk/test/sun/net/www/protocol/http/B6660405.java index 8cde84eca9f..50b5838e2c5 100644 --- a/jdk/test/sun/net/www/protocol/http/B6660405.java +++ b/jdk/test/sun/net/www/protocol/http/B6660405.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 6660405 + * @modules jdk.httpserver * @summary HttpURLConnection returns the wrong InputStream */ diff --git a/jdk/test/sun/net/www/protocol/http/B8012625.java b/jdk/test/sun/net/www/protocol/http/B8012625.java index c8c8ef0c033..8145941530c 100644 --- a/jdk/test/sun/net/www/protocol/http/B8012625.java +++ b/jdk/test/sun/net/www/protocol/http/B8012625.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /** * @test * @bug 8012625 + * @modules jdk.httpserver * @run main B8012625 */ diff --git a/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java b/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java index 5e8bb8e4c41..02e54b1529d 100644 --- a/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java +++ b/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /** * @test * @bug 6947917 + * @modules jdk.httpserver * @summary Error in basic authentication when user name and password are long */ diff --git a/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java b/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java index 33a143b5b5c..e673080306f 100644 --- a/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java +++ b/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6488669 6595324 6993490 + * @modules jdk.httpserver * @run main/othervm ChunkedErrorStream * @summary Chunked ErrorStream tests */ diff --git a/jdk/test/sun/net/www/protocol/http/HttpOnly.java b/jdk/test/sun/net/www/protocol/http/HttpOnly.java index 6a2ce8256d9..d377ebf7c15 100644 --- a/jdk/test/sun/net/www/protocol/http/HttpOnly.java +++ b/jdk/test/sun/net/www/protocol/http/HttpOnly.java @@ -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 @@ -23,6 +23,7 @@ /** * @test * @bug 7095980 8007315 + * @modules jdk.httpserver * @summary Ensure HttpURLConnection (and supporting APIs) don't expose * HttpOnly cookies */ diff --git a/jdk/test/sun/net/www/protocol/http/HttpStreams.java b/jdk/test/sun/net/www/protocol/http/HttpStreams.java index 897cd6572b5..9b94b53e09b 100644 --- a/jdk/test/sun/net/www/protocol/http/HttpStreams.java +++ b/jdk/test/sun/net/www/protocol/http/HttpStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /** * @test * @bug 8011719 + * @modules jdk.httpserver * @summary Basic checks to verify behavior of returned input streams */ diff --git a/jdk/test/sun/net/www/protocol/http/NoCache.java b/jdk/test/sun/net/www/protocol/http/NoCache.java index f452bc3d497..f60efcb1ed8 100644 --- a/jdk/test/sun/net/www/protocol/http/NoCache.java +++ b/jdk/test/sun/net/www/protocol/http/NoCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 7133367 + * @modules jdk.httpserver * @summary ResponseCache.put should not be called when setUseCaches(false) */ diff --git a/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java b/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java index 6582a67744f..8c485af01ac 100644 --- a/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java +++ b/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /** * @test * @library /lib/testlibrary/ + * @modules jdk.httpserver * @build jdk.testlibrary.SimpleSSLContext * @compile RedirectOnPost.java * @run main/othervm RedirectOnPost diff --git a/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java b/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java index 31954bb17d0..dad3d29e7a4 100644 --- a/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java +++ b/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6472250 + * @modules jdk.httpserver * @run main/othervm StreamingOutputStream * @summary HttpURLConnection.getOutputStream streaming mode bug when called multiple times */ diff --git a/jdk/test/sun/net/www/protocol/http/UserAuth.java b/jdk/test/sun/net/www/protocol/http/UserAuth.java index 4d5b2de12d0..81432a8086f 100644 --- a/jdk/test/sun/net/www/protocol/http/UserAuth.java +++ b/jdk/test/sun/net/www/protocol/http/UserAuth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6421122 + * @modules jdk.httpserver * @run main/othervm UserAuth * @summary Authorization header removed for preemptive authentication by user code */ diff --git a/jdk/test/sun/net/www/protocol/http/UserCookie.java b/jdk/test/sun/net/www/protocol/http/UserCookie.java index 2216385f312..ee5e15285cf 100644 --- a/jdk/test/sun/net/www/protocol/http/UserCookie.java +++ b/jdk/test/sun/net/www/protocol/http/UserCookie.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6439651 + * @modules jdk.httpserver * @run main/othervm UserAuth * @summary Sending "Cookie" header with JRE 1.5.0_07 doesn't work anymore */ diff --git a/jdk/test/sun/net/www/protocol/http/ZoneId.java b/jdk/test/sun/net/www/protocol/http/ZoneId.java index 125c97d486d..6d8b7d1b628 100644 --- a/jdk/test/sun/net/www/protocol/http/ZoneId.java +++ b/jdk/test/sun/net/www/protocol/http/ZoneId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,7 +24,9 @@ /* * @test * @bug 8027308 + * @key intermittent * @modules java.base/sun.net.www.protocol.http + * jdk.httpserver * @summary verifies that HttpURLConnection does not send the zone id in the * 'Host' field of the header: * Host: [fe80::a00:27ff:aaaa:aaaa] instead of diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java index a7e0bc3ab14..68b20803ae9 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 6771432 * @summary createSocket() - smpatch fails using 1.6.0_10 because of * "Unconnected sockets not implemented" + * @modules jdk.httpserver * @run main/othervm HttpsCreateSockTest * * SunJSSE does not support dynamic system properties, no way to re-use diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java index 4011cea722e..6e1414f8cdd 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6614957 * @summary HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets + * @modules jdk.httpserver * @run main/othervm HttpsSocketFacTest * * SunJSSE does not support dynamic system properties, no way to re-use diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java index 4e0f0bdac59..d90d9478e2a 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java @@ -235,6 +235,7 @@ public class ImpactOnSNI { hostname); // Ignore the test if the hostname does not sound like a domain name. if ((hostname == null) || hostname.isEmpty() || + !hostname.contains(".") || hostname.endsWith(".") || hostname.startsWith("localhost") || Character.isDigit(hostname.charAt(hostname.length() - 1))) { diff --git a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java index 0f5545707a4..e97de717772 100644 --- a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java +++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,12 @@ /* * @test - * @bug 8132734 + * @bug 8132734 8144062 * @summary Test that URL connections to multi-release jars can be runtime versioned * @library /lib/testlibrary/java/util/jar + * @modules java.compiler + * jdk.httpserver + * jdk.jartool * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer * @run testng MultiReleaseJarURLConnection */ @@ -43,8 +46,6 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.jar.JarFile; -import jdk.Version; - import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -94,7 +95,7 @@ public class MultiReleaseJarURLConnection { public void testRuntimeVersioning(String style, String file) throws Exception { String urlFile = "jar:file:" + file + "!/"; String baseUrlEntry = urlFile + "version/Version.java"; - String rtreturn = "return " + Version.current().major(); + String rtreturn = "return " + Runtime.version().major(); Assert.assertTrue(readAndCompare(new URL(baseUrlEntry), "return 8")); // #runtime is "magic" for a multi-release jar, but not for unversioned jar @@ -109,7 +110,7 @@ public class MultiReleaseJarURLConnection { if (style.equals("unversioned")) return; // direct access to versioned entry - String versUrlEntry = urlFile + "META-INF/versions/" + Version.current().major() + String versUrlEntry = urlFile + "META-INF/versions/" + Runtime.version().major() + "/version/Version.java"; Assert.assertTrue(readAndCompare(new URL(versUrlEntry), rtreturn)); // adding any fragment does not change things @@ -187,7 +188,7 @@ public class MultiReleaseJarURLConnection { MethodType mt = MethodType.methodType(int.class); MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt); Assert.assertEquals((int)mh.invoke(vcls.newInstance()), - style.equals("unversioned") ? 8 : Version.current().major()); + style.equals("unversioned") ? 8 : Runtime.version().major()); // now get a resource and verify that we don't have a fragment attached URL vclsUrl = vcls.getResource("/version/Version.class"); @@ -206,7 +207,7 @@ public class MultiReleaseJarURLConnection { if (style.equals("unversioned")) { suffix = ".jar!/version/Version.class"; } else { - suffix = ".jar!/META-INF/versions/" + Version.current().major() + suffix = ".jar!/META-INF/versions/" + Runtime.version().major() + "/version/Version.class"; } Assert.assertTrue(rep.endsWith(suffix)); diff --git a/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java b/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java index 8c8049bdf5c..9ec2dbfd019 100644 --- a/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java +++ b/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java @@ -43,6 +43,7 @@ import java.util.Random; /* * @test * @requires sun.arch.data.model == "64" + * @modules java.management * @build TestMaxCachedBufferSize * @run main/othervm TestMaxCachedBufferSize * @run main/othervm -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize diff --git a/jdk/test/sun/security/jca/PreferredProviderTest.java b/jdk/test/sun/security/jca/PreferredProviderTest.java index 56aa4a0210e..72026222fee 100644 --- a/jdk/test/sun/security/jca/PreferredProviderTest.java +++ b/jdk/test/sun/security/jca/PreferredProviderTest.java @@ -25,15 +25,17 @@ import java.security.MessageDigest; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Security; +import java.security.Signature; import java.security.Provider; import java.util.Arrays; import java.util.List; import javax.crypto.Cipher; +import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; /** * @test - * @bug 8076359 8133151 8145344 8150512 + * @bug 8076359 8133151 8145344 8150512 8155847 * @summary Test the value for new jdk.security.provider.preferred * security property */ @@ -61,8 +63,8 @@ public class PreferredProviderTest { //java.security file which will be verified. switch (type) { case "sparcv9": - preferredProp = "AES:SunJCE, SHA1:SUN, SHA-224:SUN," - + " SHA-256:SUN, SHA-384:SUN, SHA-512:SUN"; + preferredProp = "AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, " + + "HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE"; verifyPreferredProviderProperty(os, type, preferredProp); verifyDigestProvider(os, type, Arrays.asList( @@ -71,14 +73,51 @@ public class PreferredProviderTest { new DataTuple("SHA-224", "SUN"), new DataTuple("SHA-256", "SUN"), new DataTuple("SHA-384", "SUN"), - new DataTuple("SHA-512", "SUN"))); + new DataTuple("SHA-512", "SUN"), + new DataTuple("SHA-512/224", "SUN"), + new DataTuple("SHA-512/256", "SUN"))); + + verifyMacProvider(os, type, Arrays.asList( + new DataTuple("HmacSHA1", "SunJCE"), + new DataTuple("HmacSHA224", "SunJCE"), + new DataTuple("HmacSHA256", "SunJCE"), + new DataTuple("HmacSHA384", "SunJCE"), + new DataTuple("HmacSHA512", "SunJCE"))); break; case "amd64": - preferredProp = "AES:SunJCE, RSA:SunRsaSign"; + preferredProp = "AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, " + + "HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE, " + + "RSA:SunRsaSign, SHA1withRSA:SunRsaSign, " + + "Group.SHA2RSA:SunRsaSign"; + verifyPreferredProviderProperty(os, type, preferredProp); verifyKeyFactoryProvider(os, type, Arrays.asList( new DataTuple("RSA", "SunRsaSign"))); + + verifyDigestProvider(os, type, Arrays.asList( + new DataTuple("SHA1", "SUN"), + new DataTuple("SHA-1", "SUN"), + new DataTuple("SHA-224", "SUN"), + new DataTuple("SHA-256", "SUN"), + new DataTuple("SHA-384", "SUN"), + new DataTuple("SHA-512", "SUN"), + new DataTuple("SHA-512/224", "SUN"), + new DataTuple("SHA-512/256", "SUN"))); + + verifyMacProvider(os, type, Arrays.asList( + new DataTuple("HmacSHA1", "SunJCE"), + new DataTuple("HmacSHA224", "SunJCE"), + new DataTuple("HmacSHA256", "SunJCE"), + new DataTuple("HmacSHA384", "SunJCE"), + new DataTuple("HmacSHA512", "SunJCE"))); + + verifySignatureProvider(os, type, Arrays.asList( + new DataTuple("SHA1withRSA", "SunRsaSign"), + new DataTuple("SHA224withRSA", "SunRsaSign"), + new DataTuple("SHA256withRSA", "SunRsaSign"), + new DataTuple("SHA384withRSA", "SunRsaSign"), + new DataTuple("SHA512withRSA", "SunRsaSign"))); break; } verifyDigestProvider(os, type, Arrays.asList( @@ -99,6 +138,8 @@ public class PreferredProviderTest { String preferredProvider = Security.getProperty("jdk.security.provider.preferred"); if (!preferredProvider.equals(preferred)) { + System.out.println("Expected: " + preferred + "\nResult: " + + preferredProvider); throw new RuntimeException(String.format( "Test Failed: wrong jdk.security.provider.preferred value " + "on %s-%s", os, arch)); @@ -120,6 +161,19 @@ public class PreferredProviderTest { "Preferred MessageDigest algorithm verification successful."); } + private static void verifyMacProvider(String os, String arch, + List algoProviders) throws NoSuchAlgorithmException { + for (DataTuple dataTuple : algoProviders) { + System.out.printf( + "Verifying Mac for '%s'%n", dataTuple.algorithm); + Mac mac = Mac.getInstance(dataTuple.algorithm); + matchProvider(mac.getProvider(), dataTuple.provider, + dataTuple.algorithm, os, arch); + } + System.out.println( + "Preferred Mac algorithm verification successful."); + } + private static void verifyKeyFactoryProvider(String os, String arch, List algoProviders) throws NoSuchAlgorithmException { for (DataTuple dataTuple : algoProviders) { @@ -133,6 +187,19 @@ public class PreferredProviderTest { "Preferred KeyFactory algorithm verification successful."); } + private static void verifySignatureProvider(String os, String arch, + List algoProviders) throws NoSuchAlgorithmException { + for (DataTuple dataTuple : algoProviders) { + System.out.printf( + "Verifying Signature for '%s'%n", dataTuple.algorithm); + Signature si = Signature.getInstance(dataTuple.algorithm); + matchProvider(si.getProvider(), dataTuple.provider, + dataTuple.algorithm, os, arch); + } + System.out.println( + "Preferred Signature algorithm verification successful."); + } + private static void matchProvider(Provider provider, String expected, String algo, String os, String arch) { if (!provider.getName().equals(expected)) { diff --git a/jdk/test/sun/security/krb5/canonicalize/Test.java b/jdk/test/sun/security/krb5/canonicalize/Test.java index 8d21a50727f..62c44de9984 100644 --- a/jdk/test/sun/security/krb5/canonicalize/Test.java +++ b/jdk/test/sun/security/krb5/canonicalize/Test.java @@ -22,7 +22,7 @@ */ /* * @test - * @bug 6682516 + * @bug 6682516 8149521 * @summary SPNEGO_HTTP_AUTH/WWW_KRB and SPNEGO_HTTP_AUTH/WWW_SPNEGO failed on all non-windows platforms * @modules java.security.jgss/sun.security.krb5 * @run main/othervm -Djava.security.krb5.conf=krb5.conf Test @@ -44,9 +44,11 @@ public class Test { check("c1", "c1.this.domain"); check("c1.this", "c1.this.domain"); check("c1.this.domain", "c1.this.domain"); + check("c1.this.domain.", "c1.this.domain"); // canonicalized name goes IP, reject check("c2", "c2"); + check("c2.", "c2"); // canonicalized name goes strange, reject check("c3", "c3"); @@ -63,4 +65,4 @@ public class Test { throw new Exception("Output is " + pn); } } - } +} diff --git a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java index bd2fcdadc31..45a7c178455 100644 --- a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java +++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java @@ -33,6 +33,7 @@ import java.security.spec.DSAParameterSpec; import java.security.spec.InvalidParameterSpecException; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /* * @test @@ -41,26 +42,15 @@ import java.util.List; * @summary Verify that DSAGenParameterSpec can and can only be used to generate * DSA within some certain range of key sizes as described in the class * specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and - * (3072, 256) should be OK for DSAGenParameterSpec. But the real - * implementation SUN doesn't support (3072, 256). - * @run main TestDSAGenParameterSpec + * (3072, 256) should be OK for DSAGenParameterSpec. + * @run main TestDSAGenParameterSpec 2048,256,true 2048,224,true 1024,160,true 4096,256 3072,224 2048,160 1024,224 512,160 + * @run main TestDSAGenParameterSpec 3072,256,true */ public class TestDSAGenParameterSpec { private static final String ALGORITHM_NAME = "DSA"; private static final String PROVIDER_NAME = "SUN"; - private static final List DATA = Arrays.asList( - new DataTuple(1024, 160, true, true), - new DataTuple(2048, 224, true, true), - new DataTuple(2048, 256, true, true), - new DataTuple(3072, 256, true, false), - new DataTuple(1024, 224), - new DataTuple(2048, 160), - new DataTuple(4096, 256), - new DataTuple(512, 160), - new DataTuple(3072, 224)); - private static void testDSAGenParameterSpec(DataTuple dataTuple) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidParameterSpecException, InvalidAlgorithmParameterException { @@ -84,14 +74,7 @@ public class TestDSAGenParameterSpec { checkParam(param, genParamSpec); System.out.println("Test case passed"); } catch (InvalidParameterException ipe) { - // The DSAGenParameterSpec API support this, but the real - // implementation in SUN doesn't - if (!dataTuple.isSunProviderSupported) { - System.out.println("Test case passed: expected " - + "InvalidParameterException is caught"); - } else { - throw new RuntimeException("Test case failed.", ipe); - } + throw new RuntimeException("Test case failed.", ipe); } } @@ -127,11 +110,9 @@ public class TestDSAGenParameterSpec { throw new RuntimeException("Wrong seed length"); } - // use the parameters to generate real DSA keys KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM_NAME, PROVIDER_NAME); keyGen.initialize(spec); - keyGen.generateKeyPair(); } private static DSAGenParameterSpec createGenParameterSpec( @@ -158,10 +139,21 @@ public class TestDSAGenParameterSpec { } public static void main(String[] args) throws Exception { - for (DataTuple dataTuple : DATA) { + List dataTuples = Arrays.stream(args) + .map(arg -> arg.split(",")).map(params -> { + int primePLen = Integer.valueOf(params[0]); + int subprimeQLen = Integer.valueOf(params[1]); + boolean isDSASpecSupported = false; + if (params.length == 3) { + isDSASpecSupported = Boolean.valueOf(params[2]); + } + return new DataTuple(primePLen, subprimeQLen, + isDSASpecSupported); + }).collect(Collectors.toList()); + + for (DataTuple dataTuple : dataTuples) { testDSAGenParameterSpec(dataTuple); } - System.out.println("All tests passed"); } private static class DataTuple { @@ -169,18 +161,13 @@ public class TestDSAGenParameterSpec { private int primePLen; private int subprimeQLen; private boolean isDSASpecSupported; - private boolean isSunProviderSupported; private DataTuple(int primePLen, int subprimeQLen, - boolean isDSASpecSupported, boolean isSunProviderSupported) { + boolean isDSASpecSupported) { this.primePLen = primePLen; this.subprimeQLen = subprimeQLen; this.isDSASpecSupported = isDSASpecSupported; - this.isSunProviderSupported = isSunProviderSupported; - } - - private DataTuple(int primePLen, int subprimeQLen) { - this(primePLen, subprimeQLen, false, false); } } } + diff --git a/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.java b/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.java new file mode 100644 index 00000000000..17a4c5d8d71 --- /dev/null +++ b/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8150468 + * @summary check that a badly formatted policy file is handled correctly + * @run main/othervm BadPolicyFile + */ + +import java.io.File; +import java.net.URI; +import java.security.AccessControlException; +import java.security.Policy; +import java.security.URIParameter; + +public class BadPolicyFile { + + public static void main(String[] args) throws Exception { + URI uri = new File(System.getProperty("test.src", "."), + "BadPolicyFile.policy").toURI(); + Policy.setPolicy(Policy.getInstance("JavaPolicy", new URIParameter(uri))); + System.setSecurityManager(new SecurityManager()); + try { + String javahome = System.getProperty("java.home"); + throw new Exception("Expected AccessControlException"); + } catch (AccessControlException ace) { + System.out.println("Test PASSED"); + } + } +} diff --git a/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.policy b/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.policy new file mode 100644 index 00000000000..b5abfaf8f42 --- /dev/null +++ b/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.policy @@ -0,0 +1,4 @@ +grant { + // permission statement is missing trailing semi-colon + permission "java.util.PropertyPermission" "java.home", "read" +}; diff --git a/jdk/test/sun/security/provider/PolicyFile/Modules.java b/jdk/test/sun/security/provider/PolicyFile/Modules.java index 855441e036a..914ef05790d 100644 --- a/jdk/test/sun/security/provider/PolicyFile/Modules.java +++ b/jdk/test/sun/security/provider/PolicyFile/Modules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,19 @@ * @test * @bug 8047771 * @summary check permissions and principals from various modules + * @modules java.desktop + * java.logging + * java.management + * java.security.jgss + * java.smartcardio + * java.sql + * java.xml + * java.xml.bind + * jdk.attach + * jdk.jdi + * jdk.net + * jdk.security.auth + * jdk.security.jgss * @compile -addmods java.xml.ws,java.smartcardio Modules.java * @run main/othervm/java.security.policy==modules.policy * -addmods java.xml.ws,java.smartcardio Modules diff --git a/jdk/test/sun/security/provider/SecureRandom/StrongSecureRandom.java b/jdk/test/sun/security/provider/SecureRandom/StrongSecureRandom.java index 2a45522cad8..fd0b20cfdb2 100644 --- a/jdk/test/sun/security/provider/SecureRandom/StrongSecureRandom.java +++ b/jdk/test/sun/security/provider/SecureRandom/StrongSecureRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -21,11 +21,11 @@ * questions. */ -/** +/* * @test - * @bug 6425477 + * @bug 6425477 8141039 * @summary Better support for generation of high entropy random numbers - * @run main/othervm StrongSecureRandom + * @run main StrongSecureRandom */ import java.security.*; import java.util.*; @@ -35,7 +35,10 @@ import java.util.*; */ public class StrongSecureRandom { - private static String os = System.getProperty("os.name", "unknown"); + private static final String os = System.getProperty("os.name", "unknown"); + private static final String DRBG_CONFIG = "securerandom.drbg.config"; + private static final String DRBG_CONFIG_VALUE + = Security.getProperty(DRBG_CONFIG); private static void testDefaultEgd() throws Exception { // No SecurityManager installed. @@ -47,31 +50,53 @@ public class StrongSecureRandom { } } - private static void testSHA1PRNGImpl() throws Exception { - SecureRandom sr; + /** + * Verify if the mechanism is DRBG type. + * @param mech Mechanism name + * @return True if the mechanism name is DRBG type else False. + */ + private static boolean isDRBG(String mech) { + return mech.contains("_DRBG"); + } + + private static void testSecureRandomImpl(String algo, boolean drbg) + throws Exception { + byte[] ba; + final String secureRandomSource + = Security.getProperty("securerandom.source"); + try { + String urandom = "file:/dev/urandom"; - String urandom = "file:/dev/urandom"; + System.out.println("Testing new SeedGenerator and EGD"); - System.out.println("Testing new SeedGenerator and EGD"); + Security.setProperty("securerandom.source", urandom); + if (!Security.getProperty("securerandom.source").equals(urandom)) { + throw new Exception("Couldn't set securerandom.source"); + } - Security.setProperty("securerandom.source", urandom); - if (!Security.getProperty("securerandom.source").equals(urandom)) { - throw new Exception("Couldn't set securerandom.source"); + /* + * Take out a large number of bytes in hopes of blocking. + * Don't expect this to happen, unless something is broken on Linux + */ + SecureRandom sr = null; + if (drbg) { + Security.setProperty(DRBG_CONFIG, algo); + sr = SecureRandom.getInstance("DRBG"); + } else { + sr = SecureRandom.getInstance(algo); + } + if (!sr.getAlgorithm().equals(isDRBG(algo) ? "DRBG" : algo)) { + throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); + } + + ba = sr.generateSeed(4096); + sr.nextBytes(ba); + sr.setSeed(ba); + } finally { + Security.setProperty("securerandom.source", secureRandomSource); + Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); } - - /* - * Take out a large number of bytes in hopes of blocking. - * Don't expect this to happen, unless something is broken on Linux - */ - sr = SecureRandom.getInstance("SHA1PRNG"); - if (!sr.getAlgorithm().equals("SHA1PRNG")) { - throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); - } - - ba = sr.generateSeed(4096); - sr.nextBytes(ba); - sr.setSeed(ba); } private static void testNativePRNGImpls() throws Exception { @@ -85,7 +110,7 @@ public class StrongSecureRandom { return; } - System.out.println(" Testing regular"); + System.out.println("Testing regular"); sr = SecureRandom.getInstance("NativePRNG"); if (!sr.getAlgorithm().equals("NativePRNG")) { throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); @@ -94,7 +119,7 @@ public class StrongSecureRandom { sr.nextBytes(ba); sr.setSeed(ba); - System.out.println(" Testing NonBlocking"); + System.out.println("Testing NonBlocking"); sr = SecureRandom.getInstance("NativePRNGNonBlocking"); if (!sr.getAlgorithm().equals("NativePRNGNonBlocking")) { throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); @@ -108,7 +133,7 @@ public class StrongSecureRandom { return; } - System.out.println(" Testing Blocking"); + System.out.println("Testing Blocking"); sr = SecureRandom.getInstance("NativePRNGBlocking"); if (!sr.getAlgorithm().equals("NativePRNGBlocking")) { throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); @@ -141,9 +166,15 @@ public class StrongSecureRandom { throws Exception { System.out.println("Testing: '" + property + "' " + expected); - - Security.setProperty("securerandom.strongAlgorithms", property); - testStrongInstance(expected); + final String origStrongAlgoProp + = Security.getProperty("securerandom.strongAlgorithms"); + try { + Security.setProperty("securerandom.strongAlgorithms", property); + testStrongInstance(expected); + } finally { + Security.setProperty( + "securerandom.strongAlgorithms", origStrongAlgoProp); + } } private static void testProperties() throws Exception { @@ -228,7 +259,10 @@ public class StrongSecureRandom { public static void main(String args[]) throws Exception { testDefaultEgd(); - testSHA1PRNGImpl(); + for (String algo : new String[]{ + "SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) { + testSecureRandomImpl(algo, isDRBG(algo)); + } testNativePRNGImpls(); testAllImpls(); diff --git a/jdk/test/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java b/jdk/test/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java index d91ce78db4b..93889729058 100644 --- a/jdk/test/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java +++ b/jdk/test/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2011, 2016, Oracle and/or its affiliates. All rights + * reserved. * 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,10 +24,9 @@ /* * @test - * @bug 6998583 + * @bug 6998583 8141039 * @summary NativeSeedGenerator is making 8192 byte read requests from * entropy pool on each init. - * @run main SeedGeneratorChoice * @run main/othervm -Djava.security.egd=file:/dev/random SeedGeneratorChoice * @run main/othervm -Djava.security.egd=file:filename SeedGeneratorChoice */ @@ -39,14 +39,24 @@ * We should always fall back to the ThreadedSeedGenerator if exceptions * are encountered with user defined source of entropy. */ - import java.security.SecureRandom; +import java.security.Security; public class SeedGeneratorChoice { public static void main(String... arguments) throws Exception { - byte[] bytes; - SecureRandom prng = SecureRandom.getInstance("SHA1PRNG"); - bytes = prng.generateSeed(1); + for (String mech : new String[]{"SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", + "CTR_DRBG"}) { + + SecureRandom prng = null; + if (!mech.contains("_DRBG")) { + prng = SecureRandom.getInstance(mech); + } else { + Security.setProperty("securerandom.drbg.config", mech); + prng = SecureRandom.getInstance("DRBG"); + } + prng.generateSeed(1); + } } + } diff --git a/jdk/test/sun/security/rsa/SpecTest.java b/jdk/test/sun/security/rsa/SpecTest.java index 24cddfe3591..7b3c52e5d1f 100644 --- a/jdk/test/sun/security/rsa/SpecTest.java +++ b/jdk/test/sun/security/rsa/SpecTest.java @@ -24,7 +24,6 @@ /** * @test * @bug 8044199 8137231 - * @key intermittent * @summary Check same KeyPair's private key and public key have same modulus. * also check public key's public exponent equals to given spec's public * exponent. Only key size 1024 is tested with RSAKeyGenParameterSpec.F0 (3). diff --git a/jdk/test/sun/security/tools/keytool/DefaultSignatureAlgorithm.java b/jdk/test/sun/security/tools/keytool/DefaultSignatureAlgorithm.java new file mode 100644 index 00000000000..ad6297f2b21 --- /dev/null +++ b/jdk/test/sun/security/tools/keytool/DefaultSignatureAlgorithm.java @@ -0,0 +1,80 @@ +/* + * 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 8138766 + * @summary New default -sigalg for keytool + * @modules java.base/sun.security.tools.keytool + */ + +import sun.security.tools.keytool.Main; + +import java.io.File; +import java.security.KeyStore; +import java.security.cert.X509Certificate; + +public class DefaultSignatureAlgorithm { + + private static int counter = 0; + + public static void main(String[] args) throws Exception { + + // Calculating large RSA keys are too slow. + run("RSA", 1024, null, "SHA256withRSA"); + run("RSA", 3072, null, "SHA256withRSA"); + run("RSA", 3073, null, "SHA384withRSA"); + + run("DSA", 1024, null, "SHA256withDSA"); + run("DSA", 3072, null, "SHA256withDSA"); + + run("EC", 192, null, "SHA256withECDSA"); + run("EC", 384, null, "SHA384withECDSA"); + run("EC", 571, null, "SHA512withECDSA"); + + // If you specify one, it will be used. + run("EC", 571, "SHA256withECDSA", "SHA256withECDSA"); + } + + private static void run(String keyAlg, int keySize, + String sigAlg, String expectedSigAlg) throws Exception { + String alias = keyAlg + keySize + (counter++); + String cmd = "-keystore ks -storepass changeit" + + " -keypass changeit -alias " + alias + + " -keyalg " + keyAlg + " -keysize " + keySize + + " -genkeypair -dname CN=" + alias + " -debug"; + if (sigAlg != null) { + cmd += " -sigalg " + sigAlg; + } + Main.main(cmd.split(" ")); + + KeyStore ks = KeyStore.getInstance( + new File("ks"), "changeit".toCharArray()); + X509Certificate cert = (X509Certificate)ks.getCertificate(alias); + String actualSigAlg = cert.getSigAlgName(); + if (!actualSigAlg.equals(expectedSigAlg)) { + throw new Exception("Failure at " + alias + ": expected " + + expectedSigAlg + ", actually " + actualSigAlg); + } + } +} diff --git a/jdk/test/sun/text/IntHashtable/Bug4170614Test.java b/jdk/test/sun/text/IntHashtable/Bug4170614Test.java new file mode 100644 index 00000000000..97e08a1bdd4 --- /dev/null +++ b/jdk/test/sun/text/IntHashtable/Bug4170614Test.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + (this test doesn't have an at-test tag because it's run by a shell + script instead of directly by the test harness) +*/ + +/* + * + * + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved + * + * Portions copyright (c) 2007 Sun Microsystems, Inc. + * All Rights Reserved. + * + * The original version of this source code and documentation + * is copyrighted and owned by Taligent, Inc., a wholly-owned + * subsidiary of IBM. These materials are provided under terms + * of a License Agreement between Taligent and Sun. This technology + * is protected by multiple US and International patents. + * + * This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + */ +package java.text; +import sun.text.IntHashtable; + + +/** + * This class tests some internal hashCode() functions. + * Bug #4170614 complained that we had two iternal classes that + * break the invariant that if a.equals(b) than a.hashCode() == + * b.hashCode(). This is because these classes overrode equals() + * but not hashCode(). These are both purely internal classes, and + * the library itself doesn't actually call hashCode(), so this isn't + * actually causing anyone problems yet. But if these classes are + * ever exposed in the API, their hashCode() methods need to work right. + * PatternEntry will never be exposed in the API, but IntHashtable + * might be. This is a shell test to allow us to access classes that + * are declared package private. + * @author Richard Gillam + */ +public class Bug4170614Test { + public static void main(String[] args) throws Exception { + testIntHashtable(); + testPatternEntry(); + } + + + public static void testIntHashtable() throws Exception { + IntHashtable fred = new IntHashtable(); + fred.put(1, 10); + fred.put(2, 20); + fred.put(3, 30); + + IntHashtable barney = new IntHashtable(); + barney.put(1, 10); + barney.put(3, 30); + barney.put(2, 20); + + IntHashtable homer = new IntHashtable(); + homer.put(3, 30); + homer.put(1, 10); + homer.put(7, 900); + + if (fred.equals(barney)) { + System.out.println("fred.equals(barney)"); + } + else { + System.out.println("!fred.equals(barney)"); + } + System.out.println("fred.hashCode() == " + fred.hashCode()); + System.out.println("barney.hashCode() == " + barney.hashCode()); + + if (!fred.equals(barney)) { + throw new Exception("equals() failed on two hashtables that are equal"); + } + + if (fred.hashCode() != barney.hashCode()) { + throw new Exception("hashCode() failed on two hashtables that are equal"); + } + + System.out.println(); + if (fred.equals(homer)) { + System.out.println("fred.equals(homer)"); + } + else { + System.out.println("!fred.equals(homer)"); + } + System.out.println("fred.hashCode() == " + fred.hashCode()); + System.out.println("homer.hashCode() == " + homer.hashCode()); + + if (fred.equals(homer)) { + throw new Exception("equals() failed on two hashtables that are not equal"); + } + + if (fred.hashCode() == homer.hashCode()) { + throw new Exception("hashCode() failed on two hashtables that are not equal"); + } + + System.out.println(); + System.out.println("testIntHashtable() passed.\n"); + } + + public static void testPatternEntry() throws Exception { + PatternEntry fred = new PatternEntry(1, + new StringBuffer("hello"), + new StringBuffer("up")); + PatternEntry barney = new PatternEntry(1, + new StringBuffer("hello"), + new StringBuffer("down")); + // (equals() only considers the "chars" field, so fred and barney are equal) + PatternEntry homer = new PatternEntry(1, + new StringBuffer("goodbye"), + new StringBuffer("up")); + + if (fred.equals(barney)) { + System.out.println("fred.equals(barney)"); + } + else { + System.out.println("!fred.equals(barney)"); + } + System.out.println("fred.hashCode() == " + fred.hashCode()); + System.out.println("barney.hashCode() == " + barney.hashCode()); + + if (!fred.equals(barney)) { + throw new Exception("equals() failed on two hashtables that are equal"); + } + + if (fred.hashCode() != barney.hashCode()) { + throw new Exception("hashCode() failed on two hashtables that are equal"); + } + + System.out.println(); + if (fred.equals(homer)) { + System.out.println("fred.equals(homer)"); + } + else { + System.out.println("!fred.equals(homer)"); + } + System.out.println("fred.hashCode() == " + fred.hashCode()); + System.out.println("homer.hashCode() == " + homer.hashCode()); + + if (fred.equals(homer)) { + throw new Exception("equals() failed on two hashtables that are not equal"); + } + + if (fred.hashCode() == homer.hashCode()) { + throw new Exception("hashCode() failed on two hashtables that are not equal"); + } + + System.out.println(); + System.out.println("testPatternEntry() passed.\n"); + } +} diff --git a/jdk/test/sun/text/IntHashtable/Bug4170614Test.sh b/jdk/test/sun/text/IntHashtable/Bug4170614Test.sh new file mode 100644 index 00000000000..b8dad0084a6 --- /dev/null +++ b/jdk/test/sun/text/IntHashtable/Bug4170614Test.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 4170614 +# @summary Test internal hashCode() functions +# + +set -x +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTSRC=${TESTSRC}" +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTJAVA=${TESTJAVA}" +if [ "${COMPILEJAVA}" = "" ]; then + COMPILEJAVA="${TESTJAVA}" +fi +echo "COMPILEJAVA=${COMPILEJAVA}" +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTCLASSES=${TESTCLASSES}" + +goback=`pwd` + +cd ${TESTSRC} + +TEST_JAVABASE=${TESTCLASSES}/java.base +mkdir -p ${TEST_JAVABASE} +${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ + -Xmodule:java.base \ + -d ${TEST_JAVABASE} Bug4170614Test.java + +${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:java.base=${TEST_JAVABASE} java.text.Bug4170614Test + +result=$? + +cd ${goback} + +if [ $result -eq 0 ] +then + echo "Passed" +else + echo "Failed" +fi +exit $result + + + diff --git a/jdk/test/sun/text/IntHashtable/Bug4705389.java b/jdk/test/sun/text/IntHashtable/Bug4705389.java new file mode 100644 index 00000000000..d2f6e49a829 --- /dev/null +++ b/jdk/test/sun/text/IntHashtable/Bug4705389.java @@ -0,0 +1,43 @@ +/* + * 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 4705389 + * @summary Make sure to find removed slots, which test case will be timed out without the fix. + * @modules java.base/sun.text + * @run main/timeout=10 Bug4705389 + */ + +import sun.text.IntHashtable; + +public class Bug4705389 { + public static void main(String args[]) { + IntHashtable table = new IntHashtable(); + for (int i = 1; i < 132; ++i) { + table.put(i, 0); + table.remove(i); + } + table.put(132, 0); + } +} diff --git a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java index afba30c6055..b0f3b8d4f73 100644 --- a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java +++ b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java @@ -31,9 +31,12 @@ * @run main BasicLauncherTest */ +import static jdk.testlibrary.Asserts.assertTrue; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Arrays; @@ -99,7 +102,7 @@ public class BasicLauncherTest { System.out.println("Starting LingeredApp"); try { - theApp = LingeredApp.startApp(); + theApp = LingeredApp.startApp(Arrays.asList("-Xmx256m")); System.out.println("Starting " + toolName + " " + toolArgs.get(0) + " against " + theApp.getPid()); JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(toolName); @@ -129,6 +132,21 @@ public class BasicLauncherTest { launch(expectedMessage, Arrays.asList(toolArgs)); } + public static void testHeapDump() throws IOException { + File dump = new File("jhsdb.jmap.dump." + + System.currentTimeMillis() + ".hprof"); + if (dump.exists()) { + dump.delete(); + } + dump.deleteOnExit(); + + launch("heap written to", "jmap", + "--binaryheap", "--dumpfile=" + dump.getAbsolutePath()); + + assertTrue(dump.exists() && dump.isFile(), + "Could not create dump file " + dump.getAbsolutePath()); + } + public static void main(String[] args) throws IOException { @@ -145,6 +163,8 @@ public class BasicLauncherTest { launch("Java System Properties", "jinfo"); launch("java.threads", "jsnap"); + testHeapDump(); + // The test throws RuntimeException on error. // IOException is thrown if LingeredApp can't start because of some bad // environment condition diff --git a/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java b/jdk/test/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java similarity index 98% rename from jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java rename to jdk/test/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java index 5a84b6261d6..c768dd6eb01 100644 --- a/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java +++ b/jdk/test/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java @@ -36,9 +36,9 @@ import jdk.testlibrary.Platform; * @test * @bug 8042397 * @summary Unit test for jmap utility test heap configuration reader + * @modules jdk.hotspot.agent/sun.jvm.hotspot * @library /test/lib/share/classes * @library /lib/testlibrary - * @modules java.management * @build jdk.testlibrary.* * @build jdk.test.lib.apps.* * @build JMapHeapConfigTest TmtoolTestScenario @@ -149,7 +149,7 @@ public class JMapHeapConfigTest { } cmd.add("-XX:+PrintFlagsFinal"); - TmtoolTestScenario tmt = TmtoolTestScenario.create("jmap", "-heap"); + TmtoolTestScenario tmt = TmtoolTestScenario.create("jmap", "--heap"); int exitcode = tmt.launch(cmd); if (exitcode != 0) { throw new RuntimeException("Test FAILED jmap exits with non zero exit code " + exitcode); diff --git a/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java b/jdk/test/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java similarity index 97% rename from jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java rename to jdk/test/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java index 4558f3e346b..25beea66f72 100644 --- a/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java +++ b/jdk/test/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java @@ -100,11 +100,13 @@ public class TmtoolTestScenario { theApp = LingeredApp.startApp(vmArgsExtended); System.out.println("Starting " + toolName + " against " + theApp.getPid()); - JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(toolName); + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); + launcher.addToolArg(toolName); for (String cmd : toolArgs) { launcher.addToolArg(cmd); } + launcher.addToolArg("--pid"); launcher.addToolArg(Long.toString(theApp.getPid())); ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); diff --git a/jdk/test/sun/tools/jinfo/JInfoHelper.java b/jdk/test/sun/tools/jinfo/BasicJInfoTest.java similarity index 51% rename from jdk/test/sun/tools/jinfo/JInfoHelper.java rename to jdk/test/sun/tools/jinfo/BasicJInfoTest.java index 7f945136b4f..c612652f46b 100644 --- a/jdk/test/sun/tools/jinfo/JInfoHelper.java +++ b/jdk/test/sun/tools/jinfo/BasicJInfoTest.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -29,41 +27,58 @@ import jdk.testlibrary.JDKToolLauncher; import jdk.testlibrary.OutputAnalyzer; import jdk.testlibrary.ProcessTools; -/** - * The helper class for running jinfo utility. +/* + * @test + * @summary Unit test for jinfo utility + * @library /lib/testlibrary + * @build jdk.testlibrary.* + * @run main BasicJInfoTest */ -public final class JInfoHelper { +public class BasicJInfoTest { - /** - * Print configuration information for the current process - * - * @param toolArgs List of jinfo options - */ - public static OutputAnalyzer jinfo(String... toolArgs) throws Exception { - return jinfo(true, toolArgs); + private static ProcessBuilder processBuilder = new ProcessBuilder(); + + public static void main(String[] args) throws Exception { + testJinfoNoArgs(); + testJinfoFlags(); + testJinfoProps(); + testJinfoFlagInvalid(); } - /** - * Print usage information - * - * @param toolArgs List of jinfo options - */ - public static OutputAnalyzer jinfoNoPid(String... toolArgs) throws Exception { - return jinfo(false, toolArgs); + private static void testJinfoNoArgs() throws Exception { + OutputAnalyzer output = jinfo(); + output.shouldContain("-XX"); + output.shouldContain("test.jdk="); + output.shouldHaveExitValue(0); } - private static OutputAnalyzer jinfo(boolean toPid, String... toolArgs) throws Exception { + private static void testJinfoFlagInvalid() throws Exception { + OutputAnalyzer output = jinfo("-flag"); + output.shouldHaveExitValue(1); + } + + private static void testJinfoFlags() throws Exception { + OutputAnalyzer output = jinfo("-flags"); + output.shouldContain("-XX"); + output.shouldHaveExitValue(0); + } + + private static void testJinfoProps() throws Exception { + OutputAnalyzer output = jinfo("-props"); + output.shouldContain("test.jdk="); + output.shouldHaveExitValue(0); + } + + private static OutputAnalyzer jinfo(String... toolArgs) throws Exception { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jinfo"); if (toolArgs != null) { for (String toolArg : toolArgs) { launcher.addToolArg(toolArg); } } - if (toPid) { - launcher.addToolArg(Long.toString(ProcessTools.getProcessId())); - } + launcher.addToolArg(Long.toString(ProcessTools.getProcessId())); - ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); + processBuilder.command(launcher.getCommand()); System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); System.out.println(output.getOutput()); diff --git a/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java b/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java deleted file mode 100644 index 09b4750d778..00000000000 --- a/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java +++ /dev/null @@ -1,343 +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. 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. - */ - -import org.testng.annotations.Test; -import org.testng.annotations.BeforeClass; -import sun.tools.jinfo.JInfo; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.Arrays; - -import static org.testng.Assert.*; - -/** - * @test - * @bug 8039080 - * @modules jdk.jcmd/sun.tools.jinfo - * @run testng JInfoLauncherTest - * @summary Test JInfo launcher argument parsing - */ -@Test -public class JInfoLauncherTest { - public static final String VALIDATION_EXCEPTION_CLSNAME = - IllegalArgumentException.class.getName(); - - private Constructor jInfoConstructor; - private Field fldUseSA; - - @BeforeClass - public void setup() throws Exception { - jInfoConstructor = JInfo.class.getDeclaredConstructor(String[].class); - jInfoConstructor.setAccessible(true); - fldUseSA = JInfo.class.getDeclaredField("useSA"); - fldUseSA.setAccessible(true); - } - - private JInfo newJInfo(String[] args) throws Exception { - try { - return jInfoConstructor.newInstance((Object) args); - } catch (Exception e) { - if (isValidationException(e.getCause())) { - throw (Exception)e.getCause(); - } - throw e; - } - } - - private boolean getUseSA(JInfo jinfo) throws Exception { - return fldUseSA.getBoolean(jinfo); - } - - private void cmdPID(String cmd, String ... params) throws Exception { - int offset = (cmd != null ? 1 : 0); - String[] args = new String[offset + params.length]; - args[0] = cmd; - System.arraycopy(params, 0, args, offset, params.length); - JInfo j = newJInfo(args); - assertFalse(getUseSA(j), "Local jinfo must not forward to SA"); - } - - private void cmdCore(String cmd, String ... params) throws Exception { - int offset = (cmd != null ? 1 : 0); - String[] args = new String[offset + params.length]; - args[0] = cmd; - System.arraycopy(params, 0, args, offset, params.length); - JInfo j = newJInfo(args); - assertTrue(getUseSA(j), "Core jinfo must forward to SA"); - } - - private void cmdRemote(String cmd, String ... params) throws Exception { - int offset = (cmd != null ? 1 : 0); - String[] args = new String[offset + params.length]; - args[0] = cmd; - System.arraycopy(params, 0, args, offset, params.length); - JInfo j = newJInfo(args); - assertTrue(getUseSA(j), "Remote jinfo must forward to SA"); - } - - private void cmdExtraArgs(String cmd, int argsLen) throws Exception { - String[] args = new String[argsLen + 1 + (cmd != null ? 1 : 0)]; - Arrays.fill(args, "a"); - if (cmd != null) { - args[0] = cmd; - } else { - cmd = "default"; - } - try { - JInfo j = newJInfo(args); - fail("\"" + cmd + "\" does not support more than " + argsLen + - " arguments"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - private void cmdMissingArgs(String cmd, int reqArgs) throws Exception { - String[] args = new String[reqArgs - 1 + (cmd != null ? 1 : 0)]; - Arrays.fill(args, "a"); - if (cmd != null) { - args[0] = cmd; - } else { - cmd = "default"; - } - try { - JInfo j = newJInfo(args); - fail("\"" + cmd + "\" requires at least " + reqArgs + " argument"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testDefaultPID() throws Exception { - cmdPID(null, "1234"); - } - - public void testFlagsPID() throws Exception { - cmdPID("-flags", "1234"); - } - - public void testSyspropsPID() throws Exception { - cmdPID("-sysprops", "1234"); - } - - public void testReadFlagPID() throws Exception { - cmdPID("-flag", "SomeManagementFlag", "1234"); - } - - public void testSetFlag1PID() throws Exception { - cmdPID("-flag", "+SomeManagementFlag", "1234"); - } - - public void testSetFlag2PID() throws Exception { - cmdPID("-flag", "-SomeManagementFlag", "1234"); - } - - public void testSetFlag3PID() throws Exception { - cmdPID("-flag", "SomeManagementFlag=314", "1234"); - } - - public void testDefaultCore() throws Exception { - cmdCore(null, "myapp.exe", "my.core"); - } - - public void testFlagsCore() throws Exception { - cmdCore("-flags", "myapp.exe", "my.core"); - } - - public void testSyspropsCore() throws Exception { - cmdCore("-sysprops", "myapp.exe", "my.core"); - } - - public void testReadFlagCore() throws Exception { - try { - cmdCore("-flag", "SomeManagementFlag", "myapp.exe", "my.core"); - fail("Flags can not be read from core files"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testSetFlag1Core() throws Exception { - try { - cmdCore("-flag", "+SomeManagementFlag", "myapp.exe", "my.core"); - fail("Flags can not be set in core files"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testSetFlag2Core() throws Exception { - try { - cmdCore("-flag", "-SomeManagementFlag", "myapp.exe", "my.core"); - fail("Flags can not be set in core files"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testSetFlag3Core() throws Exception { - try { - cmdCore("-flag", "SomeManagementFlag=314", "myapp.exe", "my.core"); - fail("Flags can not be set in core files"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testDefaultRemote() throws Exception { - cmdRemote(null, "serverid@host"); - } - - public void testFlagsRemote() throws Exception { - cmdRemote("-flags", "serverid@host"); - } - - public void testSyspropsRemote() throws Exception { - cmdRemote("-sysprops", "serverid@host"); - } - - public void testReadFlagRemote() throws Exception { - try { - cmdCore("-flag", "SomeManagementFlag", "serverid@host"); - fail("Flags can not be read from SA server"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testSetFlag1Remote() throws Exception { - try { - cmdCore("-flag", "+SomeManagementFlag","serverid@host"); - fail("Flags can not be set on SA server"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testSetFlag2Remote() throws Exception { - try { - cmdCore("-flag", "-SomeManagementFlag", "serverid@host"); - fail("Flags can not be read set on SA server"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testSetFlag3Remote() throws Exception { - try { - cmdCore("-flag", "SomeManagementFlag=314", "serverid@host"); - fail("Flags can not be read set on SA server"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - public void testDefaultExtraArgs() throws Exception { - cmdExtraArgs(null, 2); - } - - public void testFlagsExtraArgs() throws Exception { - cmdExtraArgs("-flags", 2); - } - - public void testSyspropsExtraArgs() throws Exception { - cmdExtraArgs("-sysprops", 2); - } - - public void testFlagExtraArgs() throws Exception { - cmdExtraArgs("-flag", 2); - } - - public void testHelp1ExtraArgs() throws Exception { - cmdExtraArgs("-h", 0); - } - - public void testHelp2ExtraArgs() throws Exception { - cmdExtraArgs("-help", 0); - } - - public void testDefaultMissingArgs() throws Exception { - cmdMissingArgs(null, 1); - } - - public void testFlagsMissingArgs() throws Exception { - cmdMissingArgs("-flags", 1); - } - - public void testSyspropsMissingArgs() throws Exception { - cmdMissingArgs("-sysprops", 1); - } - - public void testFlagMissingArgs() throws Exception { - cmdMissingArgs("-flag", 2); - } - - public void testUnknownCommand() throws Exception { - try { - JInfo j = newJInfo(new String[]{"-unknown_command"}); - fail("JInfo accepts unknown commands"); - } catch (Exception e) { - if (!isValidationException(e)) { - throw e; - } - // ignore - } - } - - private static boolean isValidationException(Throwable e) { - return e.getClass().getName().equals(VALIDATION_EXCEPTION_CLSNAME); - } -} diff --git a/jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java b/jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java deleted file mode 100644 index cb28cc7a49f..00000000000 --- a/jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ - -import java.lang.management.ManagementFactory; -import com.sun.management.HotSpotDiagnosticMXBean; -import jdk.testlibrary.OutputAnalyzer; -import static jdk.testlibrary.Platform.isSolaris; -import static jdk.testlibrary.Asserts.assertEquals; -import static jdk.testlibrary.Asserts.assertNotEquals; -import static jdk.testlibrary.Asserts.assertTrue; - -/** - * @test - * @summary The test sanity checks 'jinfo -flag' option. - * @library /lib/testlibrary - * @modules java.management - * @build jdk.testlibrary.* JInfoHelper - * @run main/othervm -XX:+HeapDumpOnOutOfMemoryError JInfoRunningProcessFlagTest - */ -public class JInfoRunningProcessFlagTest { - - public static void main(String[] args) throws Exception { - testFlag(); - testFlagPlus(); - testFlagMinus(); - testFlagEqual(); - - testInvalidFlag(); - - testSolarisSpecificFlag(); - } - - private static void testFlag() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError"); - output.shouldHaveExitValue(0); - assertTrue(output.getStderr().isEmpty(), "'jinfo -flag HeapDumpOnOutOfMemoryError' stderr should be empty"); - output.shouldContain("+HeapDumpOnOutOfMemoryError"); - } - - private static void testFlagPlus() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfo("-flag", "+HeapDumpOnOutOfMemoryError"); - output.shouldHaveExitValue(0); - output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError"); - output.shouldHaveExitValue(0); - output.shouldContain("+HeapDumpOnOutOfMemoryError"); - verifyIsEnabled("HeapDumpOnOutOfMemoryError"); - } - - private static void testFlagMinus() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfo("-flag", "-HeapDumpOnOutOfMemoryError"); - output.shouldHaveExitValue(0); - output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError"); - output.shouldHaveExitValue(0); - output.shouldContain("-HeapDumpOnOutOfMemoryError"); - verifyIsDisabled("HeapDumpOnOutOfMemoryError"); - } - - private static void testFlagEqual() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError=1"); - output.shouldHaveExitValue(0); - output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError"); - output.shouldHaveExitValue(0); - output.shouldContain("+HeapDumpOnOutOfMemoryError"); - verifyIsEnabled("HeapDumpOnOutOfMemoryError"); - } - - private static void testInvalidFlag() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfo("-flag", "monkey"); - assertNotEquals(output.getExitValue(), 0, "A non-zero exit code should be returned for invalid flag"); - } - - private static void testSolarisSpecificFlag() throws Exception { - if (!isSolaris()) - return; - - OutputAnalyzer output = JInfoHelper.jinfo("-flag", "+ExtendedDTraceProbes"); - output.shouldHaveExitValue(0); - output = JInfoHelper.jinfo(); - output.shouldContain("+ExtendedDTraceProbes"); - verifyIsEnabled("ExtendedDTraceProbes"); - - output = JInfoHelper.jinfo("-flag", "-ExtendedDTraceProbes"); - output.shouldHaveExitValue(0); - output = JInfoHelper.jinfo(); - output.shouldContain("-ExtendedDTraceProbes"); - verifyIsDisabled("ExtendedDTraceProbes"); - - output = JInfoHelper.jinfo("-flag", "ExtendedDTraceProbes"); - output.shouldContain("-ExtendedDTraceProbes"); - output.shouldHaveExitValue(0); - } - - private static void verifyIsEnabled(String flag) { - HotSpotDiagnosticMXBean hotspotDiagnostic = - ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); - String flagValue = hotspotDiagnostic.getVMOption(flag).getValue(); - assertEquals(flagValue, "true", "Expected '" + flag + "' flag be enabled"); - } - - private static void verifyIsDisabled(String flag) { - HotSpotDiagnosticMXBean hotspotDiagnostic = - ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); - String flagValue = hotspotDiagnostic.getVMOption(flag).getValue(); - assertEquals(flagValue, "false", "Expected '" + flag + "' flag be disabled"); - } - -} diff --git a/jdk/test/sun/tools/jinfo/JInfoRunningProcessTest.java b/jdk/test/sun/tools/jinfo/JInfoRunningProcessTest.java deleted file mode 100644 index 633a2c99b51..00000000000 --- a/jdk/test/sun/tools/jinfo/JInfoRunningProcessTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ - -import jdk.testlibrary.OutputAnalyzer; -import static jdk.testlibrary.Asserts.assertTrue; - -/** - * @test - * @summary The test sanity checks functionality of 'jinfo', 'jinfo -sysprops' and 'jinfo -flags' - * @library /lib/testlibrary - * @modules java.management - * @build jdk.testlibrary.* JInfoHelper - * @run main/othervm -XX:+HeapDumpOnOutOfMemoryError JInfoRunningProcessTest - */ -public class JInfoRunningProcessTest { - - public static void main(String[] args) throws Exception { - testNoOptions(); - testSysprops(); - testFlags(); - } - - private static void testNoOptions() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfo(); - output.shouldHaveExitValue(0); - assertTrue(output.getStderr().isEmpty(), "'jinfo' stderr should be empty"); - output.shouldContain("+HeapDumpOnOutOfMemoryError"); - } - - private static void testSysprops() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfo("-sysprops"); - output.shouldHaveExitValue(0); - assertTrue(output.getStderr().isEmpty(), "'jinfo -sysprops' stderr should be empty"); - } - - private static void testFlags() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfo("-flags"); - output.shouldHaveExitValue(0); - assertTrue(output.getStderr().isEmpty(), "'jinfo -flags' stderr should be empty"); - output.shouldContain("+HeapDumpOnOutOfMemoryError"); - } - -} diff --git a/jdk/test/sun/tools/jinfo/JInfoSanityTest.java b/jdk/test/sun/tools/jinfo/JInfoSanityTest.java deleted file mode 100644 index 9b0bcf1b141..00000000000 --- a/jdk/test/sun/tools/jinfo/JInfoSanityTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ - -import static jdk.testlibrary.Asserts.assertNotEquals; -import static jdk.testlibrary.Asserts.assertTrue; -import static jdk.testlibrary.Asserts.assertFalse; -import jdk.testlibrary.OutputAnalyzer; - -/** - * @test - * @summary The test sanity checks functionality of 'jinfo -h', 'jinfo -help', - * and verifies jinfo exits abnormally if started with invalid options. - * @library /lib/testlibrary - * @modules java.management - * @build jdk.testlibrary.* JInfoHelper - * @run main JInfoSanityTest - */ -public class JInfoSanityTest { - - public static void main(String[] args) throws Exception { - test_h(); - test_help(); - testVersion(); - testUnknownHost(); - } - - private static void test_h() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfoNoPid("-h"); - output.shouldHaveExitValue(0); - assertFalse(output.getStderr().isEmpty(), "'jinfo -h' stderr should not be empty"); - assertTrue(output.getStdout().isEmpty(), "'jinfo -h' stdout should be empty"); - } - - private static void test_help() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfoNoPid("-help"); - output.shouldHaveExitValue(0); - assertFalse(output.getStderr().isEmpty(), "'jinfo -help' stderr should not be empty"); - assertTrue(output.getStdout().isEmpty(), "'jinfo -help' stdout should be empty"); - } - - private static void testVersion() throws Exception { - OutputAnalyzer output = JInfoHelper.jinfoNoPid("-version"); - output.shouldHaveExitValue(1); - assertFalse(output.getStderr().isEmpty(), "'jinfo -version' stderr should not be empty"); - assertTrue(output.getStdout().isEmpty(), "'jinfo -version' stdout should be empty"); - } - - private static void testUnknownHost() throws Exception { - String unknownHost = "Oja781nh2ev7vcvbajdg-Sda1-C"; - OutputAnalyzer output = JInfoHelper.jinfoNoPid("med@" + unknownHost); - assertNotEquals(output.getExitValue(), 0, "A non-zero exit code should be returned for invalid operation"); - output.shouldMatch(".*(Connection refused to host\\:|UnknownHostException\\:) " + unknownHost + ".*"); - } - -} diff --git a/jdk/test/sun/tools/jmap/BasicJMapTest.java b/jdk/test/sun/tools/jmap/BasicJMapTest.java index 75c80a2eec3..fa333cddea7 100644 --- a/jdk/test/sun/tools/jmap/BasicJMapTest.java +++ b/jdk/test/sun/tools/jmap/BasicJMapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -34,12 +34,10 @@ import jdk.testlibrary.ProcessTools; /* * @test - * @bug 6321286 * @summary Unit test for jmap utility * @key intermittent * @library /lib/testlibrary * @library /test/lib/share/classes - * @modules java.management * @build jdk.testlibrary.* * @build jdk.test.lib.hprof.* * @build jdk.test.lib.hprof.model.* @@ -54,6 +52,8 @@ public class BasicJMapTest { public static void main(String[] args) throws Exception { testHisto(); testHistoLive(); + testFinalizerInfo(); + testClstats(); testDump(); testDumpLive(); } @@ -68,6 +68,16 @@ public class BasicJMapTest { output.shouldHaveExitValue(0); } + private static void testFinalizerInfo() throws Exception { + OutputAnalyzer output = jmap("-finalizerinfo"); + output.shouldHaveExitValue(0); + } + + private static void testClstats() throws Exception { + OutputAnalyzer output = jmap("-clstats"); + output.shouldHaveExitValue(0); + } + private static void testDump() throws Exception { dump(false); } @@ -105,7 +115,6 @@ public class BasicJMapTest { private static OutputAnalyzer jmap(String... toolArgs) throws Exception { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jmap"); - launcher.addVMArg("-XX:+UsePerfData"); if (toolArgs != null) { for (String toolArg : toolArgs) { launcher.addToolArg(toolArg); diff --git a/jdk/test/sun/tools/jstack/BasicJStackTest.java b/jdk/test/sun/tools/jstack/BasicJStackTest.java index 9fd0b66b578..997876a54c5 100644 --- a/jdk/test/sun/tools/jstack/BasicJStackTest.java +++ b/jdk/test/sun/tools/jstack/BasicJStackTest.java @@ -29,10 +29,8 @@ import jdk.testlibrary.ProcessTools; /* * @test - * @bug 6260070 * @summary Unit test for jstack utility * @library /lib/testlibrary - * @modules java.management * @build jdk.testlibrary.* * @run main BasicJStackTest */ diff --git a/jdk/test/sun/tools/jstack/DeadlockDetectionTest.java b/jdk/test/sun/tools/jstack/DeadlockDetectionTest.java index 4ff2508673b..771fd128ff7 100644 --- a/jdk/test/sun/tools/jstack/DeadlockDetectionTest.java +++ b/jdk/test/sun/tools/jstack/DeadlockDetectionTest.java @@ -39,7 +39,6 @@ import jdk.testlibrary.ProcessTools; * @summary Test deadlock detection * @library /test/lib/share/classes * @library /lib/testlibrary - * @modules java.management * @build jdk.testlibrary.* * @build jdk.test.lib.apps.* * @build DeadlockDetectionTest diff --git a/jdk/test/sun/util/logging/PlatformLoggerTest.java b/jdk/test/sun/util/logging/PlatformLoggerTest.java index 530a2acea8a..4fbf0c95c2d 100644 --- a/jdk/test/sun/util/logging/PlatformLoggerTest.java +++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java @@ -31,7 +31,6 @@ * * @modules java.base/sun.util.logging * java.logging/sun.util.logging.internal - * @compile -XDignore.symbol.file PlatformLoggerTest.java * @run main/othervm PlatformLoggerTest */ @@ -42,25 +41,31 @@ import sun.util.logging.PlatformLogger; import static sun.util.logging.PlatformLogger.Level.*; public class PlatformLoggerTest { + + static Logger logger; + static PlatformLogger bar; + static PlatformLogger goo; + static PlatformLogger foo; + public static void main(String[] args) throws Exception { final String FOO_PLATFORM_LOGGER = "test.platformlogger.foo"; final String BAR_PLATFORM_LOGGER = "test.platformlogger.bar"; final String GOO_PLATFORM_LOGGER = "test.platformlogger.goo"; final String BAR_LOGGER = "test.logger.bar"; - PlatformLogger goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER); + goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER); // test the PlatformLogger methods testLogMethods(goo); // Create a platform logger using the default - PlatformLogger foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER); + foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER); checkPlatformLogger(foo, FOO_PLATFORM_LOGGER); // create a java.util.logging.Logger // now java.util.logging.Logger should be created for each platform logger - Logger logger = Logger.getLogger(BAR_LOGGER); + logger = Logger.getLogger(BAR_LOGGER); logger.setLevel(Level.WARNING); - PlatformLogger bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER); + bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER); checkPlatformLogger(bar, BAR_PLATFORM_LOGGER); // test the PlatformLogger methods diff --git a/jdk/test/sun/util/logging/SourceClassName.java b/jdk/test/sun/util/logging/SourceClassName.java index 0de431a1a20..f3023122618 100644 --- a/jdk/test/sun/util/logging/SourceClassName.java +++ b/jdk/test/sun/util/logging/SourceClassName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * logger. * * @modules java.base/sun.util.logging + * java.logging * @compile -XDignore.symbol.file SourceClassName.java * @run main/othervm SourceClassName */ diff --git a/jdk/test/tools/jar/modularJar/Basic.java b/jdk/test/tools/jar/modularJar/Basic.java index 417f71a2f5e..4ce94a24b56 100644 --- a/jdk/test/tools/jar/modularJar/Basic.java +++ b/jdk/test/tools/jar/modularJar/Basic.java @@ -33,6 +33,7 @@ import java.util.*; import java.util.function.Consumer; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; +import java.util.jar.Manifest; import java.util.regex.Pattern; import java.util.stream.Stream; import javax.tools.JavaCompiler; @@ -52,45 +53,64 @@ import static java.lang.System.out; /* * @test * @library /lib/testlibrary + * @modules jdk.compiler + * jdk.jartool * @build jdk.testlibrary.FileUtils jdk.testlibrary.JDKToolFinder * @compile Basic.java * @run testng Basic - * @summary Basic test for Modular jars + * @summary Tests for plain Modular jars & Multi-Release Modular jars */ public class Basic { static final Path TEST_SRC = Paths.get(System.getProperty("test.src", ".")); static final Path TEST_CLASSES = Paths.get(System.getProperty("test.classes", ".")); static final Path MODULE_CLASSES = TEST_CLASSES.resolve("build"); + static final Path MRJAR_DIR = MODULE_CLASSES.resolve("mrjar"); // Details based on the checked in module source static TestModuleData FOO = new TestModuleData("foo", "1.123", "jdk.test.foo.Foo", - "Hello World!!!", null, - "jdk.test.foo.internal"); + "Hello World!!!", + null, // no hashes + Set.of("java.base"), + Set.of("jdk.test.foo"), + null, // no uses + null, // no provides + Set.of("jdk.test.foo.internal")); static TestModuleData BAR = new TestModuleData("bar", "4.5.6.7", "jdk.test.bar.Bar", - "Hello from Bar!", null, - "jdk.test.bar", - "jdk.test.bar.internal"); + "Hello from Bar!", + null, // no hashes + Set.of("java.base", "foo"), + null, // no exports + null, // no uses + null, // no provides + Set.of("jdk.test.bar", + "jdk.test.bar.internal")); static class TestModuleData { final String moduleName; + final Set requires; + final Set exports; + final Set uses; + final Set provides; final String mainClass; final String version; final String message; final String hashes; final Set conceals; - TestModuleData(String mn, String v, String mc, String m, String h, String... pkgs) { + + TestModuleData(String mn, String v, String mc, String m, String h, + Set requires, Set exports, Set uses, + Set provides, Set conceals) { moduleName = mn; mainClass = mc; version = v; message = m; hashes = h; - conceals = new HashSet<>(); - Stream.of(pkgs).forEach(conceals::add); - } - TestModuleData(String mn, String v, String mc, String m, String h, Set pkgs) { - moduleName = mn; mainClass = mc; version = v; message = m; hashes = h; - conceals = pkgs; + this.requires = requires; + this.exports = exports; + this.uses = uses; + this.provides = provides; + this.conceals = conceals; } static TestModuleData from(String s) { try { @@ -99,7 +119,8 @@ public class Basic { String message = null; String name = null, version = null, mainClass = null; String hashes = null; - Set conceals = null; + Set requires, exports, uses, provides, conceals; + requires = exports = uses = provides = conceals = null; while ((line = reader.readLine()) != null) { if (line.startsWith("message:")) { message = line.substring("message:".length()); @@ -114,28 +135,46 @@ public class Basic { } } else if (line.startsWith("mainClass:")) { mainClass = line.substring("mainClass:".length()); + } else if (line.startsWith("requires:")) { + line = line.substring("requires:".length()); + requires = stringToSet(line); + } else if (line.startsWith("exports:")) { + line = line.substring("exports:".length()); + exports = stringToSet(line); + } else if (line.startsWith("uses:")) { + line = line.substring("uses:".length()); + uses = stringToSet(line); + } else if (line.startsWith("provides:")) { + line = line.substring("provides:".length()); + provides = stringToSet(line); } else if (line.startsWith("hashes:")) { hashes = line.substring("hashes:".length()); - } else if (line.startsWith("conceals:")) { + } else if (line.startsWith("conceals:")) { line = line.substring("conceals:".length()); - conceals = new HashSet<>(); - int i = line.indexOf(','); - if (i != -1) { - String[] p = line.split(","); - Stream.of(p).forEach(conceals::add); - } else { - conceals.add(line); - } + conceals = stringToSet(line); } else { throw new AssertionError("Unknown value " + line); } } - return new TestModuleData(name, version, mainClass, message, hashes, conceals); + return new TestModuleData(name, version, mainClass, message, + hashes, requires, exports, uses, + provides, conceals); } catch (IOException x) { throw new UncheckedIOException(x); } } + static Set stringToSet(String commaList) { + Set s = new HashSet<>(); + int i = commaList.indexOf(','); + if (i != -1) { + String[] p = commaList.split(","); + Stream.of(p).forEach(s::add); + } else { + s.add(commaList); + } + return s; + } } static void assertModuleData(Result r, TestModuleData expected) { @@ -150,10 +189,19 @@ public class Basic { "Expected version: ", expected.version, ", got:", received.version); assertTrue(expected.mainClass.equals(received.mainClass), "Expected mainClass: ", expected.mainClass, ", got:", received.mainClass); - expected.conceals.forEach(p -> assertTrue(received.conceals.contains(p), - "Expected ", p, ", in ", received.conceals)); - received.conceals.forEach(p -> assertTrue(expected.conceals.contains(p), - "Expected ", p, ", in ", expected.conceals)); + assertSetsEqual(expected.requires, received.requires); + assertSetsEqual(expected.exports, received.exports); + assertSetsEqual(expected.uses, received.uses); + assertSetsEqual(expected.provides, received.provides); + assertSetsEqual(expected.conceals, received.conceals); + } + + static void assertSetsEqual(Set s1, Set s2) { + if (s1 == null && s2 == null) // none expected, or received + return; + assertTrue(s1.size() == s2.size(), + "Unexpected set size difference: ", s1.size(), ", ", s2.size()); + s1.forEach(p -> assertTrue(s2.contains(p), "Expected ", p, ", in ", s2)); } @BeforeTest @@ -161,6 +209,10 @@ public class Basic { compileModule(FOO.moduleName); compileModule(BAR.moduleName, MODULE_CLASSES); compileModule("baz"); // for service provider consistency checking + + setupMRJARModuleInfo(FOO.moduleName); + setupMRJARModuleInfo(BAR.moduleName); + setupMRJARModuleInfo("baz"); } @Test @@ -180,7 +232,6 @@ public class Basic { java(mp, FOO.moduleName + "/" + FOO.mainClass) .assertSuccess() .resultChecker(r -> assertModuleData(r, FOO)); - try (InputStream fis = Files.newInputStream(modularJar); JarInputStream jis = new JarInputStream(fis)) { assertTrue(!jarContains(jis, "./"), @@ -188,6 +239,30 @@ public class Basic { } } + /** Similar to createFoo, but with a Multi-Release Modular jar. */ + @Test + public void createMRMJarFoo() throws IOException { + Path mp = Paths.get("createMRMJarFoo"); + createTestDir(mp); + Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName); + Path mrjarDir = MRJAR_DIR.resolve(FOO.moduleName); + Path modularJar = mp.resolve(FOO.moduleName + ".jar"); + + // Positive test, create + jar("--create", + "--file=" + modularJar.toString(), + "--main-class=" + FOO.mainClass, + "--module-version=" + FOO.version, + "-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(), + "-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class", + "-C", modClasses.toString(), ".") + .assertSuccess(); + java(mp, FOO.moduleName + "/" + FOO.mainClass) + .assertSuccess() + .resultChecker(r -> assertModuleData(r, FOO)); + } + + @Test public void updateFoo() throws IOException { Path mp = Paths.get("updateFoo"); @@ -212,6 +287,32 @@ public class Basic { .resultChecker(r -> assertModuleData(r, FOO)); } + @Test + public void updateMRMJarFoo() throws IOException { + Path mp = Paths.get("updateMRMJarFoo"); + createTestDir(mp); + Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName); + Path mrjarDir = MRJAR_DIR.resolve(FOO.moduleName); + Path modularJar = mp.resolve(FOO.moduleName + ".jar"); + + jar("--create", + "--file=" + modularJar.toString(), + "--no-manifest", + "-C", modClasses.toString(), "jdk") + .assertSuccess(); + jar("--update", + "--file=" + modularJar.toString(), + "--main-class=" + FOO.mainClass, + "--module-version=" + FOO.version, + "-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(), + "-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class", + "-C", modClasses.toString(), "module-info.class") + .assertSuccess(); + java(mp, FOO.moduleName + "/" + FOO.mainClass) + .assertSuccess() + .resultChecker(r -> assertModuleData(r, FOO)); + } + @Test public void partialUpdateFooMainClass() throws IOException { Path mp = Paths.get("partialUpdateFooMainClass"); @@ -289,6 +390,30 @@ public class Basic { .resultChecker(r -> assertModuleData(r, FOO)); } + @Test + public void partialUpdateMRMJarFooNotAllFiles() throws IOException { + Path mp = Paths.get("partialUpdateMRMJarFooNotAllFiles"); + createTestDir(mp); + Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName); + Path mrjarDir = MRJAR_DIR.resolve(FOO.moduleName); + Path modularJar = mp.resolve(FOO.moduleName + ".jar"); + + jar("--create", + "--file=" + modularJar.toString(), + "--module-version=" + FOO.version, + "-C", modClasses.toString(), ".") + .assertSuccess(); + jar("--update", + "--file=" + modularJar.toString(), + "--main-class=" + FOO.mainClass, + "-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(), + "-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class") + .assertSuccess(); + java(mp, FOO.moduleName + "/" + FOO.mainClass) + .assertSuccess() + .resultChecker(r -> assertModuleData(r, FOO)); + } + @Test public void partialUpdateFooAllFilesAndAttributes() throws IOException { Path mp = Paths.get("partialUpdateFooAllFilesAndAttributes"); @@ -527,6 +652,24 @@ public class Basic { .assertFailure(); } + @Test + public void servicesCreateWithoutFailureMRMJAR() throws IOException { + Path mp = Paths.get("servicesCreateWithoutFailureMRMJAR"); + createTestDir(mp); + Path modClasses = MODULE_CLASSES.resolve("baz"); + Path mrjarDir = MRJAR_DIR.resolve("baz"); + Path modularJar = mp.resolve("baz" + ".jar"); + + jar("--create", + "--file=" + modularJar.toString(), + "-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(), + "-C", modClasses.toString(), "module-info.class", + "-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class", + "-C", modClasses.toString(), "jdk/test/baz/BazService.class", + "-C", modClasses.toString(), "jdk/test/baz/internal/BazServiceImpl.class") + .assertSuccess(); + } + @Test public void printModuleDescriptorFoo() throws IOException { Path mp = Paths.get("printModuleDescriptorFoo"); @@ -611,6 +754,24 @@ public class Basic { return build; } + static void setupMRJARModuleInfo(String moduleName) throws IOException { + Path modClasses = MODULE_CLASSES.resolve(moduleName); + Path metaInfDir = MRJAR_DIR.resolve(moduleName).resolve("META-INF"); + Path versionSection = metaInfDir.resolve("versions").resolve("9"); + createTestDir(versionSection); + + Path versionModuleInfo = versionSection.resolve("module-info.class"); + System.out.println("copying " + modClasses.resolve("module-info.class") + " to " + versionModuleInfo); + Files.copy(modClasses.resolve("module-info.class"), versionModuleInfo); + + Manifest manifest = new Manifest(); + manifest.getMainAttributes().putValue("Manifest-Version", "1.0"); + manifest.getMainAttributes().putValue("Multi-Release", "true"); + try (OutputStream os = Files.newOutputStream(metaInfDir.resolve("MANIFEST.MF"))) { + manifest.write(os); + } + } + // Re-enable when there is support in javax.tools for module path // static void javac(Path dest, Path... sourceFiles) throws IOException { // out.printf("Compiling %d source files %s%n", sourceFiles.length, @@ -690,7 +851,7 @@ public class Basic { static void createTestDir(Path p) throws IOException{ if (Files.exists(p)) FileUtils.deleteFileTreeWithRetry(p); - Files.createDirectory(p); + Files.createDirectories(p); } static boolean jarContains(JarInputStream jis, String entryName) diff --git a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java index 181491ab601..5267814d711 100644 --- a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java +++ b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -26,6 +24,8 @@ package jdk.test.bar; import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleDescriptor.Exports; +import java.lang.module.ModuleDescriptor.Requires; import java.lang.reflect.Method; import java.util.Optional; import java.util.StringJoiner; @@ -39,18 +39,36 @@ public class Bar { ModuleDescriptor md = Bar.class.getModule().getDescriptor(); System.out.println("nameAndVersion:" + md.toNameAndVersion()); - System.out.println("mainClass:" + md.mainClass().get()); + md.mainClass().ifPresent(mc -> System.out.println("mainClass:" + mc)); + + StringJoiner sj = new StringJoiner(","); + md.requires().stream().map(ModuleDescriptor.Requires::name).sorted().forEach(sj::add); + System.out.println("requires:" + sj.toString()); + + sj = new StringJoiner(","); + md.exports().stream().map(ModuleDescriptor.Exports::source).sorted().forEach(sj::add); + if (!sj.toString().equals("")) + System.out.println("exports:" + sj.toString()); + + sj = new StringJoiner(","); + md.uses().stream().sorted().forEach(sj::add); + if (!sj.toString().equals("")) + System.out.println("uses:" + sj.toString()); + + sj = new StringJoiner(","); + md.provides().keySet().stream().sorted().forEach(sj::add); + if (!sj.toString().equals("")) + System.out.println("provides:" + sj.toString()); + + sj = new StringJoiner(","); + md.conceals().forEach(sj::add); + if (!sj.toString().equals("")) + System.out.println("conceals:" + sj.toString()); Method m = ModuleDescriptor.class.getDeclaredMethod("hashes"); m.setAccessible(true); ModuleDescriptor foo = jdk.test.foo.Foo.class.getModule().getDescriptor(); - Optional oHashes = - (Optional) m.invoke(foo); - + Optional oHashes = (Optional) m.invoke(foo); System.out.println("hashes:" + oHashes.get().hashFor("bar")); - - StringJoiner sj = new StringJoiner(","); - md.conceals().forEach(sj::add); - System.out.println("conceals:" + sj.toString()); } } diff --git a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/internal/Message.java b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/internal/Message.java index 17cbe3a1a03..fe8698d2e06 100644 --- a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/internal/Message.java +++ b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/internal/Message.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/jdk/test/tools/jar/modularJar/src/bar/module-info.java b/jdk/test/tools/jar/modularJar/src/bar/module-info.java index 72965186eb4..84480e25920 100644 --- a/jdk/test/tools/jar/modularJar/src/bar/module-info.java +++ b/jdk/test/tools/jar/modularJar/src/bar/module-info.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/BazService.java b/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/BazService.java index 85c585fb898..c4432047267 100644 --- a/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/BazService.java +++ b/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/BazService.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/internal/BazServiceImpl.java b/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/internal/BazServiceImpl.java index 5f41732642d..fba16b7e89f 100644 --- a/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/internal/BazServiceImpl.java +++ b/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/internal/BazServiceImpl.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/jdk/test/tools/jar/modularJar/src/baz/module-info.java b/jdk/test/tools/jar/modularJar/src/baz/module-info.java index 8a35edb0bcc..5672f74866f 100644 --- a/jdk/test/tools/jar/modularJar/src/baz/module-info.java +++ b/jdk/test/tools/jar/modularJar/src/baz/module-info.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java index 1cb35351b86..3e0ce9fa601 100644 --- a/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java +++ b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -26,6 +24,8 @@ package jdk.test.foo; import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleDescriptor.Exports; +import java.lang.module.ModuleDescriptor.Requires; import java.util.StringJoiner; import jdk.test.foo.internal.Message; @@ -36,10 +36,30 @@ public class Foo { ModuleDescriptor md = Foo.class.getModule().getDescriptor(); System.out.println("nameAndVersion:" + md.toNameAndVersion()); - System.out.println("mainClass:" + md.mainClass().get()); + md.mainClass().ifPresent(mc -> System.out.println("mainClass:" + mc)); StringJoiner sj = new StringJoiner(","); + md.requires().stream().map(Requires::name).sorted().forEach(sj::add); + System.out.println("requires:" + sj.toString()); + + sj = new StringJoiner(","); + md.exports().stream().map(Exports::source).sorted().forEach(sj::add); + if (!sj.toString().equals("")) + System.out.println("exports:" + sj.toString()); + + sj = new StringJoiner(","); + md.uses().stream().sorted().forEach(sj::add); + if (!sj.toString().equals("")) + System.out.println("uses:" + sj.toString()); + + sj = new StringJoiner(","); + md.provides().keySet().stream().sorted().forEach(sj::add); + if (!sj.toString().equals("")) + System.out.println("provides:" + sj.toString()); + + sj = new StringJoiner(","); md.conceals().forEach(sj::add); - System.out.println("conceals:" + sj.toString()); + if (!sj.toString().equals("")) + System.out.println("conceals:" + sj.toString()); } } diff --git a/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/internal/Message.java b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/internal/Message.java index 298a4fce0cb..a5959e8755a 100644 --- a/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/internal/Message.java +++ b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/internal/Message.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/jdk/test/tools/jar/modularJar/src/foo/module-info.java b/jdk/test/tools/jar/modularJar/src/foo/module-info.java index b46afa0b822..7f3e0f7cc0a 100644 --- a/jdk/test/tools/jar/modularJar/src/foo/module-info.java +++ b/jdk/test/tools/jar/modularJar/src/foo/module-info.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/jdk/test/tools/jimage/VerifyJimage.java b/jdk/test/tools/jimage/VerifyJimage.java index 9c33cc3fa74..5056e6322a5 100644 --- a/jdk/test/tools/jimage/VerifyJimage.java +++ b/jdk/test/tools/jimage/VerifyJimage.java @@ -188,7 +188,11 @@ public class VerifyJimage { String cn = removeModule(n).replaceAll("\\.class$", "").replace('/', '.'); count.incrementAndGet(); try { + System.out.println("Loading " + cn); Class.forName(cn, false, loader); + } catch (VerifyError ve) { + System.err.println("VerifyError for " + cn); + failed.add(reader.imageName() + ": " + cn + " not verified: " + ve.getMessage()); } catch (ClassNotFoundException e) { failed.add(reader.imageName() + ": " + cn + " not found"); } diff --git a/jdk/test/tools/jlink/DefaultProviderTest.java b/jdk/test/tools/jlink/DefaultProviderTest.java index 22c68287d5c..c10e9d37060 100644 --- a/jdk/test/tools/jlink/DefaultProviderTest.java +++ b/jdk/test/tools/jlink/DefaultProviderTest.java @@ -33,7 +33,7 @@ import java.util.Set; import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.PluginException; -import jdk.tools.jlink.plugin.Pool; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; import tests.Helper; @@ -65,26 +65,26 @@ public class DefaultProviderTest { private boolean enabled = true; @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.TRANSFORMER); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.TRANSFORMER); return Collections.unmodifiableSet(set); } @Override - public Set getState() { - return enabled ? EnumSet.of(STATE.AUTO_ENABLED, STATE.FUNCTIONAL) - : EnumSet.of(STATE.DISABLED); + public Set getState() { + return enabled ? EnumSet.of(State.AUTO_ENABLED, State.FUNCTIONAL) + : EnumSet.of(State.DISABLED); } @Override - public void visit(Pool in, Pool out) { + public void visit(ModulePool in, ModulePool out) { if (!enabled) { throw new PluginException(NAME + " was set"); } DefaultProviderTest.isNewPluginsCalled = true; - in.visit((Pool.ModuleData content) -> { + in.transformAndCopy(content -> { return content; }, out); } diff --git a/jdk/test/tools/jlink/ImageFileCreatorTest.java b/jdk/test/tools/jlink/ImageFileCreatorTest.java index 449d950d04d..8e093c69459 100644 --- a/jdk/test/tools/jlink/ImageFileCreatorTest.java +++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java @@ -39,7 +39,7 @@ import jdk.tools.jlink.internal.ImageFileCreator; import jdk.tools.jlink.internal.ImagePluginStack; import jdk.tools.jlink.plugin.ExecutableImage; import jdk.tools.jlink.builder.ImageBuilder; -import jdk.tools.jlink.plugin.Pool; +import jdk.tools.jlink.plugin.ModulePool; /* @@ -47,6 +47,7 @@ import jdk.tools.jlink.plugin.Pool; * @summary ImageFileCreator class test * @author Jean-Francois Denise * @modules jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jlink.builder * java.base/jdk.internal.jimage * @run main/othervm -verbose:gc -Xmx1g ImageFileCreatorTest */ @@ -214,7 +215,7 @@ public class ImageFileCreatorTest { } @Override - public void storeFiles(Pool content) { + public void storeFiles(ModulePool content) { } }; diff --git a/jdk/test/tools/jlink/ImageFilePoolTest.java b/jdk/test/tools/jlink/ImageFilePoolTest.java index 7d35f9da8d6..1ea0fada3d7 100644 --- a/jdk/test/tools/jlink/ImageFilePoolTest.java +++ b/jdk/test/tools/jlink/ImageFilePoolTest.java @@ -31,11 +31,12 @@ */ import java.io.ByteArrayInputStream; -import jdk.tools.jlink.internal.PoolImpl; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; -import jdk.tools.jlink.plugin.Pool.ModuleDataType; -import jdk.tools.jlink.plugin.Pool.Visitor; +import java.util.Optional; +import java.util.function.Function; +import jdk.tools.jlink.internal.ModuleEntryImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class ImageFilePoolTest { public static void main(String[] args) throws Exception { @@ -50,45 +51,45 @@ public class ImageFilePoolTest { private static final String SUFFIX = "END"; private void checkVisitor() throws Exception { - Pool input = new PoolImpl(); + ModulePool input = new ModulePoolImpl(); for (int i = 0; i < 1000; ++i) { String module = "module" + (i / 100); input.add(new InMemoryImageFile(module, "/" + module + "/java/class" + i, - ModuleDataType.CONFIG, "class" + i)); + ModuleEntry.Type.CONFIG, "class" + i)); } - if (input.getContent().size() != 1000) { + if (input.getEntryCount() != 1000) { throw new AssertionError(); } - Pool output = new PoolImpl(); + ModulePool output = new ModulePoolImpl(); ResourceVisitor visitor = new ResourceVisitor(); - input.visit(visitor, output); + input.transformAndCopy(visitor, output); if (visitor.getAmountBefore() == 0) { throw new AssertionError("Resources not found"); } - if (visitor.getAmountBefore() != input.getContent().size()) { + if (visitor.getAmountBefore() != input.getEntryCount()) { throw new AssertionError("Number of visited resources. Expected: " + - visitor.getAmountBefore() + ", got: " + input.getContent().size()); + visitor.getAmountBefore() + ", got: " + input.getEntryCount()); } - if (visitor.getAmountAfter() != output.getContent().size()) { + if (visitor.getAmountAfter() != output.getEntryCount()) { throw new AssertionError("Number of added resources. Expected: " + - visitor.getAmountAfter() + ", got: " + output.getContent().size()); + visitor.getAmountAfter() + ", got: " + output.getEntryCount()); } - for (ModuleData outFile : output.getContent()) { + output.entries().forEach(outFile -> { String path = outFile.getPath().replaceAll(SUFFIX + "$", ""); - ModuleData inFile = input.get(path); - if (inFile == null) { + Optional inFile = input.findEntry(path); + if (!inFile.isPresent()) { throw new AssertionError("Unknown resource: " + path); } - } + }); } - private static class ResourceVisitor implements Visitor { + private static class ResourceVisitor implements Function { private int amountBefore; private int amountAfter; @Override - public ModuleData visit(ModuleData file) { + public ModuleEntry apply(ModuleEntry file) { int index = ++amountBefore % 3; switch (index) { case 0: @@ -113,7 +114,7 @@ public class ImageFilePoolTest { } private void checkNegative() throws Exception { - PoolImpl input = new PoolImpl(); + ModulePoolImpl input = new ModulePoolImpl(); try { input.add(null); throw new AssertionError("NullPointerException is not thrown"); @@ -126,30 +127,30 @@ public class ImageFilePoolTest { } catch (NullPointerException e) { // expected } - if (input.get("unknown") != null) { - throw new AssertionError("ImageFilePool does not return null for unknown file"); + if (input.findEntry("unknown").isPresent()) { + throw new AssertionError("ImageFileModulePool does not return null for unknown file"); } - if (input.contains(new InMemoryImageFile("", "unknown", ModuleDataType.CONFIG, "unknown"))) { + if (input.contains(new InMemoryImageFile("", "unknown", ModuleEntry.Type.CONFIG, "unknown"))) { throw new AssertionError("'contain' returns true for unknown file"); } - input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleDataType.CONFIG, "")); + input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleEntry.Type.CONFIG, "")); try { - input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleDataType.CONFIG, "")); + input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleEntry.Type.CONFIG, "")); throw new AssertionError("Exception expected"); } catch (Exception e) { // expected } input.setReadOnly(); try { - input.add(new InMemoryImageFile("", "/aaa/ccc", ModuleDataType.CONFIG, "")); + input.add(new InMemoryImageFile("", "/aaa/ccc", ModuleEntry.Type.CONFIG, "")); throw new AssertionError("Exception expected"); } catch (Exception e) { // expected } } - private static class InMemoryImageFile extends ModuleData { - public InMemoryImageFile(String module, String path, ModuleDataType type, String content) { + private static class InMemoryImageFile extends ModuleEntryImpl { + public InMemoryImageFile(String module, String path, ModuleEntry.Type type, String content) { super(module, path, type, new ByteArrayInputStream(content.getBytes()), content.getBytes().length); } } diff --git a/jdk/test/tools/jlink/IntegrationTest.java b/jdk/test/tools/jlink/IntegrationTest.java index 951c16cff74..e5637b421a8 100644 --- a/jdk/test/tools/jlink/IntegrationTest.java +++ b/jdk/test/tools/jlink/IntegrationTest.java @@ -39,7 +39,7 @@ import jdk.tools.jlink.Jlink.JlinkConfiguration; import jdk.tools.jlink.Jlink.PluginsConfiguration; import jdk.tools.jlink.builder.DefaultImageBuilder; import jdk.tools.jlink.plugin.ExecutableImage; -import jdk.tools.jlink.plugin.Pool; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.PostProcessorPlugin; import jdk.tools.jlink.plugin.TransformerPlugin; import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin; @@ -56,6 +56,8 @@ import tests.JImageGenerator; * @library ../lib * @modules java.base/jdk.internal.jimage * jdk.jdeps/com.sun.tools.classfile + * jdk.jlink/jdk.tools.jlink + * jdk.jlink/jdk.tools.jlink.builder * jdk.jlink/jdk.tools.jlink.internal * jdk.jlink/jdk.tools.jlink.internal.plugins * jdk.jlink/jdk.tools.jmod @@ -88,9 +90,9 @@ public class IntegrationTest { } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.PROCESSOR); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.PROCESSOR); return Collections.unmodifiableSet(set); } @@ -128,18 +130,18 @@ public class IntegrationTest { } @Override - public void visit(Pool in, Pool out) { + public void visit(ModulePool in, ModulePool out) { System.err.println(NAME + index); ordered.add(index); - in.visit((file) -> { + in.transformAndCopy((file) -> { return file; }, out); } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.TRANSFORMER); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.TRANSFORMER); return Collections.unmodifiableSet(set); } diff --git a/jdk/test/tools/jlink/JLinkOptimTest.java b/jdk/test/tools/jlink/JLinkOptimTest.java index 82c5431f034..acc089c89c0 100644 --- a/jdk/test/tools/jlink/JLinkOptimTest.java +++ b/jdk/test/tools/jlink/JLinkOptimTest.java @@ -23,15 +23,15 @@ import jdk.internal.org.objectweb.asm.tree.MethodInsnNode; import jdk.internal.org.objectweb.asm.tree.MethodNode; import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode; import jdk.tools.jlink.internal.PluginRepository; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.plugins.OptimizationPlugin; import jdk.tools.jlink.internal.plugins.asm.AsmModulePool; import jdk.tools.jlink.internal.plugins.asm.AsmPlugin; import jdk.tools.jlink.internal.plugins.asm.AsmPools; import jdk.tools.jlink.internal.plugins.optim.ControlFlow; import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import tests.Helper; import tests.JImageGenerator; @@ -134,9 +134,9 @@ public class JLinkOptimTest { } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.TRANSFORMER); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.TRANSFORMER); return Collections.unmodifiableSet(set); } } @@ -150,13 +150,13 @@ public class JLinkOptimTest { FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); Path root = fs.getPath("/modules/java.base"); // Access module-info.class to be reused as fake module-info.class - List javabaseResources = new ArrayList<>(); + List javabaseResources = new ArrayList<>(); try (Stream stream = Files.walk(root)) { for (Iterator iterator = stream.iterator(); iterator.hasNext();) { Path p = iterator.next(); if (Files.isRegularFile(p)) { try { - javabaseResources.add(Pool.newResource(p.toString(). + javabaseResources.add(ModuleEntry.create(p.toString(). substring("/modules".length()), Files.readAllBytes(p))); } catch (Exception ex) { throw new RuntimeException(ex); @@ -166,18 +166,18 @@ public class JLinkOptimTest { } //forName folding - PoolImpl pool = new PoolImpl(); + ModulePoolImpl pool = new ModulePoolImpl(); byte[] content = Files.readAllBytes(classes. resolve("optim").resolve("ForNameTestCase.class")); byte[] content2 = Files.readAllBytes(classes. resolve("optim").resolve("AType.class")); byte[] mcontent = Files.readAllBytes(classes.resolve("module-info.class")); - pool.add(Pool.newResource("/optimplugin/optim/ForNameTestCase.class", content)); - pool.add(Pool.newResource("/optimplugin/optim/AType.class", content2)); - pool.add(Pool.newResource("/optimplugin/module-info.class", mcontent)); + pool.add(ModuleEntry.create("/optimplugin/optim/ForNameTestCase.class", content)); + pool.add(ModuleEntry.create("/optimplugin/optim/AType.class", content2)); + pool.add(ModuleEntry.create("/optimplugin/module-info.class", mcontent)); - for (ModuleData r : javabaseResources) { + for (ModuleEntry r : javabaseResources) { pool.add(r); } @@ -186,10 +186,10 @@ public class JLinkOptimTest { optional.put(OptimizationPlugin.NAME, OptimizationPlugin.FORNAME_REMOVAL); optional.put(OptimizationPlugin.LOG, "forName.log"); plugin.configure(optional); - Pool out = new PoolImpl(); + ModulePool out = new ModulePoolImpl(); plugin.visit(pool, out); - ModuleData result = out.getContent().iterator().next(); + ModuleEntry result = out.entries().iterator().next(); ClassReader optimReader = new ClassReader(result.getBytes()); ClassNode optimClass = new ClassNode(); diff --git a/jdk/test/tools/jlink/JLinkOptionsTest.java b/jdk/test/tools/jlink/JLinkOptionsTest.java index 8c8d241f5b7..565c58bffa9 100644 --- a/jdk/test/tools/jlink/JLinkOptionsTest.java +++ b/jdk/test/tools/jlink/JLinkOptionsTest.java @@ -24,7 +24,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; -import jdk.tools.jlink.plugin.Pool; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.plugin.TransformerPlugin; @@ -62,7 +62,7 @@ public class JLinkOptionsTest { } @Override - public void visit(Pool in, Pool out) { + public void visit(ModulePool in, ModulePool out) { } diff --git a/jdk/test/tools/jlink/JLinkPostProcessingTest.java b/jdk/test/tools/jlink/JLinkPostProcessingTest.java index b32bf207ff2..abc2b58142e 100644 --- a/jdk/test/tools/jlink/JLinkPostProcessingTest.java +++ b/jdk/test/tools/jlink/JLinkPostProcessingTest.java @@ -75,9 +75,9 @@ public class JLinkPostProcessingTest { } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.PROCESSOR); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.PROCESSOR); return Collections.unmodifiableSet(set); } diff --git a/jdk/test/tools/jlink/ResourcePoolTest.java b/jdk/test/tools/jlink/ResourcePoolTest.java index 77a82e5c1b2..523503c996a 100644 --- a/jdk/test/tools/jlink/ResourcePoolTest.java +++ b/jdk/test/tools/jlink/ResourcePoolTest.java @@ -37,14 +37,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; - -import jdk.tools.jlink.internal.PoolImpl; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.Module; -import jdk.tools.jlink.plugin.Pool.ModuleData; -import jdk.tools.jlink.plugin.Pool.ModuleDataType; -import jdk.tools.jlink.plugin.Pool.Visitor; +import java.util.function.Function; +import jdk.tools.jlink.internal.ModulePoolImpl; +import jdk.tools.jlink.plugin.ModulePool; +import jdk.tools.jlink.plugin.LinkModule; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class ResourcePoolTest { @@ -61,54 +61,53 @@ public class ResourcePoolTest { private static final String SUFFIX = "END"; private void checkResourceVisitor() throws Exception { - Pool input = new PoolImpl(); + ModulePool input = new ModulePoolImpl(); for (int i = 0; i < 1000; ++i) { String module = "/module" + (i / 10); String resourcePath = module + "/java/package" + i; byte[] bytes = resourcePath.getBytes(); - input.add(new ModuleData(module, resourcePath, - ModuleDataType.CLASS_OR_RESOURCE, + input.add(ModuleEntry.create(module, resourcePath, + ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(bytes), bytes.length)); } - Pool output = new PoolImpl(); + ModulePool output = new ModulePoolImpl(); ResourceVisitor visitor = new ResourceVisitor(); - input.visit(visitor, output); + input.transformAndCopy(visitor, output); if (visitor.getAmountBefore() == 0) { throw new AssertionError("Resources not found"); } - if (visitor.getAmountBefore() != input.getContent().size()) { + if (visitor.getAmountBefore() != input.getEntryCount()) { throw new AssertionError("Number of visited resources. Expected: " + - visitor.getAmountBefore() + ", got: " + input.getContent().size()); + visitor.getAmountBefore() + ", got: " + input.getEntryCount()); } - if (visitor.getAmountAfter() != output.getContent().size()) { + if (visitor.getAmountAfter() != output.getEntryCount()) { throw new AssertionError("Number of added resources. Expected: " + - visitor.getAmountAfter() + ", got: " + output.getContent().size()); + visitor.getAmountAfter() + ", got: " + output.getEntryCount()); } - for (ModuleData outResource : output.getContent()) { + output.entries().forEach(outResource -> { String path = outResource.getPath().replaceAll(SUFFIX + "$", ""); - ModuleData inResource = input.get(path); - if (inResource == null) { + if (!input.findEntry(path).isPresent()) { throw new AssertionError("Unknown resource: " + path); } - } + }); } - private static class ResourceVisitor implements Visitor { + private static class ResourceVisitor implements Function { private int amountBefore; private int amountAfter; @Override - public ModuleData visit(ModuleData resource) { + public ModuleEntry apply(ModuleEntry resource) { int index = ++amountBefore % 3; switch (index) { case 0: ++amountAfter; - return new ModuleData(resource.getModule(), resource.getPath() + SUFFIX, + return ModuleEntry.create(resource.getModule(), resource.getPath() + SUFFIX, resource.getType(), resource.stream(), resource.getLength()); case 1: ++amountAfter; - return new ModuleData(resource.getModule(), resource.getPath(), + return ModuleEntry.create(resource.getModule(), resource.getPath(), resource.getType(), resource.stream(), resource.getLength()); } return null; @@ -133,8 +132,8 @@ public class ResourcePoolTest { samples.add("javax/management/ObjectName"); test(samples, (resources, module, path) -> { try { - resources.add(new ModuleData(module, path, - ModuleDataType.CLASS_OR_RESOURCE, + resources.add(ModuleEntry.create(module, path, + ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0)); } catch (Exception ex) { throw new RuntimeException(ex); @@ -142,12 +141,12 @@ public class ResourcePoolTest { }); test(samples, (resources, module, path) -> { try { - resources.add(PoolImpl. - newCompressedResource(new ModuleData(module, path, - ModuleDataType.CLASS_OR_RESOURCE, + resources.add(ModulePoolImpl. + newCompressedResource(ModuleEntry.create(module, path, + ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0), ByteBuffer.allocate(99), "bitcruncher", null, - ((PoolImpl)resources).getStringTable(), ByteOrder.nativeOrder())); + ((ModulePoolImpl)resources).getStringTable(), ByteOrder.nativeOrder())); } catch (Exception ex) { throw new RuntimeException(ex); } @@ -158,7 +157,7 @@ public class ResourcePoolTest { if (samples.isEmpty()) { throw new AssertionError("No sample to test"); } - Pool resources = new PoolImpl(); + ModulePool resources = new ModulePoolImpl(); Set modules = new HashSet<>(); for (int i = 0; i < samples.size(); i++) { String module = samples.get(i); @@ -173,70 +172,69 @@ public class ResourcePoolTest { i++; String clazz = samples.get(i); String path = "/" + module + "/" + clazz + ".class"; - ModuleData res = resources.get(path); - checkModule(resources, res); - if (res == null) { + Optional res = resources.findEntry(path); + if (!res.isPresent()) { throw new AssertionError("Resource not found " + path); } - ModuleData res2 = resources.get(clazz); - if (res2 != null) { + checkModule(resources, res.get()); + if (resources.findEntry(clazz).isPresent()) { throw new AssertionError("Resource found " + clazz); } } - if (resources.getContent().size() != samples.size() / 2) { + if (resources.getEntryCount() != samples.size() / 2) { throw new AssertionError("Invalid number of resources"); } } - private void checkModule(Pool resources, ModuleData res) { - Module m = resources.getModule(res.getModule()); - if (m == null) { + private void checkModule(ModulePool resources, ModuleEntry res) { + Optional optMod = resources.findModule(res.getModule()); + if (!optMod.isPresent()) { throw new AssertionError("No module " + res.getModule()); } + LinkModule m = optMod.get(); if (!m.getName().equals(res.getModule())) { throw new AssertionError("Not right module name " + res.getModule()); } - if (m.get(res.getPath()) == null) { + if (!m.findEntry(res.getPath()).isPresent()) { throw new AssertionError("resource " + res.getPath() + " not in module " + m.getName()); } } private void checkResourcesAfterCompression() throws Exception { - PoolImpl resources1 = new PoolImpl(); - ModuleData res1 = new ModuleData("module1", "/module1/toto1", - ModuleDataType.CLASS_OR_RESOURCE, + ModulePoolImpl resources1 = new ModulePoolImpl(); + ModuleEntry res1 = ModuleEntry.create("module1", "/module1/toto1", + ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0); - ModuleData res2 = new ModuleData("module2", "/module2/toto1", - ModuleDataType.CLASS_OR_RESOURCE, + ModuleEntry res2 = ModuleEntry.create("module2", "/module2/toto1", + ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0); resources1.add(res1); resources1.add(res2); checkResources(resources1, res1, res2); - Pool resources2 = new PoolImpl(); - ModuleData res3 = new ModuleData("module2", "/module2/toto1", - ModuleDataType.CLASS_OR_RESOURCE, + ModulePool resources2 = new ModulePoolImpl(); + ModuleEntry res3 = ModuleEntry.create("module2", "/module2/toto1", + ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[7]), 7); resources2.add(res3); - resources2.add(PoolImpl.newCompressedResource(res1, + resources2.add(ModulePoolImpl.newCompressedResource(res1, ByteBuffer.allocate(7), "zip", null, resources1.getStringTable(), ByteOrder.nativeOrder())); checkResources(resources2, res1, res2); } - private void checkResources(Pool resources, ModuleData... expected) { - Collection ms = resources.getModules(); + private void checkResources(ModulePool resources, ModuleEntry... expected) { List modules = new ArrayList(); - for(Module m : ms) { + resources.modules().forEach(m -> { modules.add(m.getName()); - } - for (ModuleData res : expected) { + }); + for (ModuleEntry res : expected) { if (!resources.contains(res)) { throw new AssertionError("Resource not found: " + res); } - if (resources.get(res.getPath()) == null) { + if (!resources.findEntry(res.getPath()).isPresent()) { throw new AssertionError("Resource not found: " + res); } @@ -244,7 +242,7 @@ public class ResourcePoolTest { throw new AssertionError("Module not found: " + res.getModule()); } - if (!resources.getContent().contains(res)) { + if (!resources.contains(res)) { throw new AssertionError("Resources not found: " + res); } @@ -260,17 +258,17 @@ public class ResourcePoolTest { throw new AssertionError("ReadOnly resources"); } - ((PoolImpl) resources).setReadOnly(); + ((ModulePoolImpl) resources).setReadOnly(); try { - resources.add(new ModuleData("module2", "/module2/toto1", - ModuleDataType.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0)); - throw new AssertionError("Pool is read-only, but an exception is not thrown"); + resources.add(ModuleEntry.create("module2", "/module2/toto1", + ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0)); + throw new AssertionError("ModulePool is read-only, but an exception is not thrown"); } catch (Exception ex) { // Expected } } interface ResourceAdder { - void add(Pool resources, String module, String path); + void add(ModulePool resources, String module, String path); } } diff --git a/jdk/test/tools/jlink/SecurityTest.java b/jdk/test/tools/jlink/SecurityTest.java index 9497d6f3f34..dbf593bccc0 100644 --- a/jdk/test/tools/jlink/SecurityTest.java +++ b/jdk/test/tools/jlink/SecurityTest.java @@ -25,6 +25,7 @@ * @test * @summary Test JlinkPermission * @author Jean-Francois Denise + * @modules jdk.jlink/jdk.tools.jlink * @run main/othervm SecurityTest */ diff --git a/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java b/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java index 6a414b57d63..4385534e07f 100644 --- a/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java +++ b/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java @@ -55,8 +55,8 @@ import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile; import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableClassPool; import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableResourcePool; import jdk.tools.jlink.internal.plugins.asm.AsmPools; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class AddForgetResourcesTest extends AsmPluginTestBase { @@ -82,7 +82,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { new ComboPlugin() }; for (TestPlugin p : plugins) { - Pool out = p.visit(getPool()); + ModulePool out = p.visit(getPool()); p.test(getPool(), out); } } @@ -124,7 +124,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { AsmGlobalPool globalPool = pools.getGlobalPool(); WritableClassPool transformedClasses = globalPool.getTransformedClasses(); expected = globalPool.getClasses().size(); - for (ModuleData res : globalPool.getClasses()) { + for (ModuleEntry res : globalPool.getClasses()) { ClassReader reader = globalPool.getClassReader(res); String className = reader.getClassName(); if (!className.endsWith("module-info")) { @@ -137,14 +137,14 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) { - Collection inClasses = extractClasses(inResources); - Collection outClasses = extractClasses(outResources); + public void test(ModulePool inResources, ModulePool outResources) { + Collection inClasses = extractClasses(inResources); + Collection outClasses = extractClasses(outResources); if (expected != outClasses.size()) { throw new AssertionError("Classes were not added. Expected: " + expected + ", got: " + outClasses.size()); } - for (ModuleData in : inClasses) { + for (ModuleEntry in : inClasses) { String path = in.getPath(); if (!outClasses.contains(in)) { throw new AssertionError("Class not found: " + path); @@ -153,7 +153,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { continue; } String modifiedPath = path.replace(".class", SUFFIX + ".class"); - if (!outClasses.contains(Pool.newResource(modifiedPath, new byte[0]))) { + if (!outClasses.contains(ModuleEntry.create(modifiedPath, new byte[0]))) { throw new AssertionError("Class not found: " + modifiedPath); } } @@ -166,7 +166,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { public void visit() { AsmPools pools = getPools(); AsmGlobalPool globalPool = pools.getGlobalPool(); - for (ModuleData res : globalPool.getResourceFiles()) { + for (ModuleEntry res : globalPool.getResourceFiles()) { String path = res.getPath(); String moduleName = getModule(path); AsmModulePool modulePool = pools.getModulePool(moduleName); @@ -177,20 +177,20 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool in, Pool out) throws Exception { - Collection inResources = extractResources(in); - Collection outResources = extractResources(out); + public void test(ModulePool in, ModulePool out) throws Exception { + Collection inResources = extractResources(in); + Collection outResources = extractResources(out); if (2 * inResources.size() != outResources.size()) { throw new AssertionError("Classes were not added. Expected: " + (2 * inResources.size()) + ", got: " + outResources.size()); } - for (ModuleData r : inResources) { + for (ModuleEntry r : inResources) { String path = r.getPath(); if (!outResources.contains(r)) { throw new AssertionError("Class not found: " + path); } String modifiedPath = path + SUFFIX; - if (!outResources.contains(Pool.newResource(modifiedPath, new byte[0]))) { + if (!outResources.contains(ModuleEntry.create(modifiedPath, new byte[0]))) { throw new AssertionError("Class not found: " + modifiedPath); } } @@ -204,7 +204,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { AsmPools pools = getPools(); AsmGlobalPool globalPool = pools.getGlobalPool(); WritableClassPool transformedClasses = globalPool.getTransformedClasses(); - for (ModuleData res : globalPool.getClasses()) { + for (ModuleEntry res : globalPool.getClasses()) { ClassReader reader = globalPool.getClassReader(res); ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES); reader.accept(new AddMethodClassVisitor(writer), ClassReader.EXPAND_FRAMES); @@ -213,14 +213,14 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) throws Exception { - Collection inClasses = extractClasses(inResources); - Collection outClasses = extractClasses(outResources); + public void test(ModulePool inResources, ModulePool outResources) throws Exception { + Collection inClasses = extractClasses(inResources); + Collection outClasses = extractClasses(outResources); if (inClasses.size() != outClasses.size()) { throw new AssertionError("Number of classes. Expected: " + (inClasses.size()) + ", got: " + outClasses.size()); } - for (ModuleData out : outClasses) { + for (ModuleEntry out : outClasses) { String path = out.getPath(); if (!inClasses.contains(out)) { throw new AssertionError("Class not found: " + path); @@ -248,7 +248,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { public void visit() { AsmPools pools = getPools(); AsmGlobalPool globalPool = pools.getGlobalPool(); - for (ModuleData res : globalPool.getResourceFiles()) { + for (ModuleEntry res : globalPool.getResourceFiles()) { String path = res.getPath(); AsmModulePool modulePool = pools.getModulePool(getModule(path)); modulePool.getTransformedResourceFiles().addResourceFile(new ResourceFile(removeModule(path), @@ -257,14 +257,14 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool in, Pool out) throws Exception { - Collection inResources = extractResources(in); - Collection outResources = extractResources(out); + public void test(ModulePool in, ModulePool out) throws Exception { + Collection inResources = extractResources(in); + Collection outResources = extractResources(out); if (inResources.size() != outResources.size()) { throw new AssertionError("Number of resources. Expected: " + inResources.size() + ", got: " + outResources.size()); } - for (ModuleData r : outResources) { + for (ModuleEntry r : outResources) { String path = r.getPath(); if (!inResources.contains(r)) { throw new AssertionError("Resource not found: " + path); @@ -287,7 +287,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { AsmGlobalPool globalPool = pools.getGlobalPool(); WritableClassPool transformedClasses = globalPool.getTransformedClasses(); int i = 0; - for (ModuleData res : globalPool.getClasses()) { + for (ModuleEntry res : globalPool.getClasses()) { String path = removeModule(res.getPath()); String className = path.replace(".class", ""); if ((i & 1) == 0 && !className.endsWith("module-info")) { @@ -300,8 +300,8 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) throws Exception { - Collection outClasses = extractClasses(outResources); + public void test(ModulePool inResources, ModulePool outResources) throws Exception { + Collection outClasses = extractClasses(outResources); if (expected != outClasses.size()) { throw new AssertionError("Number of classes. Expected: " + expected + ", got: " + outClasses.size()); @@ -318,7 +318,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { AsmPools pools = getPools(); AsmGlobalPool globalPool = pools.getGlobalPool(); int i = 0; - for (ModuleData res : globalPool.getResourceFiles()) { + for (ModuleEntry res : globalPool.getResourceFiles()) { String path = res.getPath(); if (!path.contains("META-INF/services")) { if ((i & 1) == 0) { @@ -335,8 +335,8 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool in, Pool out) throws Exception { - Collection outResources = extractResources(out); + public void test(ModulePool in, ModulePool out) throws Exception { + Collection outResources = extractResources(out); if (expectedAmount != outResources.size()) { throw new AssertionError("Number of classes. Expected: " + expectedAmount + ", got: " + outResources.size()); @@ -354,7 +354,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { AsmGlobalPool globalPool = pools.getGlobalPool(); WritableClassPool transformedClasses = globalPool.getTransformedClasses(); int i = 0; - for (ModuleData res : globalPool.getClasses()) { + for (ModuleEntry res : globalPool.getClasses()) { ClassReader reader = globalPool.getClassReader(res); String className = reader.getClassName(); ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES); @@ -374,8 +374,8 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) throws Exception { - Collection outClasses = extractClasses(outResources); + public void test(ModulePool inResources, ModulePool outResources) throws Exception { + Collection outClasses = extractClasses(outResources); if (expected != outClasses.size()) { throw new AssertionError("Number of classes. Expected: " + expected + ", got: " + outClasses.size()); @@ -392,7 +392,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { AsmPools pools = getPools(); AsmGlobalPool globalPool = pools.getGlobalPool(); int i = 0; - for (ModuleData res : globalPool.getResourceFiles()) { + for (ModuleEntry res : globalPool.getResourceFiles()) { String path = res.getPath(); String moduleName = getModule(path); if (!path.contains("META-INF")) { @@ -412,8 +412,8 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool out) throws Exception { - Collection outResources = extractResources(out); + public void test(ModulePool inResources, ModulePool out) throws Exception { + Collection outResources = extractResources(out); if (expectedAmount != outResources.size()) { throw new AssertionError("Number of classes. Expected: " + expectedAmount + ", got: " + outResources.size()); @@ -446,7 +446,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) throws Exception { + public void test(ModulePool inResources, ModulePool outResources) throws Exception { if (!isVisitCalled()) { throw new AssertionError("Resources not visited"); } @@ -455,7 +455,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { throw new AssertionError("Number of transformed classes not equal to expected"); } // Check that only renamed classes and resource files are in the result. - for (ModuleData r : outResources.getContent()) { + outResources.entries().forEach(r -> { String resourceName = r.getPath(); if (resourceName.endsWith(".class") && !resourceName.endsWith("module-info.class")) { if (!resourceName.endsWith(SUFFIX + ".class")) { @@ -467,7 +467,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { throw new AssertionError("Resource file not renamed " + resourceName); } } - } + }); } private void renameResources() throws IOException { @@ -476,7 +476,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { for (Map.Entry> mod : MODULES.entrySet()) { String moduleName = mod.getKey(); AsmModulePool modulePool = pools.getModulePool(moduleName); - for (ModuleData res : modulePool.getResourceFiles()) { + for (ModuleEntry res : modulePool.getResourceFiles()) { ResourceFile resFile = modulePool.getResourceFile(res); if (resFile.getPath().startsWith("META-INF/services/")) { String newContent = new String(resFile.getContent()) + SUFFIX; @@ -492,7 +492,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase { AsmPools pools = getPools(); AsmGlobalPool globalPool = pools.getGlobalPool(); WritableClassPool transformedClasses = globalPool.getTransformedClasses(); - for (ModuleData res : globalPool.getClasses()) { + for (ModuleEntry res : globalPool.getClasses()) { if (res.getPath().endsWith("module-info.class")) { continue; } diff --git a/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java b/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java index d5c035562fa..c51419e682c 100644 --- a/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java +++ b/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java @@ -38,23 +38,23 @@ import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.StringTable; import jdk.tools.jlink.internal.plugins.asm.AsmPlugin; import jdk.tools.jlink.internal.plugins.asm.AsmPools; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public abstract class AsmPluginTestBase { protected static final String TEST_MODULE = "jlink.test"; protected static final Map> MODULES; - private static final Predicate isClass = r -> r.getPath().endsWith(".class"); + private static final Predicate isClass = r -> r.getPath().endsWith(".class"); private final List classes; private final List resources; - private final Pool pool; + private final ModulePool pool; static { Map> map = new HashMap<>(); @@ -75,7 +75,7 @@ public abstract class AsmPluginTestBase { List classes = new ArrayList<>(); List resources = new ArrayList<>(); - pool = new PoolImpl(); + pool = new ModulePoolImpl(); FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); Path root = fs.getPath("/modules"); @@ -100,7 +100,7 @@ public abstract class AsmPluginTestBase { MODULES.get(module).add(toResourceFile(p)); } resources.add(toPath(p.toString())); - ModuleData res = Pool.newResource(toPath(p.toString()), content); + ModuleEntry res = ModuleEntry.create(toPath(p.toString()), content); pool.add(res); } catch (Exception ex) { throw new RuntimeException(ex); @@ -110,17 +110,17 @@ public abstract class AsmPluginTestBase { } } // There is more than 10 classes in java.base... - if (classes.size() < 10 || pool.getContent().size() < 10) { + if (classes.size() < 10 || pool.getEntryCount() < 10) { throw new AssertionError("Not expected resource or class number"); } //Add a fake resource file String content = "java.lang.Object"; String path = "META-INF/services/com.foo.BarProvider"; - ModuleData resFile = Pool.newResource("/" + TEST_MODULE + "/" + + ModuleEntry resFile = ModuleEntry.create("/" + TEST_MODULE + "/" + path, content.getBytes()); pool.add(resFile); - ModuleData fakeInfoFile = Pool.newResource("/" + TEST_MODULE + ModuleEntry fakeInfoFile = ModuleEntry.create("/" + TEST_MODULE + "/module-info.class", moduleInfos.get(0)); pool.add(fakeInfoFile); MODULES.get(TEST_MODULE).add(path); @@ -144,20 +144,20 @@ public abstract class AsmPluginTestBase { return resources; } - public Pool getPool() { + public ModulePool getPool() { return pool; } public abstract void test() throws Exception; - public Collection extractClasses(Pool pool) { - return pool.getContent().stream() + public Collection extractClasses(ModulePool pool) { + return pool.entries() .filter(isClass) .collect(Collectors.toSet()); } - public Collection extractResources(Pool pool) { - return pool.getContent().stream() + public Collection extractResources(ModulePool pool) { + return pool.entries() .filter(isClass.negate()) .collect(Collectors.toSet()); } @@ -209,9 +209,9 @@ public abstract class AsmPluginTestBase { return pools != null; } - public Pool visit(Pool inResources) throws IOException { + public ModulePool visit(ModulePool inResources) throws IOException { try { - Pool outResources = new PoolImpl(inResources.getByteOrder(), new StringTable() { + ModulePool outResources = new ModulePoolImpl(inResources.getByteOrder(), new StringTable() { @Override public int addString(String str) { return -1; @@ -239,7 +239,7 @@ public abstract class AsmPluginTestBase { } public abstract void visit(); - public abstract void test(Pool inResources, Pool outResources) throws Exception; + public abstract void test(ModulePool inResources, ModulePool outResources) throws Exception; @Override public String getName() { diff --git a/jdk/test/tools/jlink/asmplugin/BasicTest.java b/jdk/test/tools/jlink/asmplugin/BasicTest.java index 0c42d4cfb99..afc5fd5f634 100644 --- a/jdk/test/tools/jlink/asmplugin/BasicTest.java +++ b/jdk/test/tools/jlink/asmplugin/BasicTest.java @@ -45,8 +45,8 @@ import java.util.logging.Logger; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.tools.jlink.internal.plugins.asm.AsmModulePool; import jdk.tools.jlink.internal.plugins.asm.AsmPool; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class BasicTest extends AsmPluginTestBase { @@ -61,7 +61,7 @@ public class BasicTest extends AsmPluginTestBase { @Override public void test() throws Exception { BasicPlugin basicPlugin = new BasicPlugin(getClasses()); - Pool res = basicPlugin.visit(getPool()); + ModulePool res = basicPlugin.visit(getPool()); basicPlugin.test(getPool(), res); } @@ -107,13 +107,13 @@ public class BasicTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) throws Exception { + public void test(ModulePool inResources, ModulePool outResources) throws Exception { if (!isVisitCalled()) { throw new AssertionError("Resources not visited"); } - if (inResources.getContent().size() != outResources.getContent().size()) { - throw new AssertionError("Input size " + inResources.getContent().size() + - " != to " + outResources.getContent().size()); + if (inResources.getEntryCount() != outResources.getEntryCount()) { + throw new AssertionError("Input size " + inResources.getEntryCount() + + " != to " + outResources.getEntryCount()); } } @@ -142,7 +142,7 @@ public class BasicTest extends AsmPluginTestBase { private void testPools() throws IOException { Set remain = new HashSet<>(classes); - for (ModuleData res : getPools().getGlobalPool().getClasses()) { + for (ModuleEntry res : getPools().getGlobalPool().getClasses()) { ClassReader reader = getPools().getGlobalPool().getClassReader(res); String className = reader.getClassName(); // Wrong naming of module-info.class in ASM diff --git a/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java b/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java index ceb2e50f9b9..416d3581552 100644 --- a/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java +++ b/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java @@ -35,14 +35,15 @@ import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.UncheckedIOException; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableClassPool; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class IdentityPluginTest extends AsmPluginTestBase { @@ -56,7 +57,7 @@ public class IdentityPluginTest extends AsmPluginTestBase { public void test() throws Exception { IdentityPlugin asm = new IdentityPlugin(); - Pool resourcePool = asm.visit(getPool()); + ModulePool resourcePool = asm.visit(getPool()); asm.test(getPool(), resourcePool); } @@ -64,7 +65,7 @@ public class IdentityPluginTest extends AsmPluginTestBase { @Override public void visit() { - for (ModuleData res : getPools().getGlobalPool().getClasses()) { + for (ModuleEntry res : getPools().getGlobalPool().getClasses()) { if (res.getPath().endsWith("module-info.class")) { continue; } @@ -77,7 +78,7 @@ public class IdentityPluginTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) throws IOException { + public void test(ModulePool inResources, ModulePool outResources) throws IOException { if (outResources.isEmpty()) { throw new AssertionError("Empty result"); } @@ -93,13 +94,17 @@ public class IdentityPluginTest extends AsmPluginTestBase { throw new AssertionError("Class not transformed " + className); } } - for (ModuleData r : outResources.getContent()) { + outResources.entries().forEach(r -> { if (r.getPath().endsWith(".class") && !r.getPath().endsWith("module-info.class")) { - ClassReader reader = new ClassReader(new ByteArrayInputStream(r.getBytes())); - ClassWriter w = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES); - reader.accept(w, ClassReader.EXPAND_FRAMES); + try { + ClassReader reader = new ClassReader(new ByteArrayInputStream(r.getBytes())); + ClassWriter w = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES); + reader.accept(w, ClassReader.EXPAND_FRAMES); + } catch (IOException exp) { + throw new UncheckedIOException(exp); + } } - } + }); } @Override diff --git a/jdk/test/tools/jlink/asmplugin/NegativeTest.java b/jdk/test/tools/jlink/asmplugin/NegativeTest.java index f95b7c62399..6263fcaaa4a 100644 --- a/jdk/test/tools/jlink/asmplugin/NegativeTest.java +++ b/jdk/test/tools/jlink/asmplugin/NegativeTest.java @@ -43,7 +43,7 @@ import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.tools.jlink.plugin.Plugin; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.StringTable; import jdk.tools.jlink.internal.plugins.asm.AsmGlobalPool; import jdk.tools.jlink.internal.plugins.asm.AsmModulePool; @@ -51,7 +51,7 @@ import jdk.tools.jlink.internal.plugins.asm.AsmPlugin; import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile; import jdk.tools.jlink.internal.plugins.asm.AsmPools; import jdk.tools.jlink.plugin.PluginException; -import jdk.tools.jlink.plugin.Pool; +import jdk.tools.jlink.plugin.ModulePool; public class NegativeTest extends AsmPluginTestBase { public static void main(String[] args) throws Exception { @@ -102,7 +102,7 @@ public class NegativeTest extends AsmPluginTestBase { } } }; - Pool resources = new PoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() { + ModulePool resources = new ModulePoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() { @Override public int addString(String str) { return -1; @@ -136,7 +136,7 @@ public class NegativeTest extends AsmPluginTestBase { action(() -> pools.fillOutputResources(null), "Output resource is null", NullPointerException.class); } }; - Pool resources = new PoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() { + ModulePool resources = new ModulePoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() { @Override public int addString(String str) { return -1; diff --git a/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java b/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java index 9453ac5f917..bd0a8fdbf4d 100644 --- a/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java +++ b/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java @@ -48,8 +48,8 @@ import jdk.tools.jlink.internal.plugins.asm.AsmModulePool; import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile; import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableResourcePool; import jdk.tools.jlink.plugin.PluginException; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class PackageMappingTest extends AsmPluginTestBase { @@ -72,7 +72,7 @@ public class PackageMappingTest extends AsmPluginTestBase { new PackageMappingPlugin(newFiles, true) }; for (TestPlugin p : plugins) { - Pool pool = p.visit(getPool()); + ModulePool pool = p.visit(getPool()); p.test(getPool(), pool); } } @@ -105,12 +105,12 @@ public class PackageMappingTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) { + public void test(ModulePool inResources, ModulePool outResources) { Set in = getPools().getGlobalPool().getResourceFiles().stream() - .map(ModuleData::getPath) + .map(ModuleEntry::getPath) .collect(Collectors.toSet()); Set out = extractResources(outResources).stream() - .map(ModuleData::getPath) + .map(ModuleEntry::getPath) .collect(Collectors.toSet()); in.addAll(PackageMappingTest.this.newFiles); if (!Objects.equals(in, out)) { diff --git a/jdk/test/tools/jlink/asmplugin/SortingTest.java b/jdk/test/tools/jlink/asmplugin/SortingTest.java index 0fc4c7a6854..26974b3b065 100644 --- a/jdk/test/tools/jlink/asmplugin/SortingTest.java +++ b/jdk/test/tools/jlink/asmplugin/SortingTest.java @@ -35,12 +35,13 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import jdk.tools.jlink.internal.plugins.asm.AsmModulePool; import jdk.tools.jlink.plugin.PluginException; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class SortingTest extends AsmPluginTestBase { @@ -66,7 +67,7 @@ public class SortingTest extends AsmPluginTestBase { List sorted = new ArrayList<>(getResources()); sorted.sort(null); ClassSorterPlugin sorterPlugin = new ClassSorterPlugin(sorted); - Pool resourcePool = sorterPlugin.visit(getPool()); + ModulePool resourcePool = sorterPlugin.visit(getPool()); sorterPlugin.test(getPool(), resourcePool); } @@ -78,7 +79,7 @@ public class SortingTest extends AsmPluginTestBase { List sorted = new ArrayList<>(getResources()); sorted.sort((s1, s2) -> -getModuleName(s1).compareTo(getModuleName(s2))); ModuleSorterPlugin sorterPlugin = new ModuleSorterPlugin(); - Pool resourcePool = sorterPlugin.visit(getPool()); + ModulePool resourcePool = sorterPlugin.visit(getPool()); sorterPlugin.test(getPool(), resourcePool); } @@ -88,8 +89,8 @@ public class SortingTest extends AsmPluginTestBase { public void visit() { for (AsmModulePool modulePool : getPools().getModulePools()) { modulePool.setSorter(resources -> { - List sort = resources.getContent().stream() - .map(ModuleData::getPath) + List sort = resources.entries() + .map(ModuleEntry::getPath) .collect(Collectors.toList()); sort.sort(null); return sort; @@ -102,21 +103,21 @@ public class SortingTest extends AsmPluginTestBase { } @Override - public void test(Pool inResources, Pool outResources) throws Exception { + public void test(ModulePool inResources, ModulePool outResources) throws Exception { if (!isVisitCalled()) { throw new AssertionError("Resources not visited"); } - List sortedResourcePaths = outResources.getContent().stream() - .map(ModuleData::getPath) + List sortedResourcePaths = outResources.entries() + .map(ModuleEntry::getPath) .collect(Collectors.toList()); List defaultResourceOrder = new ArrayList<>(); - for (ModuleData r : inResources.getContent()) { - if (!inResources.getContent().contains(r)) { + inResources.entries().forEach(r -> { + if (!inResources.contains(r)) { throw new AssertionError("Resource " + r.getPath() + " not in result pool"); } defaultResourceOrder.add(r.getPath()); - } + }); // Check that default sorting is not equal to sorted one if (defaultResourceOrder.equals(sortedResourcePaths)) { throw new AssertionError("Sorting not applied, default ordering"); @@ -147,27 +148,28 @@ public class SortingTest extends AsmPluginTestBase { public void visit() { getPools().getGlobalPool().setSorter( (resources) -> expectedClassesOrder.stream() - .map(resources::get) - .map(ModuleData::getPath) + .map(resources::findEntry) + .map(Optional::get) + .map(ModuleEntry::getPath) .collect(Collectors.toList())); } @Override - public void test(Pool inResources, Pool outResources) throws Exception { + public void test(ModulePool inResources, ModulePool outResources) throws Exception { if (!isVisitCalled()) { throw new AssertionError("Resources not visited"); } - List sortedResourcePaths = outResources.getContent().stream() - .map(ModuleData::getPath) + List sortedResourcePaths = outResources.entries() + .map(ModuleEntry::getPath) .collect(Collectors.toList()); List defaultResourceOrder = new ArrayList<>(); - for (ModuleData r : getPool().getContent()) { - if (!getPool().getContent().contains(r)) { + getPool().entries().forEach(r -> { + if (!getPool().contains(r)) { throw new AssertionError("Resource " + r.getPath() + " not in result pool"); } defaultResourceOrder.add(r.getPath()); - } + }); // Check that default sorting is not equal to sorted one if (defaultResourceOrder.equals(sortedResourcePaths)) { throw new AssertionError("Sorting not applied, default ordering"); diff --git a/jdk/test/tools/jlink/asmplugin/VisitorTest.java b/jdk/test/tools/jlink/asmplugin/VisitorTest.java index 1b278a8bd48..500d415bc50 100644 --- a/jdk/test/tools/jlink/asmplugin/VisitorTest.java +++ b/jdk/test/tools/jlink/asmplugin/VisitorTest.java @@ -46,8 +46,8 @@ import jdk.tools.jlink.internal.plugins.asm.AsmPool.ClassReaderVisitor; import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile; import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFileVisitor; import jdk.tools.jlink.internal.plugins.asm.AsmPools; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class VisitorTest extends AsmPluginTestBase { @@ -69,7 +69,7 @@ public class VisitorTest extends AsmPluginTestBase { }; for (TestPlugin p : plugins) { System.err.println("Testing: " + p.getName()); - Pool out = p.visit(getPool()); + ModulePool out = p.visit(getPool()); p.test(getPool(), out); } } @@ -149,15 +149,15 @@ public class VisitorTest extends AsmPluginTestBase { } @Override - public void test(Pool in, Pool out) throws Exception { - Collection inClasses = getPool.apply(getPools()).getClasses(); + public void test(ModulePool in, ModulePool out) throws Exception { + Collection inClasses = getPool.apply(getPools()).getClasses(); if (inClasses.size() != classReaderVisitor.getAmount()) { throw new AssertionError("Testing " + name + ". Number of visited classes. Expected: " + inClasses.size() + ", got: " + classReaderVisitor.getAmount()); } - Collection outClasses = extractClasses(out); + Collection outClasses = extractClasses(out); int changedClasses = 0; - for (ModuleData r : outClasses) { + for (ModuleEntry r : outClasses) { if (r.getPath().endsWith("Changed.class")) { ++changedClasses; } @@ -192,15 +192,15 @@ public class VisitorTest extends AsmPluginTestBase { } @Override - public void test(Pool in, Pool out) throws Exception { - Collection inResources = getPool.apply(getPools()).getResourceFiles(); + public void test(ModulePool in, ModulePool out) throws Exception { + Collection inResources = getPool.apply(getPools()).getResourceFiles(); if (inResources.size() != resourceFileVisitor.getAmount()) { throw new AssertionError("Testing " + name + ". Number of visited resources. Expected: " + inResources.size() + ", got: " + resourceFileVisitor.getAmount()); } - Collection outResources = extractResources(out); + Collection outResources = extractResources(out); int changedClasses = 0; - for (ModuleData r : outResources) { + for (ModuleEntry r : outResources) { if (r.getPath().endsWith("Changed")) { ++changedClasses; } diff --git a/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java b/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java index 38054ec2015..781039a517a 100644 --- a/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java +++ b/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java @@ -26,7 +26,9 @@ import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; -import jdk.tools.jlink.plugin.Pool; +import java.util.function.Function; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; public class CustomPlugin implements TransformerPlugin { @@ -37,13 +39,8 @@ public class CustomPlugin implements TransformerPlugin { } @Override - public void visit(Pool in, Pool out) { - in.visit(new Pool.Visitor() { - @Override - public Pool.ModuleData visit(Pool.ModuleData content) { - return content; - } - }, out); + public void visit(ModulePool in, ModulePool out) { + in.transformAndCopy(Function.identity(), out); } @Override @@ -61,9 +58,9 @@ public class CustomPlugin implements TransformerPlugin { } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.PROCESSOR); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.PROCESSOR); return Collections.unmodifiableSet(set); } } diff --git a/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java b/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java index d06f99050b1..aa150350d7f 100644 --- a/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java +++ b/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java @@ -29,8 +29,8 @@ import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; /** @@ -49,23 +49,23 @@ public final class HelloPlugin implements TransformerPlugin { } @Override - public void visit(Pool inResources, Pool outResources) { + public void visit(ModulePool inResources, ModulePool outResources) { try { System.out.println("Hello!!!!!!!!!!"); File f = new File(OUTPUT_FILE); f.createNewFile(); - for (ModuleData res : inResources.getContent()) { + inResources.entries().forEach(res -> { outResources.add(res); - } + }); } catch (IOException ex) { throw new UncheckedIOException(ex); } } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.TRANSFORMER); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.TRANSFORMER); return Collections.unmodifiableSet(set); } diff --git a/jdk/test/tools/jlink/plugins/CompressorPluginTest.java b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java index cd01b93836b..d37bf1b73d2 100644 --- a/jdk/test/tools/jlink/plugins/CompressorPluginTest.java +++ b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java @@ -53,14 +53,14 @@ import jdk.internal.jimage.decompressor.ResourceDecompressor; import jdk.internal.jimage.decompressor.ResourceDecompressorFactory; import jdk.internal.jimage.decompressor.StringSharingDecompressorFactory; import jdk.internal.jimage.decompressor.ZipDecompressorFactory; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.StringTable; import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin; import jdk.tools.jlink.internal.plugins.StringSharingPlugin; import jdk.tools.jlink.internal.plugins.ZipPlugin; import jdk.tools.jlink.plugin.Plugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; public class CompressorPluginTest { @@ -86,7 +86,7 @@ public class CompressorPluginTest { new ZipDecompressorFactory() }); - Pool classes = gatherClasses(javabase); + ModulePool classes = gatherClasses(javabase); // compress = String sharing checkCompress(classes, new StringSharingPlugin(), null, new ResourceDecompressorFactory[]{ @@ -173,8 +173,8 @@ public class CompressorPluginTest { Collections.singletonList(".*IOException.class")); } - private Pool gatherResources(Path module) throws Exception { - Pool pool = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() { + private ModulePool gatherResources(Path module) throws Exception { + ModulePool pool = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() { @Override public int addString(String str) { @@ -191,15 +191,15 @@ public class CompressorPluginTest { Path p = iterator.next(); if (Files.isRegularFile(p)) { byte[] content = Files.readAllBytes(p); - pool.add(Pool.newResource(p.toString(), content)); + pool.add(ModuleEntry.create(p.toString(), content)); } } } return pool; } - private Pool gatherClasses(Path module) throws Exception { - Pool pool = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() { + private ModulePool gatherClasses(Path module) throws Exception { + ModulePool pool = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() { @Override public int addString(String str) { @@ -216,27 +216,27 @@ public class CompressorPluginTest { Path p = iterator.next(); if (Files.isRegularFile(p) && p.toString().endsWith(".class")) { byte[] content = Files.readAllBytes(p); - pool.add(Pool.newResource(p.toString(), content)); + pool.add(ModuleEntry.create(p.toString(), content)); } } } return pool; } - private void checkCompress(Pool resources, Plugin prov, + private void checkCompress(ModulePool resources, Plugin prov, Properties config, ResourceDecompressorFactory[] factories) throws Exception { checkCompress(resources, prov, config, factories, Collections.emptyList(), Collections.emptyList()); } - private void checkCompress(Pool resources, Plugin prov, + private void checkCompress(ModulePool resources, Plugin prov, Properties config, ResourceDecompressorFactory[] factories, List includes, List excludes) throws Exception { - long original = 0; - long compressed = 0; - for (ModuleData resource : resources.getContent()) { + long[] original = new long[1]; + long[] compressed = new long[1]; + resources.entries().forEach(resource -> { List includesPatterns = includes.stream() .map(Pattern::compile) .collect(Collectors.toList()); @@ -252,7 +252,7 @@ public class CompressorPluginTest { } prov.configure(props); final Map strings = new HashMap<>(); - PoolImpl inputResources = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() { + ModulePoolImpl inputResources = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() { @Override public int addString(String str) { int id = strID; @@ -267,32 +267,32 @@ public class CompressorPluginTest { } }); inputResources.add(resource); - Pool compressedResources = applyCompressor(prov, inputResources, resource, includesPatterns, excludesPatterns); - original += resource.getLength(); - compressed += compressedResources.get(resource.getPath()).getLength(); + ModulePool compressedResources = applyCompressor(prov, inputResources, resource, includesPatterns, excludesPatterns); + original[0] += resource.getLength(); + compressed[0] += compressedResources.findEntry(resource.getPath()).get().getLength(); applyDecompressors(factories, inputResources, compressedResources, strings, includesPatterns, excludesPatterns); - } + }); String compressors = Stream.of(factories) .map(Object::getClass) .map(Class::getSimpleName) .collect(Collectors.joining(", ")); - String size = "Compressed size: " + compressed + ", original size: " + original; + String size = "Compressed size: " + compressed[0] + ", original size: " + original[0]; System.out.println("Used " + compressors + ". " + size); - if (original <= compressed) { + if (original[0] <= compressed[0]) { throw new AssertionError("java.base not compressed."); } } - private Pool applyCompressor(Plugin plugin, - PoolImpl inputResources, - ModuleData res, + private ModulePool applyCompressor(Plugin plugin, + ModulePoolImpl inputResources, + ModuleEntry res, List includesPatterns, - List excludesPatterns) throws Exception { + List excludesPatterns) { TransformerPlugin compressor = (TransformerPlugin) plugin; - Pool compressedPool = new PoolImpl(ByteOrder.nativeOrder(), inputResources.getStringTable()); - compressor.visit(inputResources, compressedPool); + ModulePool compressedModulePool = new ModulePoolImpl(ByteOrder.nativeOrder(), inputResources.getStringTable()); + compressor.visit(inputResources, compressedModulePool); String path = res.getPath(); - ModuleData compressed = compressedPool.get(path); + ModuleEntry compressed = compressedModulePool.findEntry(path).get(); CompressedResourceHeader header = CompressedResourceHeader.readFromResource(ByteOrder.nativeOrder(), compressed.getBytes()); if (isIncluded(includesPatterns, excludesPatterns, path)) { @@ -310,29 +310,33 @@ public class CompressorPluginTest { } else if (header != null) { throw new AssertionError("Path should not be compressed: " + path); } - return compressedPool; + return compressedModulePool; } private void applyDecompressors(ResourceDecompressorFactory[] decompressors, - Pool inputResources, - Pool compressedResources, + ModulePool inputResources, + ModulePool compressedResources, Map strings, List includesPatterns, - List excludesPatterns) throws Exception { - for (ModuleData compressed : compressedResources.getContent()) { + List excludesPatterns) { + compressedResources.entries().forEach(compressed -> { CompressedResourceHeader header = CompressedResourceHeader.readFromResource( ByteOrder.nativeOrder(), compressed.getBytes()); String path = compressed.getPath(); - ModuleData orig = inputResources.get(path); + ModuleEntry orig = inputResources.findEntry(path).get(); if (!isIncluded(includesPatterns, excludesPatterns, path)) { - continue; + return; } byte[] decompressed = compressed.getBytes(); for (ResourceDecompressorFactory factory : decompressors) { - ResourceDecompressor decompressor = factory.newDecompressor(new Properties()); - decompressed = decompressor.decompress( + try { + ResourceDecompressor decompressor = factory.newDecompressor(new Properties()); + decompressed = decompressor.decompress( strings::get, decompressed, CompressedResourceHeader.getSize(), header.getUncompressedSize()); + } catch (Exception exp) { + throw new RuntimeException(exp); + } } if (decompressed.length != orig.getLength()) { @@ -345,7 +349,7 @@ public class CompressorPluginTest { throw new AssertionError("Decompressed and original differ at index " + i); } } - } + }); } private boolean isIncluded(List includesPatterns, List excludesPatterns, String path) { diff --git a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java index cde83aa2761..744d7a2ba25 100644 --- a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java +++ b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java @@ -35,12 +35,11 @@ import java.io.File; import java.nio.file.Files; import java.util.HashMap; import java.util.Map; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; -import jdk.tools.jlink.plugin.Pool.ModuleDataType; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; public class ExcludeFilesPluginTest { @@ -73,20 +72,20 @@ public class ExcludeFilesPluginTest { prop.put(ExcludeFilesPlugin.NAME, s); ExcludeFilesPlugin fplug = new ExcludeFilesPlugin(); fplug.configure(prop); - PoolImpl files = new PoolImpl(); - PoolImpl fresult = new PoolImpl(); - ModuleData f = Pool.newImageFile(module, "/" + module + "/" + sample, - ModuleDataType.CONFIG, new ByteArrayInputStream(new byte[0]), 0); + ModulePoolImpl files = new ModulePoolImpl(); + ModulePoolImpl fresult = new ModulePoolImpl(); + ModuleEntry f = ModuleEntry.create(module, "/" + module + "/" + sample, + ModuleEntry.Type.CONFIG, new ByteArrayInputStream(new byte[0]), 0); files.add(f); fplug.visit(files, fresult); if (exclude) { - if (fresult.getContent().contains(f)) { + if (fresult.contains(f)) { throw new Exception(sample + " should be excluded by " + s); } } else { - if (!fresult.getContent().contains(f)) { + if (!fresult.contains(f)) { throw new Exception(sample + " shouldn't be excluded by " + s); } } diff --git a/jdk/test/tools/jlink/plugins/ExcludePluginTest.java b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java index 0f508073288..c39e738e079 100644 --- a/jdk/test/tools/jlink/plugins/ExcludePluginTest.java +++ b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java @@ -34,11 +34,11 @@ import java.io.File; import java.nio.file.Files; import java.util.HashMap; import java.util.Map; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.plugins.ExcludePlugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class ExcludePluginTest { @@ -75,17 +75,17 @@ public class ExcludePluginTest { prop.put(ExcludePlugin.NAME, s); ExcludePlugin excludePlugin = new ExcludePlugin(); excludePlugin.configure(prop); - Pool resources = new PoolImpl(); - ModuleData resource = Pool.newResource(sample, new byte[0]); + ModulePool resources = new ModulePoolImpl(); + ModuleEntry resource = ModuleEntry.create(sample, new byte[0]); resources.add(resource); - Pool result = new PoolImpl(); + ModulePool result = new ModulePoolImpl(); excludePlugin.visit(resources, result); if (exclude) { - if (result.getContent().contains(resource)) { + if (result.contains(resource)) { throw new AssertionError(sample + " should be excluded by " + s); } } else { - if (!result.getContent().contains(resource)) { + if (!result.contains(resource)) { throw new AssertionError(sample + " shouldn't be excluded by " + s); } } diff --git a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java index 701368c3dd0..edc10702eb3 100644 --- a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java +++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java @@ -32,13 +32,12 @@ import java.io.ByteArrayInputStream; import java.util.HashMap; import java.util.Map; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.plugins.ExcludeVMPlugin; import jdk.tools.jlink.plugin.Plugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; -import jdk.tools.jlink.plugin.Pool.ModuleDataType; +import jdk.tools.jlink.plugin.ModulePool; +import jdk.tools.jlink.plugin.ModuleEntry; import jdk.tools.jlink.plugin.TransformerPlugin; public class ExcludeVMPluginTest { @@ -165,14 +164,14 @@ public class ExcludeVMPluginTest { private void doCheckVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception { // Create a pool with jvm.cfg and the input paths. byte[] jvmcfgContent = jvmcfg.getBytes(); - Pool pool = new PoolImpl(); - pool.add(Pool.newImageFile("java.base", "/java.base/native/jvm.cfg", - ModuleDataType.NATIVE_LIB, new ByteArrayInputStream(jvmcfgContent), jvmcfgContent.length)); + ModulePool pool = new ModulePoolImpl(); + pool.add(ModuleEntry.create("java.base", "/java.base/native/jvm.cfg", + ModuleEntry.Type.NATIVE_LIB, new ByteArrayInputStream(jvmcfgContent), jvmcfgContent.length)); for (String in : input) { - pool.add(Pool.newImageFile("java.base", in, - ModuleDataType.NATIVE_LIB, new ByteArrayInputStream(new byte[0]), 0)); + pool.add(ModuleEntry.create("java.base", in, + ModuleEntry.Type.NATIVE_LIB, new ByteArrayInputStream(new byte[0]), 0)); } - Pool out = new PoolImpl(); + ModulePool out = new ModulePoolImpl(); TransformerPlugin p = new ExcludeVMPlugin(); Map config = new HashMap<>(); @@ -182,22 +181,22 @@ public class ExcludeVMPluginTest { p.configure(config); p.visit(pool, out); - String newContent = new String(out.get("/java.base/native/jvm.cfg").stream().readAllBytes()); + String newContent = new String(out.findEntry("/java.base/native/jvm.cfg").get().stream().readAllBytes()); if (!expectdJvmCfg.equals(newContent)) { throw new Exception("Got content " + newContent + " expected " + expectdJvmCfg); } - if (out.getContent().size() != (expectedOutput.length + 1)) { - for (ModuleData m : out.getContent()) { + if (out.getEntryCount() != (expectedOutput.length + 1)) { + out.entries().forEach(m -> { System.err.println(m.getPath()); - } - throw new Exception("Invalid output size " + out.getContent().size() + " expected " + (expectedOutput.length + 1)); + }); + throw new Exception("Invalid output size " + out.getEntryCount() + " expected " + (expectedOutput.length + 1)); } - for (ModuleData md : out.getContent()) { + out.entries().forEach(md -> { if (md.getPath().equals("/java.base/native/jvm.cfg")) { - continue; + return; } boolean contained = false; for (String o : expectedOutput) { @@ -207,9 +206,9 @@ public class ExcludeVMPluginTest { } } if (!contained) { - throw new Exception(md.getPath() + " not expected"); + throw new RuntimeException(md.getPath() + " not expected"); } - } + }); } diff --git a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java index 5fecfec388b..a6fb749ba7f 100644 --- a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java +++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java @@ -26,6 +26,7 @@ * @summary Test files copy plugin * @author Jean-Francois Denise * @modules jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jlink.builder * jdk.jlink/jdk.tools.jlink.internal.plugins * @run main FileCopierPluginTest */ @@ -36,13 +37,12 @@ import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.builder.DefaultImageBuilder; import jdk.tools.jlink.internal.plugins.FileCopierPlugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; -import jdk.tools.jlink.plugin.Pool.ModuleDataType; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; public class FileCopierPluginTest { @@ -85,21 +85,20 @@ public class FileCopierPluginTest { Map conf = new HashMap<>(); conf.put(FileCopierPlugin.NAME, builder.toString()); plug.configure(conf); - Pool pool = new PoolImpl(); - plug.visit(new PoolImpl(), pool); - if (pool.getContent().size() != expected) { + ModulePool pool = new ModulePoolImpl(); + plug.visit(new ModulePoolImpl(), pool); + if (pool.getEntryCount() != expected) { throw new AssertionError("Wrong number of added files"); } - for (ModuleData f : pool.getContent()) { - if (!f.getType().equals(ModuleDataType.OTHER)) { + pool.entries().forEach(f -> { + if (!f.getType().equals(ModuleEntry.Type.OTHER)) { throw new AssertionError("Invalid type " + f.getType() + " for file " + f.getPath()); } if (f.stream() == null) { throw new AssertionError("Null stream for file " + f.getPath()); } - - } + }); Path root = new File(".").toPath(); DefaultImageBuilder imgbuilder = new DefaultImageBuilder(root); imgbuilder.storeFiles(pool); diff --git a/jdk/test/tools/jlink/plugins/LastSorterTest.java b/jdk/test/tools/jlink/plugins/LastSorterTest.java index 100ca1e4674..0dc27b44ec8 100644 --- a/jdk/test/tools/jlink/plugins/LastSorterTest.java +++ b/jdk/test/tools/jlink/plugins/LastSorterTest.java @@ -26,6 +26,7 @@ * @summary Test last sorter property * @author Jean-Francois Denise * @modules jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jlink * @run main/othervm LastSorterTest */ @@ -40,12 +41,12 @@ import java.util.Set; import jdk.tools.jlink.internal.ImagePluginConfiguration; import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.internal.ImagePluginStack; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.Jlink; import jdk.tools.jlink.Jlink.PluginsConfiguration; import jdk.tools.jlink.plugin.Plugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; public class LastSorterTest { @@ -80,7 +81,7 @@ public class LastSorterTest { ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config); // check order - PoolImpl res = fillOutResourcePool(); + ModulePoolImpl res = fillOutResourceModulePool(); try { stack.visitResources(res); @@ -91,18 +92,18 @@ public class LastSorterTest { } } - private PoolImpl fillOutResourcePool() throws Exception { - PoolImpl res = new PoolImpl(); - res.add(Pool.newResource("/eee/bbb/res1.class", new byte[90])); - res.add(Pool.newResource("/aaaa/bbb/res2.class", new byte[90])); - res.add(Pool.newResource("/bbb/aa/res1.class", new byte[90])); - res.add(Pool.newResource("/aaaa/bbb/res3.class", new byte[90])); - res.add(Pool.newResource("/bbb/aa/res2.class", new byte[90])); - res.add(Pool.newResource("/fff/bbb/res1.class", new byte[90])); - res.add(Pool.newResource("/aaaa/bbb/res1.class", new byte[90])); - res.add(Pool.newResource("/bbb/aa/res3.class", new byte[90])); - res.add(Pool.newResource("/ccc/bbb/res1.class", new byte[90])); - res.add(Pool.newResource("/ddd/bbb/res1.class", new byte[90])); + private ModulePoolImpl fillOutResourceModulePool() throws Exception { + ModulePoolImpl res = new ModulePoolImpl(); + res.add(ModuleEntry.create("/eee/bbb/res1.class", new byte[90])); + res.add(ModuleEntry.create("/aaaa/bbb/res2.class", new byte[90])); + res.add(ModuleEntry.create("/bbb/aa/res1.class", new byte[90])); + res.add(ModuleEntry.create("/aaaa/bbb/res3.class", new byte[90])); + res.add(ModuleEntry.create("/bbb/aa/res2.class", new byte[90])); + res.add(ModuleEntry.create("/fff/bbb/res1.class", new byte[90])); + res.add(ModuleEntry.create("/aaaa/bbb/res1.class", new byte[90])); + res.add(ModuleEntry.create("/bbb/aa/res3.class", new byte[90])); + res.add(ModuleEntry.create("/ccc/bbb/res1.class", new byte[90])); + res.add(ModuleEntry.create("/ddd/bbb/res1.class", new byte[90])); return res; } @@ -124,7 +125,7 @@ public class LastSorterTest { ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config); // check order - PoolImpl res = fillOutResourcePool(); + ModulePoolImpl res = fillOutResourceModulePool(); stack.visitResources(res); } @@ -159,7 +160,7 @@ public class LastSorterTest { ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config); // check order - PoolImpl res = fillOutResourcePool(); + ModulePoolImpl res = fillOutResourceModulePool(); try { stack.visitResources(res); throw new AssertionError("Order was changed after the last sorter, but no exception occurred"); @@ -178,17 +179,17 @@ public class LastSorterTest { } @Override - public void visit(Pool resources, Pool output) { - List paths = new ArrayList<>(); - for (ModuleData res : resources.getContent()) { + public void visit(ModulePool resources, ModulePool output) { + List paths = new ArrayList<>(); + resources.entries().forEach(res -> { if (res.getPath().startsWith(starts)) { paths.add(0, res); } else { paths.add(res); } - } + }); - for (ModuleData r : paths) { + for (ModuleEntry r : paths) { output.add(r); } } @@ -199,9 +200,9 @@ public class LastSorterTest { } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.TRANSFORMER); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.TRANSFORMER); return Collections.unmodifiableSet(set); } diff --git a/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java b/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java index cbf418669c0..701736139c6 100644 --- a/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java +++ b/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java @@ -36,11 +36,12 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; -import jdk.tools.jlink.internal.PoolImpl; +import java.util.stream.Collectors; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.plugins.OrderResourcesPlugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; public class OrderResourcesPluginTest { @@ -50,52 +51,52 @@ public class OrderResourcesPluginTest { } public void test() throws Exception { - ModuleData[] array = { - Pool.newResource("/module1/toto1.class", new byte[0]), - Pool.newResource("/module2/toto2.class", new byte[0]), - Pool.newResource("/module3/toto3.class", new byte[0]), - Pool.newResource("/module3/toto3/module-info.class", new byte[0]), - Pool.newResource("/zazou/toto.class", new byte[0]), - Pool.newResource("/module4/zazou.class", new byte[0]), - Pool.newResource("/module5/toto5.class", new byte[0]), - Pool.newResource("/module6/toto6/module-info.class", new byte[0]) + ModuleEntry[] array = { + ModuleEntry.create("/module1/toto1.class", new byte[0]), + ModuleEntry.create("/module2/toto2.class", new byte[0]), + ModuleEntry.create("/module3/toto3.class", new byte[0]), + ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]), + ModuleEntry.create("/zazou/toto.class", new byte[0]), + ModuleEntry.create("/module4/zazou.class", new byte[0]), + ModuleEntry.create("/module5/toto5.class", new byte[0]), + ModuleEntry.create("/module6/toto6/module-info.class", new byte[0]) }; - ModuleData[] sorted = { - Pool.newResource("/zazou/toto.class", new byte[0]), - Pool.newResource("/module3/toto3/module-info.class", new byte[0]), - Pool.newResource("/module6/toto6/module-info.class", new byte[0]), - Pool.newResource("/module1/toto1.class", new byte[0]), - Pool.newResource("/module2/toto2.class", new byte[0]), - Pool.newResource("/module3/toto3.class", new byte[0]), - Pool.newResource("/module4/zazou.class", new byte[0]), - Pool.newResource("/module5/toto5.class", new byte[0]) + ModuleEntry[] sorted = { + ModuleEntry.create("/zazou/toto.class", new byte[0]), + ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]), + ModuleEntry.create("/module6/toto6/module-info.class", new byte[0]), + ModuleEntry.create("/module1/toto1.class", new byte[0]), + ModuleEntry.create("/module2/toto2.class", new byte[0]), + ModuleEntry.create("/module3/toto3.class", new byte[0]), + ModuleEntry.create("/module4/zazou.class", new byte[0]), + ModuleEntry.create("/module5/toto5.class", new byte[0]) }; - ModuleData[] sorted2 = { - Pool.newResource("/module5/toto5.class", new byte[0]), - Pool.newResource("/module6/toto6/module-info.class", new byte[0]), - Pool.newResource("/module4/zazou.class", new byte[0]), - Pool.newResource("/module3/toto3.class", new byte[0]), - Pool.newResource("/module3/toto3/module-info.class", new byte[0]), - Pool.newResource("/module1/toto1.class", new byte[0]), - Pool.newResource("/module2/toto2.class", new byte[0]), - Pool.newResource("/zazou/toto.class", new byte[0]) + ModuleEntry[] sorted2 = { + ModuleEntry.create("/module5/toto5.class", new byte[0]), + ModuleEntry.create("/module6/toto6/module-info.class", new byte[0]), + ModuleEntry.create("/module4/zazou.class", new byte[0]), + ModuleEntry.create("/module3/toto3.class", new byte[0]), + ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]), + ModuleEntry.create("/module1/toto1.class", new byte[0]), + ModuleEntry.create("/module2/toto2.class", new byte[0]), + ModuleEntry.create("/zazou/toto.class", new byte[0]) }; - Pool resources = new PoolImpl(); - for (ModuleData r : array) { + ModulePool resources = new ModulePoolImpl(); + for (ModuleEntry r : array) { resources.add(r); } { - Pool out = new PoolImpl(); + ModulePool out = new ModulePoolImpl(); Map config = new HashMap<>(); config.put(OrderResourcesPlugin.NAME, "/zazou/*,*/module-info.class"); TransformerPlugin p = new OrderResourcesPlugin(); p.configure(config); p.visit(resources, out); - check(out.getContent(), sorted); + check(out.entries().collect(Collectors.toList()), sorted); } { @@ -112,26 +113,26 @@ public class OrderResourcesPluginTest { } Files.write(order.toPath(), builder.toString().getBytes()); - Pool out = new PoolImpl(); + ModulePool out = new ModulePoolImpl(); Map config = new HashMap<>(); config.put(OrderResourcesPlugin.NAME, "@" + order.getAbsolutePath()); TransformerPlugin p = new OrderResourcesPlugin(); p.configure(config); p.visit(resources, out); - check(out.getContent(), sorted2); + check(out.entries().collect(Collectors.toList()), sorted2); } } - private void check(Collection outResources, - ModuleData[] sorted) { + private void check(Collection outResources, + ModuleEntry[] sorted) { if (outResources.size() != sorted.length) { throw new AssertionError("Wrong number of resources:\n" + "expected: " + Arrays.toString(sorted) + ",\n" + " got: " + outResources); } int i = 0; - for (ModuleData r : outResources) { + for (ModuleEntry r : outResources) { System.err.println("Resource: " + r); if (!sorted[i].getPath().equals(r.getPath())) { throw new AssertionError("Resource not properly sorted, difference at: " + i + "\n" diff --git a/jdk/test/tools/jlink/plugins/PluginOrderTest.java b/jdk/test/tools/jlink/plugins/PluginOrderTest.java index 42655d408fe..4c9f2c2241d 100644 --- a/jdk/test/tools/jlink/plugins/PluginOrderTest.java +++ b/jdk/test/tools/jlink/plugins/PluginOrderTest.java @@ -44,8 +44,8 @@ import java.util.Set; import jdk.tools.jlink.internal.PluginOrderingGraph; import jdk.tools.jlink.plugin.Plugin; -import jdk.tools.jlink.plugin.Plugin.CATEGORY; -import jdk.tools.jlink.plugin.Pool; +import jdk.tools.jlink.plugin.Plugin.Category; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; public class PluginOrderTest { @@ -96,8 +96,8 @@ public class PluginOrderTest { set.add("plug2"); List plugins = new ArrayList<>(); plugins.add(new Plug("plug2", Collections.emptySet(), Collections.emptySet(), - CATEGORY.TRANSFORMER)); - plugins.add(new Plug("plug1", set, Collections.emptySet(), CATEGORY.TRANSFORMER)); + Category.TRANSFORMER)); + plugins.add(new Plug("plug1", set, Collections.emptySet(), Category.TRANSFORMER)); List ordered = PluginOrderingGraph.sort(plugins); if (ordered.get(0) != plugins.get(1) || ordered.get(1) != plugins.get(0)) { throw new Exception("Invalid sorting"); @@ -108,32 +108,32 @@ public class PluginOrderTest { Set lst1 = new HashSet<>(); lst1.add("plug2"); lst1.add("plug3"); - Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), Category.TRANSFORMER); - Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); Set lst3 = new HashSet<>(); lst3.add("plug4"); lst3.add("plug6"); - Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), Category.TRANSFORMER); - Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); Set lst5 = new HashSet<>(); lst5.add("plug3"); lst5.add("plug1"); lst5.add("plug2"); lst5.add("plug6"); - Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), Category.TRANSFORMER); Set lst6 = new HashSet<>(); lst6.add("plug4"); lst6.add("plug2"); - Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), Category.TRANSFORMER); - Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); - Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); List plugins = new ArrayList<>(); plugins.add(p1); @@ -153,11 +153,11 @@ public class PluginOrderTest { set2.add("plug1"); List plugins = new ArrayList<>(); plugins.add(new Plug("plug2", set2, Collections.emptySet(), - CATEGORY.TRANSFORMER)); + Category.TRANSFORMER)); Set set1 = new HashSet<>(); set1.add("plug2"); - plugins.add(new Plug("plug1", set1, Collections.emptySet(), CATEGORY.TRANSFORMER)); + plugins.add(new Plug("plug1", set1, Collections.emptySet(), Category.TRANSFORMER)); PluginOrderingGraph.sort(plugins); } @@ -166,31 +166,31 @@ public class PluginOrderTest { Set lst1 = new HashSet<>(); lst1.add("plug2"); lst1.add("plug3"); - Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), Category.TRANSFORMER); - Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); Set lst3 = new HashSet<>(); lst3.add("plug4"); lst3.add("plug6"); - Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), Category.TRANSFORMER); - Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); Set lst5 = new HashSet<>(); lst5.add("plug3"); lst5.add("plug1"); lst5.add("plug2"); - Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), Category.TRANSFORMER); Set lst6 = new HashSet<>(); lst6.add("plug4"); lst6.add("plug1"); - Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), Category.TRANSFORMER); - Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); - Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); List plugins = new ArrayList<>(); plugins.add(p1); @@ -208,8 +208,8 @@ public class PluginOrderTest { Set lst1 = new HashSet<>(); lst1.add("plug2"); lst1.add("plug3"); - Plugin p = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER); - Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER); + Plugin p = new Plug("plug1", lst1, Collections.emptySet(), Category.TRANSFORMER); + Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER); Set lst3 = new HashSet<>(); lst3.add("plug2"); @@ -217,7 +217,7 @@ public class PluginOrderTest { Set lst4 = new HashSet<>(); lst4.add("plug1"); - Plugin p3 = new Plug("plug3", lst4, lst3, CATEGORY.TRANSFORMER); + Plugin p3 = new Plug("plug3", lst4, lst3, Category.TRANSFORMER); List plugins = new ArrayList<>(); plugins.add(p); plugins.add(p2); @@ -229,10 +229,10 @@ public class PluginOrderTest { private final Set isBefore; private final Set isAfter; - private final CATEGORY category; + private final Category category; private final String name; - private Plug(String name, Set isBefore, Set isAfter, CATEGORY category) { + private Plug(String name, Set isBefore, Set isAfter, Category category) { this.name = name; this.isBefore = isBefore; this.isAfter = isAfter; @@ -255,12 +255,12 @@ public class PluginOrderTest { } @Override - public void visit(Pool in, Pool out) { + public void visit(ModulePool in, ModulePool out) { } @Override - public Set getType() { + public Set getType() { return Collections.singleton(category); } diff --git a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java index 525fb0b5ce2..5b8ed2d6c83 100644 --- a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java +++ b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java @@ -26,6 +26,7 @@ * @summary Negative test for ImagePluginStack. * @author Andrei Eremeev * @modules jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jlink * @run main/othervm PluginsNegativeTest */ import java.lang.reflect.Layer; @@ -39,11 +40,12 @@ import java.util.Set; import jdk.tools.jlink.internal.ImagePluginConfiguration; import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.internal.ImagePluginStack; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.Jlink; import jdk.tools.jlink.Jlink.PluginsConfiguration; import jdk.tools.jlink.plugin.Plugin; -import jdk.tools.jlink.plugin.Pool; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; public class PluginsNegativeTest { @@ -96,8 +98,8 @@ public class PluginsNegativeTest { plugins.add(createPlugin("plugin")); ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new PluginsConfiguration(plugins, null, null)); - PoolImpl inResources = new PoolImpl(); - inResources.add(Pool.newResource("/aaa/bbb/A", new byte[10])); + ModulePoolImpl inResources = new ModulePoolImpl(); + inResources.add(ModuleEntry.create("/aaa/bbb/A", new byte[10])); try { stack.visitResources(inResources); throw new AssertionError("Exception expected when output resource is empty"); @@ -110,8 +112,8 @@ public class PluginsNegativeTest { plugins.add(createPlugin("plugin")); ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new PluginsConfiguration(plugins, null, null)); - PoolImpl inResources = new PoolImpl(); - PoolImpl outResources = (PoolImpl) stack.visitResources(inResources); + ModulePoolImpl inResources = new ModulePoolImpl(); + ModulePoolImpl outResources = (ModulePoolImpl) stack.visitResources(inResources); if (!outResources.isEmpty()) { throw new AssertionError("Output resource is not empty"); } @@ -126,7 +128,7 @@ public class PluginsNegativeTest { } @Override - public void visit(Pool inResources, Pool outResources) { + public void visit(ModulePool inResources, ModulePool outResources) { // do nothing } @@ -136,9 +138,9 @@ public class PluginsNegativeTest { } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.TRANSFORMER); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.TRANSFORMER); return Collections.unmodifiableSet(set); } diff --git a/jdk/test/tools/jlink/plugins/PrevisitorTest.java b/jdk/test/tools/jlink/plugins/PrevisitorTest.java index 16d79f0c068..1f721d66d5f 100644 --- a/jdk/test/tools/jlink/plugins/PrevisitorTest.java +++ b/jdk/test/tools/jlink/plugins/PrevisitorTest.java @@ -26,6 +26,7 @@ * @summary Test previsitor * @author Andrei Eremeev * @modules jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jlink * @run main/othervm PrevisitorTest */ import java.nio.ByteOrder; @@ -36,19 +37,20 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import jdk.tools.jlink.internal.ImagePluginConfiguration; import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.internal.ImagePluginStack; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.ResourcePrevisitor; import jdk.tools.jlink.internal.StringTable; import jdk.tools.jlink.Jlink; import jdk.tools.jlink.plugin.Plugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; public class PrevisitorTest { @@ -68,17 +70,17 @@ public class PrevisitorTest { plugins.add(createPlugin(CustomPlugin.NAME)); ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new Jlink.PluginsConfiguration(plugins, null, null)); - PoolImpl inResources = new PoolImpl(ByteOrder.nativeOrder(), new CustomStringTable()); - inResources.add(Pool.newResource("/aaa/bbb/res1.class", new byte[90])); - inResources.add(Pool.newResource("/aaa/bbb/res2.class", new byte[90])); - inResources.add(Pool.newResource("/aaa/bbb/res3.class", new byte[90])); - inResources.add(Pool.newResource("/aaa/ddd/res1.class", new byte[90])); - inResources.add(Pool.newResource("/aaa/res1.class", new byte[90])); - Pool outResources = stack.visitResources(inResources); - Collection input = inResources.getContent().stream() + ModulePoolImpl inResources = new ModulePoolImpl(ByteOrder.nativeOrder(), new CustomStringTable()); + inResources.add(ModuleEntry.create("/aaa/bbb/res1.class", new byte[90])); + inResources.add(ModuleEntry.create("/aaa/bbb/res2.class", new byte[90])); + inResources.add(ModuleEntry.create("/aaa/bbb/res3.class", new byte[90])); + inResources.add(ModuleEntry.create("/aaa/ddd/res1.class", new byte[90])); + inResources.add(ModuleEntry.create("/aaa/res1.class", new byte[90])); + ModulePool outResources = stack.visitResources(inResources); + Collection input = inResources.entries() .map(Object::toString) .collect(Collectors.toList()); - Collection output = outResources.getContent().stream() + Collection output = outResources.entries() .map(Object::toString) .collect(Collectors.toList()); if (!input.equals(output)) { @@ -114,19 +116,20 @@ public class PrevisitorTest { private boolean isPrevisitCalled = false; @Override - public void visit(Pool inResources, Pool outResources) { + public void visit(ModulePool inResources, ModulePool outResources) { if (!isPrevisitCalled) { throw new AssertionError("Previsit was not called"); } CustomStringTable table = (CustomStringTable) - ((PoolImpl) inResources).getStringTable(); + ((ModulePoolImpl) inResources).getStringTable(); if (table.size() == 0) { throw new AssertionError("Table is empty"); } Map count = new HashMap<>(); for (int i = 0; i < table.size(); ++i) { String s = table.getString(i); - if (inResources.get(s) != null) { + Optional e = inResources.findEntry(s); + if (e.isPresent()) { throw new AssertionError(); } count.compute(s, (k, c) -> 1 + (c == null ? 0 : c)); @@ -136,9 +139,9 @@ public class PrevisitorTest { throw new AssertionError("Expected one entry in the table, got: " + v + " for " + k); } }); - for (ModuleData r : inResources.getContent()) { + inResources.entries().forEach(r -> { outResources.add(r); - } + }); } @Override @@ -147,21 +150,21 @@ public class PrevisitorTest { } @Override - public void previsit(Pool resources, StringTable strings) { + public void previsit(ModulePool resources, StringTable strings) { isPrevisitCalled = true; - for (ModuleData r : resources.getContent()) { + resources.entries().forEach(r -> { String s = r.getPath(); int lastIndexOf = s.lastIndexOf('/'); if (lastIndexOf >= 0) { strings.addString(s.substring(0, lastIndexOf)); } - } + }); } @Override - public Set getType() { - Set set = new HashSet<>(); - set.add(CATEGORY.TRANSFORMER); + public Set getType() { + Set set = new HashSet<>(); + set.add(Category.TRANSFORMER); return Collections.unmodifiableSet(set); } } diff --git a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java index 786da460990..c02a8e6db0c 100644 --- a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java +++ b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java @@ -38,6 +38,8 @@ * @run main StringSharingPluginTest */ +import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.file.Files; @@ -50,11 +52,11 @@ import java.util.function.Consumer; import jdk.internal.jimage.decompressor.CompressedResourceHeader; import jdk.internal.jimage.decompressor.StringSharingDecompressor; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.StringTable; import jdk.tools.jlink.internal.plugins.StringSharingPlugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; import tests.Helper; import tests.JImageValidator; @@ -78,7 +80,7 @@ public class StringSharingPluginTest { Map map = new HashMap<>(); Map reversedMap = new HashMap<>(); - PoolImpl resources = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() { + ModulePoolImpl resources = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() { @Override public int addString(String str) { Integer id = map.get(str); @@ -104,7 +106,7 @@ public class StringSharingPluginTest { byte[] content = Files.readAllBytes(p); String path = p.toString().replace('\\', '/'); path = path.substring("/modules".length()); - ModuleData res = Pool.newResource(path, content); + ModuleEntry res = ModuleEntry.create(path, content); resources.add(res); } catch (Exception ex) { throw new RuntimeException(ex); @@ -115,19 +117,23 @@ public class StringSharingPluginTest { stream.forEach(c); } TransformerPlugin plugin = new StringSharingPlugin(); - PoolImpl result = new PoolImpl(resources.getByteOrder(), resources.getStringTable()); + ModulePoolImpl result = new ModulePoolImpl(resources.getByteOrder(), resources.getStringTable()); plugin.visit(resources, result); if (result.isEmpty()) { throw new AssertionError("No result"); } - for (ModuleData res : result.getContent()) { + result.entries().forEach(res -> { if (res.getPath().endsWith(".class")) { - byte[] uncompacted = StringSharingDecompressor.normalize(reversedMap::get, res.getBytes(), + try { + byte[] uncompacted = StringSharingDecompressor.normalize(reversedMap::get, res.getBytes(), CompressedResourceHeader.getSize()); - JImageValidator.readClass(uncompacted); + JImageValidator.readClass(uncompacted); + } catch (IOException exp) { + throw new UncheckedIOException(exp); + } } - } + }); } } diff --git a/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java index fd8acae896c..d3617db6f8a 100644 --- a/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java +++ b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java @@ -54,10 +54,10 @@ import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.Method; import java.util.HashMap; import java.util.Map; -import jdk.tools.jlink.internal.PoolImpl; +import jdk.tools.jlink.internal.ModulePoolImpl; import jdk.tools.jlink.internal.plugins.StripDebugPlugin; -import jdk.tools.jlink.plugin.Pool; -import jdk.tools.jlink.plugin.Pool.ModuleData; +import jdk.tools.jlink.plugin.ModuleEntry; +import jdk.tools.jlink.plugin.ModulePool; import jdk.tools.jlink.plugin.TransformerPlugin; import tests.Helper; @@ -106,7 +106,7 @@ public class StripDebugPluginTest { path = path.replace('\\', '/'); StripDebugPlugin debug = new StripDebugPlugin(); debug.configure(new HashMap<>()); - ModuleData result1 = stripDebug(debug, Pool.newResource(path,content), path, infoPath, moduleInfo); + ModuleEntry result1 = stripDebug(debug, ModuleEntry.create(path,content), path, infoPath, moduleInfo); if (!path.endsWith("module-info.class")) { if (result1.getLength() >= content.length) { @@ -116,7 +116,7 @@ public class StripDebugPluginTest { checkDebugAttributes(result1.getBytes()); } - ModuleData result2 = stripDebug(debug, result1, path, infoPath, moduleInfo); + ModuleEntry result2 = stripDebug(debug, result1, path, infoPath, moduleInfo); if (result1.getLength() != result2.getLength()) { throw new AssertionError("removing debug info twice reduces class size of " + path); @@ -124,18 +124,18 @@ public class StripDebugPluginTest { checkDebugAttributes(result1.getBytes()); } - private ModuleData stripDebug(TransformerPlugin debug, ModuleData classResource, + private ModuleEntry stripDebug(TransformerPlugin debug, ModuleEntry classResource, String path, String infoPath, byte[] moduleInfo) throws Exception { - Pool resources = new PoolImpl(); + ModulePool resources = new ModulePoolImpl(); resources.add(classResource); if (!path.endsWith("module-info.class")) { - ModuleData res2 = Pool.newResource(infoPath, moduleInfo); + ModuleEntry res2 = ModuleEntry.create(infoPath, moduleInfo); resources.add(res2); } - Pool results = new PoolImpl(); + ModulePool results = new ModulePoolImpl(); debug.visit(resources, results); System.out.println(classResource.getPath()); - return results.get(classResource.getPath()); + return results.findEntry(classResource.getPath()).get(); } private void checkDebugAttributes(byte[] strippedClassFile) throws IOException, ConstantPoolException { diff --git a/jdk/test/tools/launcher/FXLauncherTest.java b/jdk/test/tools/launcher/FXLauncherTest.java index 0ee9d981cda..7fec8d59d36 100644 --- a/jdk/test/tools/launcher/FXLauncherTest.java +++ b/jdk/test/tools/launcher/FXLauncherTest.java @@ -29,6 +29,7 @@ * jfx app class, a main-class for the manifest, a bogus one and none. * All should execute except the incorrect fx app class entries. * @run main/othervm FXLauncherTest + * @key intermittent */ import java.io.File; import java.io.IOException; diff --git a/jdk/test/tools/launcher/modules/patch/PatchTest.java b/jdk/test/tools/launcher/modules/patch/basic/PatchTest.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/PatchTest.java rename to jdk/test/tools/launcher/modules/patch/basic/PatchTest.java diff --git a/jdk/test/tools/launcher/modules/patch/src/test/jdk/test/Main.java b/jdk/test/tools/launcher/modules/patch/basic/src/test/jdk/test/Main.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src/test/jdk/test/Main.java rename to jdk/test/tools/launcher/modules/patch/basic/src/test/jdk/test/Main.java diff --git a/jdk/test/tools/launcher/modules/patch/src/test/module-info.java b/jdk/test/tools/launcher/modules/patch/basic/src/test/module-info.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src/test/module-info.java rename to jdk/test/tools/launcher/modules/patch/basic/src/test/module-info.java diff --git a/jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/Annotation.java b/jdk/test/tools/launcher/modules/patch/basic/src1/java.base/java/text/Annotation.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/Annotation.java rename to jdk/test/tools/launcher/modules/patch/basic/src1/java.base/java/text/Annotation.java diff --git a/jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/AnnotationBuddy.java b/jdk/test/tools/launcher/modules/patch/basic/src1/java.base/java/text/AnnotationBuddy.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/AnnotationBuddy.java rename to jdk/test/tools/launcher/modules/patch/basic/src1/java.base/java/text/AnnotationBuddy.java diff --git a/jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/Main.java b/jdk/test/tools/launcher/modules/patch/basic/src1/jdk.compiler/com/sun/tools/javac/Main.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/Main.java rename to jdk/test/tools/launcher/modules/patch/basic/src1/jdk.compiler/com/sun/tools/javac/Main.java diff --git a/jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/MainBuddy.java b/jdk/test/tools/launcher/modules/patch/basic/src1/jdk.compiler/com/sun/tools/javac/MainBuddy.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/MainBuddy.java rename to jdk/test/tools/launcher/modules/patch/basic/src1/jdk.compiler/com/sun/tools/javac/MainBuddy.java diff --git a/jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClient.java b/jdk/test/tools/launcher/modules/patch/basic/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClient.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClient.java rename to jdk/test/tools/launcher/modules/patch/basic/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClient.java diff --git a/jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClientBuddy.java b/jdk/test/tools/launcher/modules/patch/basic/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClientBuddy.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClientBuddy.java rename to jdk/test/tools/launcher/modules/patch/basic/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClientBuddy.java diff --git a/jdk/test/tools/launcher/modules/patch/src2/java.base/java/lang2/Object.java b/jdk/test/tools/launcher/modules/patch/basic/src2/java.base/java/lang2/Object.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src2/java.base/java/lang2/Object.java rename to jdk/test/tools/launcher/modules/patch/basic/src2/java.base/java/lang2/Object.java diff --git a/jdk/test/tools/launcher/modules/patch/src2/jdk.compiler/com/sun/tools/javac2/Main.java b/jdk/test/tools/launcher/modules/patch/basic/src2/jdk.compiler/com/sun/tools/javac2/Main.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src2/jdk.compiler/com/sun/tools/javac2/Main.java rename to jdk/test/tools/launcher/modules/patch/basic/src2/jdk.compiler/com/sun/tools/javac2/Main.java diff --git a/jdk/test/tools/launcher/modules/patch/src2/jdk.naming.dns/com/sun/jndi/dns2/Zone.java b/jdk/test/tools/launcher/modules/patch/basic/src2/jdk.naming.dns/com/sun/jndi/dns2/Zone.java similarity index 100% rename from jdk/test/tools/launcher/modules/patch/src2/jdk.naming.dns/com/sun/jndi/dns2/Zone.java rename to jdk/test/tools/launcher/modules/patch/basic/src2/jdk.naming.dns/com/sun/jndi/dns2/Zone.java diff --git a/jdk/test/tools/launcher/modules/patch/systemmodules/PatchSystemModules.java b/jdk/test/tools/launcher/modules/patch/systemmodules/PatchSystemModules.java new file mode 100644 index 00000000000..0e5345aefb3 --- /dev/null +++ b/jdk/test/tools/launcher/modules/patch/systemmodules/PatchSystemModules.java @@ -0,0 +1,225 @@ +/** + * 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 8157068 + * @summary Patch java.base and user module with Hashes attribute tied with + * other module. + * @library /lib/testlibrary + * @modules jdk.compiler + * @build CompilerUtils + * @run testng PatchSystemModules + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import jdk.testlibrary.FileUtils; +import jdk.testlibrary.JDKToolFinder; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import static jdk.testlibrary.ProcessTools.executeCommand; +import static org.testng.Assert.*; + +public class PatchSystemModules { + private static final String JAVA_HOME = System.getProperty("java.home"); + + private static final Path TEST_SRC = Paths.get(System.getProperty("test.src")); + private static final Path PATCH_SRC_DIR = TEST_SRC.resolve("src1"); + + private static final Path JMODS = Paths.get(JAVA_HOME, "jmods"); + private static final Path MODS_DIR = Paths.get("mods"); + private static final Path JARS_DIR = Paths.get("jars"); + private static final Path PATCH_DIR = Paths.get("patches"); + private static final Path IMAGE = Paths.get("image"); + + private static final String JAVA_BASE = "java.base"; + private final String[] modules = new String[] { "m1", "m2" }; + + @BeforeTest + private void setup() throws Throwable { + Path src = TEST_SRC.resolve("src"); + for (String name : modules) { + assertTrue(CompilerUtils.compile(src.resolve(name), + MODS_DIR, + "-modulesourcepath", src.toString())); + } + + // compile patched source + assertTrue(CompilerUtils.compile(PATCH_SRC_DIR.resolve(JAVA_BASE), + PATCH_DIR.resolve(JAVA_BASE), + "-Xmodule:java.base")); + assertTrue(CompilerUtils.compile(PATCH_SRC_DIR.resolve("m2"), + PATCH_DIR.resolve("m2"))); + + // create an image with only m1 and m2 + if (Files.exists(JMODS)) { + // create an image with m1,m2 + createImage(); + } + } + + @Test + public void test() throws Throwable { + Path patchedJavaBase = PATCH_DIR.resolve(JAVA_BASE); + Path patchedM2 = PATCH_DIR.resolve("m2"); + + Path home = Paths.get(JAVA_HOME); + runTest(home, + "-mp", MODS_DIR.toString(), + "-m", "m1/p1.Main", "1"); + runTest(home, + "-Xpatch:java.base=" + patchedJavaBase.toString(), + "-mp", MODS_DIR.toString(), + "-m", "m1/p1.Main", "1"); + + runTest(home, + "-Xpatch:m2=" + patchedM2.toString(), + "-mp", MODS_DIR.toString(), + "-m", "m1/p1.Main", "2"); + } + + @Test + public void testImage() throws Throwable { + if (Files.notExists(JMODS)) + return; + + Path patchedJavaBase = PATCH_DIR.resolve(JAVA_BASE); + Path patchedM2 = PATCH_DIR.resolve("m2"); + + runTest(IMAGE, + "-m", "m1/p1.Main", "1"); + runTest(IMAGE, + "-Xpatch:java.base=" + patchedJavaBase.toString(), + "-m", "m1/p1.Main", "1"); + runTest(IMAGE, + "-Xpatch:m2=" + patchedM2.toString(), + "-m", "m1/p1.Main", "2"); + } + + @Test + public void upgradeTiedModule() throws Throwable { + if (Files.notExists(JMODS)) + return; + + Path m1 = MODS_DIR.resolve("m1.jar"); + + // create another m1.jar + jar("--create", + "--file=" + m1.toString(), + "-C", MODS_DIR.resolve("m1").toString(), "."); + + // Fail to upgrade m1.jar with mismatched hash + runTestWithExitCode(getJava(IMAGE), + "-upgrademodulepath", m1.toString(), + "-m", "m1/p1.Main"); + + runTestWithExitCode(getJava(IMAGE), + "-Xpatch:java.base=" + PATCH_DIR.resolve(JAVA_BASE).toString(), + "-upgrademodulepath", m1.toString(), + "-m", "m1/p1.Main", "1"); + } + + private void runTestWithExitCode(String... options) throws Throwable { + assertTrue(executeCommand(options) + .outputTo(System.out) + .errorTo(System.out) + .shouldContain("differs to expected hash") + .getExitValue() != 0); + } + + private void runTest(Path image, String... opts) throws Throwable { + String[] options = + Stream.concat(Stream.of(getJava(image)), + Stream.of(opts)) + .toArray(String[]::new); + + ProcessBuilder pb = new ProcessBuilder(options); + int exitValue = executeCommand(pb) + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + static void createImage() throws Throwable { + FileUtils.deleteFileTreeUnchecked(JARS_DIR); + FileUtils.deleteFileTreeUnchecked(IMAGE); + + Files.createDirectories(JARS_DIR); + Path m1 = JARS_DIR.resolve("m1.jar"); + Path m2 = JARS_DIR.resolve("m2.jar"); + + // hash m1 in m2's Hashes attribute + jar("--create", + "--file=" + m1.toString(), + "-C", MODS_DIR.resolve("m1").toString(), "."); + + jar("--create", + "--file=" + m2.toString(), + "--modulepath", JARS_DIR.toString(), + "--hash-modules", "m1", + "-C", MODS_DIR.resolve("m2").toString(), "."); + + + String mpath = JARS_DIR.toString() + File.pathSeparator + JMODS.toString(); + execTool("jlink", "--modulepath", mpath, + "--addmods", "m1", + "--output", IMAGE.toString()); + } + + static void jar(String... args) throws Throwable { + execTool("jar", args); + } + + static void execTool(String tool, String... args) throws Throwable { + String path = JDKToolFinder.getJDKTool(tool); + List commands = new ArrayList<>(); + commands.add(path); + Stream.of(args).forEach(commands::add); + ProcessBuilder pb = new ProcessBuilder(commands); + int exitValue = executeCommand(pb) + .outputTo(System.out) + .errorTo(System.out) + .shouldNotContain("no module is recorded in hash") + .getExitValue(); + + assertTrue(exitValue == 0); + } + + static String getJava(Path image) { + boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("win"); + Path java = image.resolve("bin").resolve(isWindows ? "java.exe" : "java"); + if (Files.notExists(java)) + throw new RuntimeException(java + " not found"); + return java.toAbsolutePath().toString(); + } +} diff --git a/jdk/test/tools/launcher/modules/patch/systemmodules/src/m1/module-info.java b/jdk/test/tools/launcher/modules/patch/systemmodules/src/m1/module-info.java new file mode 100644 index 00000000000..d23aeb1669b --- /dev/null +++ b/jdk/test/tools/launcher/modules/patch/systemmodules/src/m1/module-info.java @@ -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 { + requires m2; +} diff --git a/jdk/test/tools/launcher/modules/patch/systemmodules/src/m1/p1/Main.java b/jdk/test/tools/launcher/modules/patch/systemmodules/src/m1/p1/Main.java new file mode 100644 index 00000000000..2329905a0f0 --- /dev/null +++ b/jdk/test/tools/launcher/modules/patch/systemmodules/src/m1/p1/Main.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 p1; + +public class Main { + public static void main(String[] args) throws Exception { + int version = p2.Lib.version(); + int expected = args.length == 0 ? 1 : Integer.parseInt(args[0]); + + if (version != expected) + throw new RuntimeException(version + " != " + expected + " (expected)"); + } +} diff --git a/jdk/test/tools/launcher/modules/patch/systemmodules/src/m2/module-info.java b/jdk/test/tools/launcher/modules/patch/systemmodules/src/m2/module-info.java new file mode 100644 index 00000000000..bc0f12b2204 --- /dev/null +++ b/jdk/test/tools/launcher/modules/patch/systemmodules/src/m2/module-info.java @@ -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 m2 { + exports p2; +} diff --git a/jdk/test/tools/launcher/modules/patch/systemmodules/src/m2/p2/Lib.java b/jdk/test/tools/launcher/modules/patch/systemmodules/src/m2/p2/Lib.java new file mode 100644 index 00000000000..1d43aedc718 --- /dev/null +++ b/jdk/test/tools/launcher/modules/patch/systemmodules/src/m2/p2/Lib.java @@ -0,0 +1,30 @@ +/** + * 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 p2; + +public class Lib { + public static int version() { + return 1; + } +} diff --git a/jdk/test/tools/launcher/modules/patch/systemmodules/src1/java.base/jdk/internal/modules/SystemModules.java b/jdk/test/tools/launcher/modules/patch/systemmodules/src1/java.base/jdk/internal/modules/SystemModules.java new file mode 100644 index 00000000000..e30761204e1 --- /dev/null +++ b/jdk/test/tools/launcher/modules/patch/systemmodules/src1/java.base/jdk/internal/modules/SystemModules.java @@ -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 jdk.internal.module; + +/* + * Test -Xpatch:java.base=jdk/modules/java.base to override + * java.base with an exploded image + */ +public final class SystemModules { + public static final String[] MODULE_NAMES = new String[0]; +} diff --git a/jdk/test/tools/launcher/modules/patch/systemmodules/src1/m2/p2/Lib.java b/jdk/test/tools/launcher/modules/patch/systemmodules/src1/m2/p2/Lib.java new file mode 100644 index 00000000000..5313c7e7aed --- /dev/null +++ b/jdk/test/tools/launcher/modules/patch/systemmodules/src1/m2/p2/Lib.java @@ -0,0 +1,30 @@ +/** + * 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 p2; + +public class Lib { + public static int version() { + return 2; + } +} diff --git a/jdk/test/tools/pack200/TestNormal.java b/jdk/test/tools/pack200/TestNormal.java index 0172a5e65b6..a85a9d4040f 100644 --- a/jdk/test/tools/pack200/TestNormal.java +++ b/jdk/test/tools/pack200/TestNormal.java @@ -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 @@ -25,85 +25,37 @@ /* * @test * @run main/timeout=600 TestNormal - * @bug 8020802 + * @bug 8020802 8156807 * @summary Need an ability to create jar files that are invariant to the pack200 packing/unpacking * @author Alexander Zuev */ import java.io.*; -import java.util.Collections; -import java.util.Properties; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; public class TestNormal { private static String FS = File.separator; public static void main(String args[]) throws Exception { - Properties p = System.getProperties(); - String java_home = p.getProperty("test.jdk"); String testdir = Utils.TEST_CLS_DIR.getAbsolutePath(); try { - execJavaCommand(java_home, "jar cnf normalized.jar -C " + testdir + " ."); - execJavaCommand(java_home, "jar cf original.jar -C " + testdir + " ."); - execJavaCommand(java_home, "pack200 -r repacked.jar original.jar"); - compareJars(new JarFile("normalized.jar"), new JarFile("repacked.jar")); + String jarCmd = Utils.getJarCmd(); + String packCmd = Utils.getPack200Cmd(); + + // create the original jar + Utils.runExec(jarCmd, "cf", "original.jar", "-C", testdir, "."); + + // create the reference jar + Utils.runExec(packCmd, "-r", "repacked.jar", "original.jar"); + + // create the normalized jar using jar(1) + Utils.runExec(jarCmd, "cnf", "normalized.jar", "-C", testdir, "."); + + // compare archive contents bit wise, these should be identical! + Utils.doCompareBitWise(new File("repacked.jar"), + new File("normalized.jar")); } finally { - String[] cleanupList = {"normalized.jar", "original.jar", "repacked.jar"}; - for (String s : cleanupList) { - delete(new File(s)); - } - } - } - - public static void execJavaCommand(String java_home, String cmd) throws Exception { - Process proc = Runtime.getRuntime().exec(java_home + FS + "bin" + FS + cmd); - String s; - BufferedReader stdInput = - new BufferedReader(new InputStreamReader(proc.getInputStream())); - BufferedReader stdError = - new BufferedReader(new InputStreamReader(proc.getErrorStream())); - while ((s = stdInput.readLine()) != null) { - System.out.println(s); - } - while ((s = stdError.readLine()) != null) { - System.err.println(s); - } - } - - public static void compareJars(JarFile jf1, JarFile jf2) throws Exception { - try { - if (jf1.size() != jf2.size()) { - throw new Exception("Jars " + jf1.getName() + " and " + jf2.getName() - + " have different number of entries"); - } - for (JarEntry elem1 : Collections.list(jf1.entries())) { - JarEntry elem2 = jf2.getJarEntry(elem1.getName()); - if (elem2 == null) { - throw new Exception("Element " + elem1.getName() + " is missing from " + jf2.getName()); - } - if (!elem1.isDirectory() && elem1.getCrc() != elem2.getCrc()) { - throw new Exception("The crc of " + elem1.getName() + " is different."); - } - } - } finally { - jf1.close(); - jf2.close(); - } - } - - static void delete(File f) throws IOException { - if (!f.exists()) { - return; - } - if (f.isDirectory()) { - for (File c : f.listFiles()) { - delete(c); - } - } - if (!f.delete()) { - throw new FileNotFoundException("Failed to delete file: " + f); + Utils.cleanup(); } } } diff --git a/jdk/test/tools/pack200/Utils.java b/jdk/test/tools/pack200/Utils.java index f4641987e73..45e09c37abc 100644 --- a/jdk/test/tools/pack200/Utils.java +++ b/jdk/test/tools/pack200/Utils.java @@ -33,7 +33,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.URI; -import java.net.URL; import java.nio.charset.Charset; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.FileSystem; @@ -483,9 +482,15 @@ class Utils { } return out; } + + static List runExec(String... cmds) { + return runExec(Arrays.asList(cmds)); + } + static List runExec(List cmdsList) { return runExec(cmdsList, null); } + static List runExec(List cmdsList, Map penv) { ArrayList alist = new ArrayList(); ProcessBuilder pb = diff --git a/langtools/.hgtags b/langtools/.hgtags index 5f7979643e2..22c89e3d14e 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -361,3 +361,5 @@ cba09a2e6ae969b029783eb59bb01017b78f8eef jdk-9+114 3e3553ee39d9e081573bc7c88a252214a3152763 jdk-9+116 59adcdd0cd3b6724b4fc0083c258bf4682689f2f jdk-9+117 59a16fa5dedea9ff5bea0a501e4d0d40193426f3 jdk-9+118 +6347efd1be03b4fdcf18f64c4fe4be5f60c0831a jdk-9+119 +0f81cdd51b42ad38fbceae40985e9bd0bca12180 jdk-9+120 diff --git a/langtools/make/build.properties b/langtools/make/build.properties index 38939fa856f..c65ccb64bd1 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -28,6 +28,10 @@ javac.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-options -Werror javac.source = 9 javac.target = 9 +#version used to compile build tools +javac.build.source = 8 +javac.build.target = 8 + langtools.resource.includes = \ com/sun/tools/javac/resources/compiler.properties diff --git a/langtools/make/build.xml b/langtools/make/build.xml index e96ec89a819..b894201c341 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -89,11 +89,17 @@ + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/langtools/make/launcher.sh-template b/langtools/make/launcher.sh-template index 4a2e37c409a..d6a1eb6fc2d 100644 --- a/langtools/make/launcher.sh-template +++ b/langtools/make/launcher.sh-template @@ -48,4 +48,4 @@ done unset DUALCASE IFS=$nl -"#TARGET_JAVA#" "#XPATCH#" ${ea} ${javaOpts} #PROGRAM# ${toolOpts} +"#TARGET_JAVA#" #XPATCH# ${ea} ${javaOpts} #PROGRAM# ${toolOpts} diff --git a/langtools/make/tools/crules/AssertCheckAnalyzer.java b/langtools/make/tools/crules/AssertCheckAnalyzer.java index d46b5e13d65..b665d74215e 100644 --- a/langtools/make/tools/crules/AssertCheckAnalyzer.java +++ b/langtools/make/tools/crules/AssertCheckAnalyzer.java @@ -37,6 +37,9 @@ import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.Assert; +/**This analyzer guards against complex messages (i.e. those that use string concatenation) passed + * to various Assert.check methods. + */ public class AssertCheckAnalyzer extends AbstractCodingRulesAnalyzer { enum AssertOverloadKind { diff --git a/langtools/make/tools/crules/MutableFieldsAnalyzer.java b/langtools/make/tools/crules/MutableFieldsAnalyzer.java index a992f55884b..5609556be5c 100644 --- a/langtools/make/tools/crules/MutableFieldsAnalyzer.java +++ b/langtools/make/tools/crules/MutableFieldsAnalyzer.java @@ -41,6 +41,7 @@ import static com.sun.tools.javac.code.Flags.STATIC; import static com.sun.tools.javac.code.Flags.SYNTHETIC; import static com.sun.tools.javac.code.Kinds.Kind.*; +/**This analyzer guards against non-final static fields.*/ public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer { public MutableFieldsAnalyzer(JavacTask task) { @@ -98,12 +99,14 @@ public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer { ignoreFields("com.sun.tools.javac.code.Type", "moreInfo"); ignoreFields("com.sun.tools.javac.util.SharedNameTable", "freelist"); ignoreFields("com.sun.tools.javac.util.Log", "useRawMessages"); - ignoreFields("com.sun.tools.javac.util.ModuleWrappers$ModuleFinderHelper", - "moduleFinderInterface", "ofMethod", "emptyMethod"); - ignoreFields("com.sun.tools.javac.util.ModuleWrappers$ConfigurationHelper", + ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ModuleFinder", + "moduleFinderClass", "ofMethod"); + ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Configuration", "configurationClass", "resolveRequiresAndUsesMethod"); - ignoreFields("com.sun.tools.javac.util.ModuleWrappers$LayerHelper", + ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Layer", "layerClass", "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod"); + ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ServiceLoaderHelper", + "loadMethod"); ignoreFields("com.sun.tools.javac.util.ModuleHelper", "addExportsMethod", "getUnnamedModuleMethod", "getModuleMethod"); } diff --git a/langtools/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java b/langtools/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java index bc22ac259ae..4d774958e1d 100644 --- a/langtools/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java +++ b/langtools/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java @@ -27,6 +27,8 @@ package javax.annotation.processing; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import java.util.LinkedHashSet; +import java.util.Collections; import java.util.Set; import java.lang.annotation.Annotation; @@ -91,6 +93,38 @@ public interface RoundEnvironment { */ Set getElementsAnnotatedWith(TypeElement a); + /** + * Returns the elements annotated with one or more of the given + * annotation types. + * + * @apiNote This method may be useful when processing repeating + * annotations by looking for an annotation type and its + * containing annotation type at the same time. + * + * @implSpec The default implementation of this method creates an + * empty result set, iterates over the annotations in the argument + * set calling {@link #getElementsAnnotatedWith(TypeElement)} on + * each annotation and adding those results to the result + * set. Finally, the contents of the result set are returned as an + * unmodifiable set. + * + * @param annotations annotation types being requested + * @return the elements annotated with one or more of the given + * annotation types, or an empty set if there are none + * @throws IllegalArgumentException if the any elements of the + * argument set do not represent an annotation type + * @jls 9.6.3 Repeatable Annotation Types + * @since 9 + */ + default Set getElementsAnnotatedWithAny(TypeElement... annotations){ + // Use LinkedHashSet rather than HashSet for predictability + Set result = new LinkedHashSet<>(); + for (TypeElement annotation : annotations) { + result.addAll(getElementsAnnotatedWith(annotation)); + } + return Collections.unmodifiableSet(result); + } + /** * Returns the elements annotated with the given annotation type. * The annotation may appear directly or be inherited. Only @@ -110,4 +144,36 @@ public interface RoundEnvironment { * represent an annotation type */ Set getElementsAnnotatedWith(Class a); + + /** + * Returns the elements annotated with one or more of the given + * annotation types. + * + * @apiNote This method may be useful when processing repeating + * annotations by looking for an annotation type and its + * containing annotation type at the same time. + * + * @implSpec The default implementation of this method creates an + * empty result set, iterates over the annotations in the argument + * set calling {@link #getElementsAnnotatedWith(Class)} on + * each annotation and adding those results to the result + * set. Finally, the contents of the result set are returned as an + * unmodifiable set. + * + * @param annotations annotation types being requested + * @return the elements annotated with one or more of the given + * annotation types, or an empty set if there are none + * @throws IllegalArgumentException if the any elements of the + * argument set do not represent an annotation type + * @jls 9.6.3 Repeatable Annotation Types + * @since 9 + */ + default Set getElementsAnnotatedWithAny(Set> annotations){ + // Use LinkedHashSet rather than HashSet for predictability + Set result = new LinkedHashSet<>(); + for (Class annotation : annotations) { + result.addAll(getElementsAnnotatedWith(annotation)); + } + return Collections.unmodifiableSet(result); + } } diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java b/langtools/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java index a4ae3e8ea35..768c7ba4b45 100644 --- a/langtools/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -55,7 +55,7 @@ public enum SourceVersion { * 1.6: no changes * 1.7: diamond syntax, try-with-resources, etc. * 1.8: lambda expressions and default methods - * 9: To be determined + * 9: modules, small cleanups to 1.7 and 1.8 changes */ /** @@ -145,6 +145,9 @@ public enum SourceVersion { * The version recognized by the Java Platform, Standard Edition * 9. * + * Additions in this release include modules and removal of a + * single underscore from the set of legal identifier names. + * * @since 9 */ RELEASE_9; @@ -233,10 +236,10 @@ public enum SourceVersion { } /** - * Returns whether or not {@code name} is a syntactically valid - * qualified name in the latest source version. Unlike {@link - * #isIdentifier isIdentifier}, this method returns {@code false} - * for keywords and literals. + * Returns whether or not {@code name} is a syntactically valid + * qualified name in the latest source version. Unlike {@link + * #isIdentifier isIdentifier}, this method returns {@code false} + * for keywords, boolean literals, and the null literal. * * @param name the string to check * @return {@code true} if this string is a @@ -244,45 +247,115 @@ public enum SourceVersion { * @jls 6.2 Names and Identifiers */ public static boolean isName(CharSequence name) { + return isName(name, latest()); + } + + /** + * Returns whether or not {@code name} is a syntactically valid + * qualified name in the given source version. Unlike {@link + * #isIdentifier isIdentifier}, this method returns {@code false} + * for keywords, boolean literals, and the null literal. + * + * @param name the string to check + * @param version the version to use + * @return {@code true} if this string is a + * syntactically valid name, {@code false} otherwise. + * @jls 6.2 Names and Identifiers + * @since 9 + */ + public static boolean isName(CharSequence name, SourceVersion version) { String id = name.toString(); for(String s : id.split("\\.", -1)) { - if (!isIdentifier(s) || isKeyword(s)) + if (!isIdentifier(s) || isKeyword(s, version)) return false; } return true; } - private final static Set keywords; - static { - Set s = new HashSet<>(); - String [] kws = { - "abstract", "continue", "for", "new", "switch", - "assert", "default", "if", "package", "synchronized", - "boolean", "do", "goto", "private", "this", - "break", "double", "implements", "protected", "throw", - "byte", "else", "import", "public", "throws", - "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", - "char", "final", "interface", "static", "void", - "class", "finally", "long", "strictfp", "volatile", - "const", "float", "native", "super", "while", - // literals - "null", "true", "false" - }; - for(String kw : kws) - s.add(kw); - keywords = Collections.unmodifiableSet(s); + /** + * Returns whether or not {@code s} is a keyword, boolean literal, + * or null literal in the latest source version. + * + * @param s the string to check + * @return {@code true} if {@code s} is a keyword, or boolean + * literal, or null literal, {@code false} otherwise. + * @jls 3.9 Keywords + * @jls 3.10.3 Boolean Literals + * @jls 3.10.7 The Null Literal + */ + public static boolean isKeyword(CharSequence s) { + return isKeyword(s, latest()); } /** - * Returns whether or not {@code s} is a keyword or literal in the - * latest source version. + * Returns whether or not {@code s} is a keyword, boolean literal, + * or null literal in the given source version. * * @param s the string to check - * @return {@code true} if {@code s} is a keyword or literal, {@code false} otherwise. + * @param version the version to use + * @return {@code true} if {@code s} is a keyword, or boolean + * literal, or null literal, {@code false} otherwise. + * @jls 3.9 Keywords + * @jls 3.10.3 Boolean Literals + * @jls 3.10.7 The Null Literal + * @since 9 */ - public static boolean isKeyword(CharSequence s) { - return keywords.contains(s.toString()); + public static boolean isKeyword(CharSequence s, SourceVersion version) { + String id = s.toString(); + switch(id) { + // A trip through history + case "strictfp": + return version.compareTo(RELEASE_2) >= 0; + + case "assert": + return version.compareTo(RELEASE_4) >= 0; + + case "enum": + return version.compareTo(RELEASE_5) >= 0; + + case "_": + return version.compareTo(RELEASE_9) >= 0; + + // Keywords common across versions + + // Modifiers + case "public": case "protected": case "private": + case "abstract": case "static": case "final": + case "transient": case "volatile": case "synchronized": + case "native": + + // Declarations + case "class": case "interface": case "extends": + case "package": case "throws": case "implements": + + // Primitive types and void + case "boolean": case "byte": case "char": + case "short": case "int": case "long": + case "float": case "double": + case "void": + + // Control flow + case "if": case "else": + case "try": case "catch": case "finally": + case "do": case "while": + case "for": case "continue": + case "switch": case "case": case "default": + case "break": case "throw": case "return": + + // Other keywords + case "this": case "new": case "super": + case "import": case "instanceof": + + // Forbidden! + case "goto": case "const": + + // literals + case "null": case "true": case "false": + return true; + + default: + return false; + } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java index e73f28c229c..43c0e90b339 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -28,6 +28,7 @@ package com.sun.tools.javac.api; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Locale; +import java.util.Objects; import java.util.ServiceLoader; import java.util.Set; import java.util.stream.Collectors; @@ -130,9 +131,13 @@ public class BasicJavacTask extends JavacTask { public TypeMirror getTypeMirror(Iterable path) { // TODO: Should complete attribution if necessary Tree last = null; - for (Tree node : path) - last = node; - return ((JCTree)last).type; + for (Tree node : path) { + last = Objects.requireNonNull(node); + } + if (last == null) { + throw new IllegalArgumentException("empty path"); + } + return ((JCTree) last).type; } @Override @DefinedBy(Api.COMPILER_TREE) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java index 835acf14b26..71d7aac0b05 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java @@ -148,9 +148,10 @@ public class TypeAnnotationPosition { // For exception parameters, index into exception table. In // com.sun.tools.javac.jvm.Gen.genCatch, we first use this to hold - // the catch type index. Then in + // the catch type's constant pool entry index. Then in // com.sun.tools.javac.jvm.Code.fillExceptionParameterPositions we // use that value to determine the exception table index. + // When read from class file, this holds private int exception_index = Integer.MIN_VALUE; // If this type annotation is within a lambda expression, @@ -303,13 +304,13 @@ public class TypeAnnotationPosition { } public int getExceptionIndex() { - Assert.check(exception_index >= 0, "exception_index does not contain a bytecode offset"); + Assert.check(exception_index >= 0, "exception_index is not set"); return exception_index; } public void setExceptionIndex(final int exception_index) { - Assert.check(hasCatchType(), "exception_index already contains a bytecode offset"); - Assert.check(exception_index >= 0, "Expected a valid bytecode offset"); + Assert.check(!hasExceptionIndex(), "exception_index already set"); + Assert.check(exception_index >= 0, "Expected a valid index into exception table"); this.exception_index = exception_index; } @@ -330,8 +331,8 @@ public class TypeAnnotationPosition { } public void setCatchInfo(final int catchType, final int startPos) { - Assert.check(this.exception_index < 0, - "exception_index already contains a bytecode index"); + Assert.check(!hasExceptionIndex(), + "exception_index is already set"); Assert.check(catchType >= 0, "Expected a valid catch type"); this.exception_index = -((catchType | startPos << 8) + 1); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java index 7ce6ccd17ec..7030511e9dd 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java @@ -365,18 +365,22 @@ public class ArgumentAttr extends JCTree.Visitor { @Override Type speculativeType(Symbol msym, MethodResolutionPhase phase) { - for (Map.Entry _entry : speculativeTypes.entrySet()) { - DeferredAttrContext deferredAttrContext = _entry.getKey().checkContext.deferredAttrContext(); - if (deferredAttrContext.phase == phase && deferredAttrContext.msym == msym) { - return _entry.getValue(); + if (pertinentToApplicability) { + for (Map.Entry _entry : speculativeTypes.entrySet()) { + DeferredAttrContext deferredAttrContext = _entry.getKey().checkContext.deferredAttrContext(); + if (deferredAttrContext.phase == phase && deferredAttrContext.msym == msym) { + return _entry.getValue(); + } } + return Type.noType; + } else { + return super.speculativeType(msym, phase); } - return Type.noType; } @Override JCTree speculativeTree(DeferredAttrContext deferredAttrContext) { - return speculativeTree; + return pertinentToApplicability ? speculativeTree : super.speculativeTree(deferredAttrContext); } /** diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 1fd1d379a74..893cdc09518 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -811,6 +811,7 @@ public class Attr extends JCTree.Visitor { DiagnosticPosition prevLintPos = deferredLintHandler.setPos(variable.pos()); + final JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); try { Type itype = attribExpr(variable.init, env, type); if (itype.constValue() != null) { @@ -819,6 +820,7 @@ public class Attr extends JCTree.Visitor { return null; } } finally { + log.useSource(prevSource); deferredLintHandler.setPos(prevLintPos); } } @@ -2666,7 +2668,7 @@ public class Attr extends JCTree.Visitor { @Override public boolean compatible(Type found, Type req, Warner warn) { //return type must be compatible in both current context and assignment context - return chk.basicHandler.compatible(found, inferenceContext().asUndetVar(req), warn); + return chk.basicHandler.compatible(inferenceContext().asUndetVar(found), inferenceContext().asUndetVar(req), warn); } @Override @@ -2678,17 +2680,31 @@ public class Attr extends JCTree.Visitor { class ExpressionLambdaReturnContext extends FunctionalReturnContext { JCExpression expr; + boolean expStmtExpected; ExpressionLambdaReturnContext(JCExpression expr, CheckContext enclosingContext) { super(enclosingContext); this.expr = expr; } + @Override + public void report(DiagnosticPosition pos, JCDiagnostic details) { + if (expStmtExpected) { + enclosingContext.report(pos, diags.fragment(Fragments.StatExprExpected)); + } else { + super.report(pos, details); + } + } + @Override public boolean compatible(Type found, Type req, Warner warn) { //a void return is compatible with an expression statement lambda - return TreeInfo.isExpressionStatement(expr) && req.hasTag(VOID) || - super.compatible(found, req, warn); + if (req.hasTag(VOID)) { + expStmtExpected = true; + return TreeInfo.isExpressionStatement(expr); + } else { + return super.compatible(found, req, warn); + } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java index c588ecd3e1d..fa861b07c9a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java @@ -35,6 +35,7 @@ import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.DefinedBy.Api; +import com.sun.tools.javac.util.GraphUtils.DependencyKind; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.comp.Attr.ResultInfo; @@ -44,9 +45,10 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.EnumSet; -import java.util.LinkedHashMap; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -172,6 +174,7 @@ public class DeferredAttr extends JCTree.Visitor { public JCExpression tree; Env env; AttrMode mode; + boolean pertinentToApplicability = true; SpeculativeCache speculativeCache; DeferredType(JCExpression tree, Env env) { @@ -290,6 +293,7 @@ public class DeferredAttr extends JCTree.Visitor { resultInfo.checkContext.deferredAttrContext(); Assert.check(deferredAttrContext != emptyDeferredAttrContext); if (deferredStuckPolicy.isStuck()) { + pertinentToApplicability = false; deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy); return Type.noType; } else { @@ -574,28 +578,11 @@ public class DeferredAttr extends JCTree.Visitor { */ void complete() { while (!deferredAttrNodes.isEmpty()) { - Map> depVarsMap = new LinkedHashMap<>(); - List stuckVars = List.nil(); boolean progress = false; //scan a defensive copy of the node list - this is because a deferred //attribution round can add new nodes to the list for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) { - if (!deferredAttrNode.process(this)) { - List restStuckVars = - List.from(deferredAttrNode.deferredStuckPolicy.stuckVars()) - .intersect(inferenceContext.restvars()); - stuckVars = stuckVars.prependList(restStuckVars); - //update dependency map - for (Type t : List.from(deferredAttrNode.deferredStuckPolicy.depVars()) - .intersect(inferenceContext.restvars())) { - Set prevDeps = depVarsMap.get(t); - if (prevDeps == null) { - prevDeps = new LinkedHashSet<>(); - depVarsMap.put(t, prevDeps); - } - prevDeps.addAll(restStuckVars); - } - } else { + if (deferredAttrNode.process(this)) { deferredAttrNodes.remove(deferredAttrNode); progress = true; } @@ -610,7 +597,9 @@ public class DeferredAttr extends JCTree.Visitor { //remove all variables that have already been instantiated //from the list of stuck variables try { - inferenceContext.solveAny(stuckVars, depVarsMap, warn); + //find stuck expression to unstuck + DeferredAttrNode toUnstuck = pickDeferredNode(); + inferenceContext.solveAny(List.from(toUnstuck.deferredStuckPolicy.stuckVars()), warn); inferenceContext.notifyChange(); } catch (Infer.GraphStrategy.NodeNotFoundException ex) { //this means that we are in speculative mode and the @@ -632,6 +621,59 @@ public class DeferredAttr extends JCTree.Visitor { } return dac.parent.insideOverloadPhase(); } + + /** + * Pick the deferred node to be unstuck. The chosen node is the first strongly connected + * component containing exactly one node found in the dependency graph induced by deferred nodes. + * If no such component is found, the first deferred node is returned. + */ + DeferredAttrNode pickDeferredNode() { + List nodes = deferredAttrNodes.stream() + .map(StuckNode::new) + .collect(List.collector()); + //init stuck expression graph; a deferred node A depends on a deferred node B iff + //the intersection between A's input variable and B's output variable is non-empty. + for (StuckNode sn1 : nodes) { + for (Type t : sn1.data.deferredStuckPolicy.stuckVars()) { + for (StuckNode sn2 : nodes) { + if (sn1 != sn2 && sn2.data.deferredStuckPolicy.depVars().contains(t)) { + sn1.deps.add(sn2); + } + } + } + } + //compute tarjan on the stuck graph + List csn = GraphUtils.tarjan(nodes).get(0); + return csn.length() == 1 ? csn.get(0).data : deferredAttrNodes.get(0); + } + + class StuckNode extends GraphUtils.TarjanNode { + + Set deps = new HashSet<>(); + + StuckNode(DeferredAttrNode data) { + super(data); + } + + @Override + public DependencyKind[] getSupportedDependencyKinds() { + return new DependencyKind[] { Infer.DependencyKind.STUCK }; + } + + @Override + public Collection getDependenciesByKind(DependencyKind dk) { + if (dk == Infer.DependencyKind.STUCK) { + return deps; + } else { + throw new IllegalStateException(); + } + } + + @Override + public Iterable getAllDependencies() { + return deps; + } + } } /** diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 776a1bfc18c..d0e49a2d10c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -2345,10 +2345,11 @@ public class Flow { // assigned before reading their value public void visitSelect(JCFieldAccess tree) { super.visitSelect(tree); + JCTree sel = TreeInfo.skipParens(tree.selected); if (enforceThisDotInit && - tree.selected.hasTag(IDENT) && - ((JCIdent)tree.selected).name == names._this && - tree.sym.kind == VAR) { + sel.hasTag(IDENT) && + ((JCIdent)sel).name == names._this && + tree.sym.kind == VAR) { checkInit(tree.pos(), (VarSymbol)tree.sym); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java index 87026e6e4fe..4ecbca5acba 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java @@ -52,11 +52,9 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -196,7 +194,7 @@ public class Infer { //inject return constraints earlier doIncorporation(inferenceContext, warn); //propagation - boolean shouldPropagate = resultInfo.checkContext.inferenceContext().free(resultInfo.pt); + boolean shouldPropagate = shouldPropagate(mt.getReturnType(), resultInfo, inferenceContext); InferenceContext minContext = shouldPropagate ? inferenceContext.min(roots(mt, deferredAttrContext), true, warn) : @@ -257,6 +255,13 @@ public class Infer { } } //where + private boolean shouldPropagate(Type restype, Attr.ResultInfo target, InferenceContext inferenceContext) { + return target.checkContext.inferenceContext() != emptyContext && //enclosing context is a generic method + inferenceContext.free(restype) && //return type contains inference vars + (!inferenceContext.inferencevars.contains(restype) || //no eager instantiation is required (as per 18.5.2) + !needsEagerInstantiation((UndetVar)inferenceContext.asUndetVar(restype), target.pt, inferenceContext)); + } + private List roots(MethodType mt, DeferredAttrContext deferredAttrContext) { ListBuffer roots = new ListBuffer<>(); roots.add(mt.getReturnType()); @@ -311,7 +316,7 @@ public class Infer { */ saved_undet = inferenceContext.save(); if (allowGraphInference && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { - boolean shouldPropagate = resultInfo.checkContext.inferenceContext().free(resultInfo.pt); + boolean shouldPropagate = shouldPropagate(getReturnType(), resultInfo, inferenceContext); InferenceContext minContext = shouldPropagate ? inferenceContext.min(roots(asMethodType(), null), false, warn) : @@ -396,8 +401,9 @@ public class Infer { to = from.isPrimitive() ? from : syms.objectType; } else if (qtype.hasTag(UNDETVAR)) { if (resultInfo.pt.isReference()) { - to = generateReturnConstraintsUndetVarToReference( - tree, (UndetVar)qtype, to, resultInfo, inferenceContext); + if (needsEagerInstantiation((UndetVar)qtype, to, inferenceContext)) { + to = generateReferenceToTargetConstraint(tree, (UndetVar)qtype, to, resultInfo, inferenceContext); + } } else { if (to.isPrimitive()) { to = generateReturnConstraintsPrimitive(tree, (UndetVar)qtype, to, @@ -441,9 +447,7 @@ public class Infer { return types.boxedClass(to).type; } - private Type generateReturnConstraintsUndetVarToReference(JCTree tree, - UndetVar from, Type to, Attr.ResultInfo resultInfo, - InferenceContext inferenceContext) { + private boolean needsEagerInstantiation(UndetVar from, Type to, InferenceContext inferenceContext) { Type captureOfTo = types.capture(to); /* T is a reference type, but is not a wildcard-parameterized type, and either */ @@ -454,8 +458,7 @@ public class Infer { for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { Type captureOfBound = types.capture(t); if (captureOfBound != t) { - return generateReferenceToTargetConstraint(tree, from, to, - resultInfo, inferenceContext); + return true; } } @@ -469,8 +472,7 @@ public class Infer { !inferenceContext.free(aLowerBound) && !inferenceContext.free(anotherLowerBound) && commonSuperWithDiffParameterization(aLowerBound, anotherLowerBound)) { - return generateReferenceToTargetConstraint(tree, from, to, - resultInfo, inferenceContext); + return true; } } } @@ -485,12 +487,11 @@ public class Infer { for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { Type sup = types.asSuper(t, to.tsym); if (sup != null && sup.isRaw()) { - return generateReferenceToTargetConstraint(tree, from, to, - resultInfo, inferenceContext); + return true; } } } - return to; + return false; } private boolean commonSuperWithDiffParameterization(Type t, Type s) { @@ -1477,21 +1478,16 @@ public class Infer { //not a throws undet var return false; } - if (t.getBounds(InferenceBound.EQ, InferenceBound.LOWER, InferenceBound.UPPER) - .diff(t.getDeclaredBounds()).nonEmpty()) { - //not an unbounded undet var - return false; - } Infer infer = inferenceContext.infer; - for (Type db : t.getDeclaredBounds()) { + for (Type db : t.getBounds(InferenceBound.UPPER)) { if (t.isInterface()) continue; - if (infer.types.asSuper(infer.syms.runtimeExceptionType, db.tsym) != null) { - //declared bound is a supertype of RuntimeException - return true; + if (infer.types.asSuper(infer.syms.runtimeExceptionType, db.tsym) == null) { + //upper bound is not a supertype of RuntimeException - give up + return false; } } - //declared bound is more specific then RuntimeException - give up - return false; + + return true; } @Override @@ -1655,12 +1651,10 @@ public class Infer { class GraphSolver { InferenceContext inferenceContext; - Map> stuckDeps; Warner warn; - GraphSolver(InferenceContext inferenceContext, Map> stuckDeps, Warner warn) { + GraphSolver(InferenceContext inferenceContext, Warner warn) { this.inferenceContext = inferenceContext; - this.stuckDeps = stuckDeps; this.warn = warn; } @@ -1671,7 +1665,7 @@ public class Infer { */ void solve(GraphStrategy sstrategy) { doIncorporation(inferenceContext, warn); //initial propagation of bounds - InferenceGraph inferenceGraph = new InferenceGraph(stuckDeps); + InferenceGraph inferenceGraph = new InferenceGraph(); while (!sstrategy.done()) { if (dependenciesFolder != null) { //add this graph to the pending queue @@ -1720,12 +1714,12 @@ public class Infer { */ class Node extends GraphUtils.TarjanNode, Node> implements DottableNode, Node> { - /** map listing all dependencies (grouped by kind) */ - EnumMap> deps; + /** node dependencies */ + Set deps; Node(Type ivar) { super(ListBuffer.of(ivar)); - this.deps = new EnumMap<>(DependencyKind.class); + this.deps = new HashSet<>(); } @Override @@ -1734,76 +1728,53 @@ public class Infer { } public Iterable getAllDependencies() { - return getDependencies(DependencyKind.values()); + return deps; } @Override public Collection getDependenciesByKind(GraphUtils.DependencyKind dk) { - return getDependencies((DependencyKind)dk); - } - - /** - * Retrieves all dependencies with given kind(s). - */ - protected Set getDependencies(DependencyKind... depKinds) { - Set buf = new LinkedHashSet<>(); - for (DependencyKind dk : depKinds) { - Set depsByKind = deps.get(dk); - if (depsByKind != null) { - buf.addAll(depsByKind); - } + if (dk == DependencyKind.BOUND) { + return deps; + } else { + throw new IllegalStateException(); } - return buf; } /** * Adds dependency with given kind. */ - protected void addDependency(DependencyKind dk, Node depToAdd) { - Set depsByKind = deps.get(dk); - if (depsByKind == null) { - depsByKind = new LinkedHashSet<>(); - deps.put(dk, depsByKind); - } - depsByKind.add(depToAdd); + protected void addDependency(Node depToAdd) { + deps.add(depToAdd); } /** * Add multiple dependencies of same given kind. */ - protected void addDependencies(DependencyKind dk, Set depsToAdd) { + protected void addDependencies(Set depsToAdd) { for (Node n : depsToAdd) { - addDependency(dk, n); + addDependency(n); } } /** * Remove a dependency, regardless of its kind. */ - protected Set removeDependency(Node n) { - Set removedKinds = new HashSet<>(); - for (DependencyKind dk : DependencyKind.values()) { - Set depsByKind = deps.get(dk); - if (depsByKind == null) continue; - if (depsByKind.remove(n)) { - removedKinds.add(dk); - } - } - return removedKinds; + protected boolean removeDependency(Node n) { + return deps.remove(n); } /** * Compute closure of a give node, by recursively walking * through all its dependencies (of given kinds) */ - protected Set closure(DependencyKind... depKinds) { + protected Set closure() { boolean progress = true; Set closure = new HashSet<>(); closure.add(this); while (progress) { progress = false; for (Node n1 : new HashSet<>(closure)) { - progress = closure.addAll(n1.getDependencies(depKinds)); + progress = closure.addAll(n1.deps); } } return closure; @@ -1815,9 +1786,8 @@ public class Infer { */ protected boolean isLeaf() { //no deps, or only one self dep - Set allDeps = getDependencies(DependencyKind.BOUND, DependencyKind.STUCK); - if (allDeps.isEmpty()) return true; - for (Node n : allDeps) { + if (deps.isEmpty()) return true; + for (Node n : deps) { if (n != this) { return false; } @@ -1834,24 +1804,15 @@ public class Infer { for (Node n : nodes) { Assert.check(n.data.length() == 1, "Attempt to merge a compound node!"); data.appendList(n.data); - for (DependencyKind dk : DependencyKind.values()) { - addDependencies(dk, n.getDependencies(dk)); - } + addDependencies(n.deps); } //update deps - EnumMap> deps2 = new EnumMap<>(DependencyKind.class); - for (DependencyKind dk : DependencyKind.values()) { - for (Node d : getDependencies(dk)) { - Set depsByKind = deps2.get(dk); - if (depsByKind == null) { - depsByKind = new LinkedHashSet<>(); - deps2.put(dk, depsByKind); - } - if (data.contains(d.data.first())) { - depsByKind.add(this); - } else { - depsByKind.add(d); - } + Set deps2 = new HashSet<>(); + for (Node d : deps) { + if (data.contains(d.data.first())) { + deps2.add(this); + } else { + deps2.add(d); } } deps = deps2; @@ -1862,9 +1823,9 @@ public class Infer { * topology. */ private void graphChanged(Node from, Node to) { - for (DependencyKind dk : removeDependency(from)) { + if (removeDependency(from)) { if (to != null) { - addDependency(dk, to); + addDependency(to); } } } @@ -1880,22 +1841,19 @@ public class Infer { public Properties dependencyAttributes(Node sink, GraphUtils.DependencyKind dk) { Properties p = new Properties(); p.put("style", ((DependencyKind)dk).dotSyle); - if (dk == DependencyKind.STUCK) return p; - else { - StringBuilder buf = new StringBuilder(); - String sep = ""; - for (Type from : data) { - UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from); - for (Type bound : uv.getBounds(InferenceBound.values())) { - if (bound.containsAny(List.from(sink.data))) { - buf.append(sep); - buf.append(bound); - sep = ","; - } + StringBuilder buf = new StringBuilder(); + String sep = ""; + for (Type from : data) { + UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from); + for (Type bound : uv.getBounds(InferenceBound.values())) { + if (bound.containsAny(List.from(sink.data))) { + buf.append(sep); + buf.append(bound); + sep = ","; } } - p.put("label", "\"" + buf.toString() + "\""); } + p.put("label", "\"" + buf.toString() + "\""); return p; } } @@ -1903,8 +1861,8 @@ public class Infer { /** the nodes in the inference graph */ ArrayList nodes; - InferenceGraph(Map> optDeps) { - initNodes(optDeps); + InferenceGraph() { + initNodes(); } /** @@ -1946,7 +1904,7 @@ public class Infer { * in the graph. For each component containing more than one node, a super node is * created, effectively replacing the original cyclic nodes. */ - void initNodes(Map> stuckDeps) { + void initNodes() { //add nodes nodes = new ArrayList<>(); for (Type t : inferenceContext.restvars()) { @@ -1955,17 +1913,12 @@ public class Infer { //add dependencies for (Node n_i : nodes) { Type i = n_i.data.first(); - Set optDepsByNode = stuckDeps.get(i); for (Node n_j : nodes) { Type j = n_j.data.first(); UndetVar uv_i = (UndetVar)inferenceContext.asUndetVar(i); if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) { //update i's bound dependencies - n_i.addDependency(DependencyKind.BOUND, n_j); - } - if (optDepsByNode != null && optDepsByNode.contains(j)) { - //update i's stuck dependencies - n_i.addDependency(DependencyKind.STUCK, n_j); + n_i.addDependency(n_j); } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java index 398e291bdbb..f44cdc53d9a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java @@ -469,15 +469,11 @@ class InferenceContext { } } - private void solve(GraphStrategy ss, Warner warn) { - solve(ss, new HashMap>(), warn); - } - /** * Solve with given graph strategy. */ - private void solve(GraphStrategy ss, Map> stuckDeps, Warner warn) { - GraphSolver s = infer.new GraphSolver(this, stuckDeps, warn); + private void solve(GraphStrategy ss, Warner warn) { + GraphSolver s = infer.new GraphSolver(this, warn); s.solve(ss); } @@ -506,12 +502,12 @@ class InferenceContext { /** * Solve at least one variable in given list. */ - public void solveAny(List varsToSolve, Map> optDeps, Warner warn) { + public void solveAny(List varsToSolve, Warner warn) { solve(infer.new BestLeafSolver(varsToSolve.intersect(restvars())) { public boolean done() { return instvars().intersect(varsToSolve).nonEmpty(); } - }, optDeps, warn); + }, warn); } /** diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java index 207eb7fb538..81f80481002 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java @@ -128,7 +128,6 @@ public class Modules extends JCTree.Visitor { private final boolean allowModules; public final boolean multiModuleMode; - public final boolean noModules; private final String moduleOverride; @@ -167,10 +166,6 @@ public class Modules extends JCTree.Visitor { moduleOverride = options.get(Option.XMODULE); - // The following is required, for now, to support building - // Swing beaninfo via javadoc. - noModules = options.isSet("noModules"); - multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH); ClassWriter classWriter = ClassWriter.instance(context); classWriter.multiModuleMode = multiModuleMode; @@ -194,7 +189,7 @@ public class Modules extends JCTree.Visitor { } public boolean enter(List trees, ClassSymbol c) { - if (!allowModules || noModules) { + if (!allowModules) { for (JCCompilationUnit tree: trees) { tree.modle = syms.noModule; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java index 1c84b51a0db..899365f28e2 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java @@ -380,13 +380,17 @@ public abstract class BaseFileManager implements JavaFileManager { dest = CharBuffer.allocate(newCapacity).put(dest); } else if (result.isMalformed() || result.isUnmappable()) { // bad character in input + StringBuilder unmappable = new StringBuilder(); + int len = result.length(); - log.error(new SimpleDiagnosticPosition(dest.limit()), - "illegal.char.for.encoding", - charset == null ? encodingName : charset.name()); + for (int i = 0; i < len; i++) { + unmappable.append(String.format("%02X", inbuf.get())); + } - // skip past the coding error - inbuf.position(inbuf.position() + result.length()); + String charsetName = charset == null ? encodingName : charset.name(); + + log.error(dest.limit(), + Errors.IllegalCharForEncoding(unmappable.toString(), charsetName)); // undo the flip() to prepare the output buffer // for more translation diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java index 53f515da4eb..1f1b1c7d724 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -74,10 +74,10 @@ import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.ModuleWrappers.Configuration; -import com.sun.tools.javac.util.ModuleWrappers.Layer; -import com.sun.tools.javac.util.ModuleWrappers.ModuleFinder; -import com.sun.tools.javac.util.ModuleWrappers.ServiceLoaderHelper; +import com.sun.tools.javac.util.JDK9Wrappers.Configuration; +import com.sun.tools.javac.util.JDK9Wrappers.Layer; +import com.sun.tools.javac.util.JDK9Wrappers.ModuleFinder; +import com.sun.tools.javac.util.JDK9Wrappers.ServiceLoaderHelper; import static java.nio.file.FileVisitOption.FOLLOW_LINKS; @@ -972,7 +972,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil Collection paths = locations.getLocation(location); ModuleFinder finder = ModuleFinder.of(paths.toArray(new Path[paths.size()])); Layer bootLayer = Layer.boot(); - Configuration cf = bootLayer.configuration().resolveRequiresAndUses(ModuleFinder.empty(), finder, Collections.emptySet()); + Configuration cf = bootLayer.configuration().resolveRequiresAndUses(ModuleFinder.of(), finder, Collections.emptySet()); Layer layer = bootLayer.defineModulesWithOneLoader(cf, ClassLoader.getSystemClassLoader()); return ServiceLoaderHelper.load(layer, service); } else { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java index 12106e3ecc1..2ec0256463f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java @@ -1062,7 +1062,7 @@ public class Locations { return null; } - if (p.getFileName().toString().endsWith(".jar")) { + if (p.getFileName().toString().endsWith(".jar") && fsInfo.exists(p)) { try (FileSystem fs = FileSystems.newFileSystem(p, null)) { Path moduleInfoClass = fs.getPath("module-info.class"); if (Files.exists(moduleInfoClass)) { @@ -1138,7 +1138,7 @@ public class Locations { } } - if (warn && false) { // temp disable + if (warn && false) { // temp disable, when enabled, massage examples.not-yet.txt suitably. log.warning(Warnings.LocnUnknownFileOnModulePath(p)); } return null; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java index a37991e2dd2..e1f2a557533 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java @@ -174,6 +174,17 @@ public class Main { return Result.CMDERR; } + // prefix argv with contents of _JAVAC_OPTIONS if set + String envOpt = System.getenv("_JAVAC_OPTIONS"); + if (envOpt != null && !envOpt.trim().isEmpty()) { + String[] envv = envOpt.split("\\s+"); + String[] result = new String[envv.length + argv.length]; + System.arraycopy(envv, 0, result, 0, envv.length); + System.arraycopy(argv, 0, result, envv.length, argv.length); + argv = result; + } + + // expand @-files try { argv = CommandLine.parse(argv); } catch (FileNotFoundException | NoSuchFileException e) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java index 77d8736b367..34884389345 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -51,6 +51,7 @@ public class JavacRoundEnvironment implements RoundEnvironment { private final boolean processingOver; private final boolean errorRaised; private final ProcessingEnvironment processingEnv; + private final Elements eltUtils; // Caller must pass in an immutable set private final Set rootElements; @@ -63,6 +64,7 @@ public class JavacRoundEnvironment implements RoundEnvironment { this.errorRaised = errorRaised; this.rootElements = rootElements; this.processingEnv = processingEnv; + this.eltUtils = processingEnv.getElementUtils(); } public String toString() { @@ -100,9 +102,6 @@ public class JavacRoundEnvironment implements RoundEnvironment { return rootElements; } - private static final String NOT_AN_ANNOTATION_TYPE = - "The argument does not represent an annotation type: "; - /** * Returns the elements annotated with the given annotation type. * Only type elements included in this round of annotation @@ -117,10 +116,9 @@ public class JavacRoundEnvironment implements RoundEnvironment { */ @DefinedBy(Api.ANNOTATION_PROCESSING) public Set getElementsAnnotatedWith(TypeElement a) { - Set result = Collections.emptySet(); - if (a.getKind() != ElementKind.ANNOTATION_TYPE) - throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); + throwIfNotAnnotation(a); + Set result = Collections.emptySet(); ElementScanner9, TypeElement> scanner = new AnnotationSetScanner(result); @@ -130,41 +128,93 @@ public class JavacRoundEnvironment implements RoundEnvironment { return result; } + @DefinedBy(Api.ANNOTATION_PROCESSING) + public Set getElementsAnnotatedWithAny(TypeElement... annotations) { + // Don't bother to special-case annotations.length == 1 as + // return getElementsAnnotatedWith(annotations[0]); + + Set annotationSet = new LinkedHashSet<>(annotations.length); + for (TypeElement annotation : annotations) { + throwIfNotAnnotation(annotation); + annotationSet.add(annotation); + } + + Set result = Collections.emptySet(); + ElementScanner9, Set> scanner = + new AnnotationSetMultiScanner(result); + + for (Element element : rootElements) + result = scanner.scan(element, annotationSet); + + return result; + } + // Could be written as a local class inside getElementsAnnotatedWith private class AnnotationSetScanner extends - ElementScanner9, TypeElement> { + ElementScanningIncludingTypeParameters, TypeElement> { // Insertion-order preserving set - Set annotatedElements = new LinkedHashSet<>(); + private Set annotatedElements = new LinkedHashSet<>(); AnnotationSetScanner(Set defaultSet) { super(defaultSet); } @Override @DefinedBy(Api.LANGUAGE_MODEL) - public Set visitType(TypeElement e, TypeElement p) { + public Set scan(Element e, TypeElement annotation) { + for (AnnotationMirror annotMirror : eltUtils.getAllAnnotationMirrors(e)) { + if (annotation.equals(mirrorAsElement(annotMirror))) { + annotatedElements.add(e); + break; + } + } + e.accept(this, annotation); + return annotatedElements; + } + } + + // Could be written as a local class inside getElementsAnnotatedWithAny + private class AnnotationSetMultiScanner extends + ElementScanningIncludingTypeParameters, Set> { + // Insertion-order preserving set + private Set annotatedElements = new LinkedHashSet<>(); + + AnnotationSetMultiScanner(Set defaultSet) { + super(defaultSet); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Set scan(Element e, Set annotations) { + for (AnnotationMirror annotMirror : eltUtils.getAllAnnotationMirrors(e)) { + if (annotations.contains(mirrorAsElement(annotMirror))) { + annotatedElements.add(e); + break; + } + } + e.accept(this, annotations); + return annotatedElements; + } + } + + private static abstract class ElementScanningIncludingTypeParameters + extends ElementScanner9 { + + protected ElementScanningIncludingTypeParameters(R defaultValue) { + super(defaultValue); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public R visitType(TypeElement e, P p) { // Type parameters are not considered to be enclosed by a type scan(e.getTypeParameters(), p); return super.visitType(e, p); } @Override @DefinedBy(Api.LANGUAGE_MODEL) - public Set visitExecutable(ExecutableElement e, TypeElement p) { + public R visitExecutable(ExecutableElement e, P p) { // Type parameters are not considered to be enclosed by an executable scan(e.getTypeParameters(), p); return super.visitExecutable(e, p); } - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public Set scan(Element e, TypeElement p) { - java.util.List annotationMirrors = - processingEnv.getElementUtils().getAllAnnotationMirrors(e); - for (AnnotationMirror annotationMirror : annotationMirrors) { - if (p.equals(annotationMirror.getAnnotationType().asElement())) - annotatedElements.add(e); - } - e.accept(this, p); - return annotatedElements; - } } /** @@ -172,17 +222,48 @@ public class JavacRoundEnvironment implements RoundEnvironment { */ @DefinedBy(Api.ANNOTATION_PROCESSING) public Set getElementsAnnotatedWith(Class a) { - if (!a.isAnnotation()) - throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); + throwIfNotAnnotation(a); String name = a.getCanonicalName(); if (name == null) return Collections.emptySet(); else { - TypeElement annotationType = processingEnv.getElementUtils().getTypeElement(name); + TypeElement annotationType = eltUtils.getTypeElement(name); if (annotationType == null) return Collections.emptySet(); else return getElementsAnnotatedWith(annotationType); } } + + @DefinedBy(Api.ANNOTATION_PROCESSING) + public Set getElementsAnnotatedWithAny(Set> annotations) { + List annotationsAsElements = new ArrayList<>(annotations.size()); + + for (Class annotation : annotations) { + throwIfNotAnnotation(annotation); + String name = annotation.getCanonicalName(); + if (name == null) + continue; + annotationsAsElements.add(eltUtils.getTypeElement(name)); + } + + return getElementsAnnotatedWithAny(annotationsAsElements.toArray(new TypeElement[0])); + } + + private Element mirrorAsElement(AnnotationMirror annotationMirror) { + return annotationMirror.getAnnotationType().asElement(); + } + + private static final String NOT_AN_ANNOTATION_TYPE = + "The argument does not represent an annotation type: "; + + private void throwIfNotAnnotation(Class a) { + if (!a.isAnnotation()) + throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); + } + + private void throwIfNotAnnotation(TypeElement a) { + if (a.getKind() != ElementKind.ANNOTATION_TYPE) + throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index a531e1793c0..3d6169d4343 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -522,8 +522,9 @@ compiler.err.icls.cant.have.static.decl=\ compiler.err.illegal.char=\ illegal character: ''{0}'' +# 0: string, 1: string compiler.err.illegal.char.for.encoding=\ - unmappable character for encoding {0} + unmappable character (0x{0}) for encoding {1} # 0: set of modifier, 1: set of modifier compiler.err.illegal.combination.of.modifiers=\ @@ -779,6 +780,10 @@ compiler.misc.incompatible.ret.type.in.lambda=\ bad return type in lambda expression\n\ {0} +compiler.misc.stat.expr.expected=\ + lambda body is not compatible with a void functional interface\n\ + (consider using a block lambda body, or use a statement expression instead) + # 0: type compiler.misc.incompatible.ret.type.in.mref=\ bad return type in method reference\n\ @@ -2747,9 +2752,6 @@ compiler.err.module.name.mismatch=\ compiler.err.module.decl.sb.in.module-info.java=\ module declarations should be in a file named module-info.java -compiler.err.unexpected.after.module=\ - unexpected input after module declaration - compiler.err.module-info.with.xmodule.sourcepath=\ illegal combination of -Xmodule and module-info on sourcepath diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java new file mode 100644 index 00000000000..c9c9046c4ea --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java @@ -0,0 +1,255 @@ +/* + * 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 com.sun.tools.javac.util; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.file.Path; +import java.util.Collection; +import java.util.ServiceLoader; + +/** + * This class provides wrappers for classes and methods that are new in JDK 9, and which are not + * available on older versions of the platform on which javac may be compiled and run. + * In future releases, when javac is always compiled on JDK 9 or later, the use of these wrappers + * can be replaced by use of the real underlying classes. + * + *

    Wrapper classes provide a subset of the API of the wrapped classes, as needed for use + * in javac. Wrapper objects contain an {@code Object} reference to the underlying runtime object, + * and {@code Class} and {@code Method} objects for obtaining or using such instances via + * runtime reflection. The {@code Class} and {@code Method} objects are set up on a per-class + * basis, by an {@code init} method, which is called from static methods on the wrapper class, + * or in the constructor, when instances are created. + *

    + * + *

    This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class JDK9Wrappers { + + /** + * Helper class for new method in java.util.ServiceLoader. + */ + public static final class ServiceLoaderHelper { + @SuppressWarnings("unchecked") + public static ServiceLoader load(Layer layer, Class service) { + try { + init(); + Object result = loadMethod.invoke(null, layer.theRealLayer, service); + return (ServiceLoader)result; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException ex) { + throw new Abort(ex); + } + } + + // ----------------------------------------------------------------------------------------- + + private static Method loadMethod = null; + + private static void init() { + if (loadMethod == null) { + try { + Class layerClass = Layer.layerClass; + loadMethod = ServiceLoader.class.getDeclaredMethod("load", layerClass, Class.class); + } catch (NoSuchMethodException | SecurityException ex) { + throw new Abort(ex); + } + } + } + } + + /** + * Wrapper class for java.lang.module.ModuleFinder. + */ + public static class ModuleFinder { + private final Object theRealModuleFinder; + + private ModuleFinder(Object moduleFinder) { + this.theRealModuleFinder = moduleFinder; + init(); + } + + public static ModuleFinder of(Path... dirs) { + try { + init(); + Object result = ofMethod.invoke(null, (Object)dirs); + ModuleFinder mFinder = new ModuleFinder(result); + return mFinder; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException ex) { + throw new Abort(ex); + } + } + + // ----------------------------------------------------------------------------------------- + + private static Class moduleFinderClass = null; + private static Method ofMethod; + + static final Class getModuleFinderClass() { + init(); + return moduleFinderClass; + } + + private static void init() { + if (moduleFinderClass == null) { + try { + moduleFinderClass = Class.forName("java.lang.module.ModuleFinder", false, null); + ofMethod = moduleFinderClass.getDeclaredMethod("of", Path[].class); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { + throw new Abort(ex); + } + } + } + } + + /** + * Wrapper class for java.lang.module.Configuration. + */ + public static final class Configuration { + private final Object theRealConfiguration; + + private Configuration(Object configuration) { + this.theRealConfiguration = configuration; + init(); + } + + public Configuration resolveRequiresAndUses( + ModuleFinder beforeFinder, + ModuleFinder afterFinder, + Collection roots) { + try { + Object result = resolveRequiresAndUsesMethod.invoke(theRealConfiguration, + beforeFinder.theRealModuleFinder, + afterFinder.theRealModuleFinder, + roots + ); + Configuration configuration = new Configuration(result); + return configuration; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException ex) { + throw new Abort(ex); + } + } + + // ----------------------------------------------------------------------------------------- + + private static Class configurationClass = null; + private static Method resolveRequiresAndUsesMethod; + + static final Class getConfigurationClass() { + init(); + return configurationClass; + } + + private static void init() { + if (configurationClass == null) { + try { + configurationClass = Class.forName("java.lang.module.Configuration", false, null); + Class moduleFinderInterface = ModuleFinder.getModuleFinderClass(); + resolveRequiresAndUsesMethod = configurationClass.getDeclaredMethod("resolveRequiresAndUses", + moduleFinderInterface, + moduleFinderInterface, + Collection.class + ); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { + throw new Abort(ex); + } + } + } + } + + /** + * Wrapper class for java.lang.module.Layer. + */ + public static final class Layer { + private final Object theRealLayer; + + private Layer(Object layer) { + this.theRealLayer = layer; + } + + public static Layer boot() { + try { + init(); + Object result = bootMethod.invoke(null); + Layer layer = new Layer(result); + return layer; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException ex) { + throw new Abort(ex); + } + } + + public Configuration configuration() { + try { + Object result = configurationMethod.invoke(theRealLayer); + Configuration configuration = new Configuration(result); + return configuration; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException ex) { + throw new Abort(ex); + } + } + + public Layer defineModulesWithOneLoader(Configuration configuration, ClassLoader parentClassLoader) { + try { + Object result = defineModulesWithOneLoaderMethod.invoke( + theRealLayer, configuration.theRealConfiguration, parentClassLoader); + Layer layer = new Layer(result); + return layer; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException ex) { + throw new Abort(ex); + } + } + + // ----------------------------------------------------------------------------------------- + + private static Class layerClass = null; + private static Method bootMethod; + private static Method defineModulesWithOneLoaderMethod; + private static Method configurationMethod; + + private static void init() { + if (layerClass == null) { + try { + layerClass = Class.forName("java.lang.reflect.Layer", false, null); + bootMethod = layerClass.getDeclaredMethod("boot"); + defineModulesWithOneLoaderMethod = layerClass.getDeclaredMethod("defineModulesWithOneLoader", + Configuration.getConfigurationClass(), + ClassLoader.class); + configurationMethod = layerClass.getDeclaredMethod("configuration"); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { + throw new Abort(ex); + } + } + } + } +} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java deleted file mode 100644 index a2adaac8257..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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 com.sun.tools.javac.util; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.file.Path; -import java.util.Collection; -import java.util.ServiceLoader; - -/** This class provides wrappers for classes and methods that are new in JDK 9, and which are not - * available on older versions of the platform on which javac may be compiled and run. - * In future releases, when javac is always compiled on JDK 9 or later, the use of these wrappers - * can be replaced by use of the real underlying classes. - */ -public class ModuleWrappers { - public static final class ServiceLoaderHelper { - @SuppressWarnings("unchecked") - public static ServiceLoader load(Layer layer, Class service) { - try { - Class layerClass = LayerHelper.getLayerClass(); - Method loadMethod = ServiceLoader.class - .getDeclaredMethod("load", layerClass, Class.class); - Object result = loadMethod.invoke(ServiceLoader.class, layer.theRealLayer, service); - return (ServiceLoader)result; - } catch (NoSuchMethodException | - SecurityException | - IllegalArgumentException | - IllegalAccessException | - InvocationTargetException ex) { - throw new Abort(ex); - } - } - } - - public static class ModuleFinder { - Object theRealModuleFinder; - - private ModuleFinder(Object moduleFinder) { - this.theRealModuleFinder = moduleFinder; - } - - public static ModuleFinder of(Path... dirs) { - try { - Object result = ModuleFinderHelper.getOfMethod() - .invoke(ModuleFinderHelper.moduleFinderInterface, (Object)dirs); - ModuleFinder mFinder = new ModuleFinder(result); - return mFinder; - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { - throw new Abort(ex); - } - } - - public static ModuleFinder empty() { - try { - Object result = ModuleFinderHelper.getEmptyMethod() - .invoke(ModuleFinderHelper.moduleFinderInterface); - ModuleFinder mFinder = new ModuleFinder(result); - return mFinder; - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { - throw new Abort(ex); - } - } - } - - private static class ModuleFinderHelper { - static Method ofMethod = null; - static Method emptyMethod = null; - static Class moduleFinderInterface; - - static Method getOfMethod() { - if (ModuleFinderHelper.ofMethod == null) { - try { - getModuleFinderInterface(); - ofMethod = moduleFinderInterface.getDeclaredMethod("of", Path[].class); - } catch (NoSuchMethodException | SecurityException ex) { - throw new Abort(ex); - } - } - return ofMethod; - } - - static Method getEmptyMethod() { - if (emptyMethod == null) { - try { - getModuleFinderInterface(); - emptyMethod = moduleFinderInterface.getDeclaredMethod("empty"); - } catch (NoSuchMethodException | SecurityException ex) { - throw new Abort(ex); - } - } - return emptyMethod; - } - - static Class getModuleFinderInterface() { - if (moduleFinderInterface == null) { - try { - moduleFinderInterface = Class.forName("java.lang.module.ModuleFinder", false, ClassLoader.getSystemClassLoader()); - } catch (ClassNotFoundException ex) { - throw new Abort(ex); - } - } - return moduleFinderInterface; - } - } - - public static final class Configuration { - Object theRealConfiguration; - - private Configuration(Object configuration) { - this.theRealConfiguration = configuration; - } - - public Configuration resolveRequiresAndUses( - ModuleFinder beforeFinder, - ModuleFinder afterFinder, - Collection roots) { - try { - Object result = ConfigurationHelper.getResolveRequiresAndUses() - .invoke(theRealConfiguration, - beforeFinder.theRealModuleFinder, - afterFinder.theRealModuleFinder, - roots - ); - Configuration configuration = new Configuration(result); - return configuration; - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { - throw new Abort(ex); - } - } - } - - private static class ConfigurationHelper { - static Method resolveRequiresAndUsesMethod; - static Class configurationClass; - - static Method getResolveRequiresAndUses() { - if (resolveRequiresAndUsesMethod == null) { - try { - getConfigurationClass(); - Class moduleFinderInterface = ModuleFinderHelper.getModuleFinderInterface(); - Class configurationClass = ConfigurationHelper.getConfigurationClass(); - resolveRequiresAndUsesMethod = configurationClass.getDeclaredMethod("resolveRequiresAndUses", - moduleFinderInterface, - moduleFinderInterface, - Collection.class - ); - } catch (NoSuchMethodException | SecurityException ex) { - throw new Abort(ex); - } - } - return resolveRequiresAndUsesMethod; - } - - static Class getConfigurationClass() { - if (configurationClass == null) { - try { - configurationClass = Class.forName("java.lang.module.Configuration", false, ClassLoader.getSystemClassLoader()); - } catch (ClassNotFoundException ex) { - throw new Abort(ex); - } - } - return configurationClass; - } - } - - public static final class Layer { - Object theRealLayer; - - private Layer(Object layer) { - this.theRealLayer = layer; - } - - public static Layer boot() { - try { - Object result = LayerHelper.getBootMethod().invoke(LayerHelper.getLayerClass()); - Layer layer = new Layer(result); - return layer; - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { - throw new Abort(ex); - } - } - - public Configuration configuration() { - try { - Object result = LayerHelper.getConfigurationMethod().invoke(theRealLayer); - Layer layer = new Layer(result); - return new Configuration(result); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { - throw new Abort(ex); - } - } - - public Layer defineModulesWithOneLoader(Configuration configuration, ClassLoader parentClassLoader) { - try { - Object result = LayerHelper.getDefineModulesWithOneLoaderMethod() - .invoke(theRealLayer, configuration.theRealConfiguration, parentClassLoader); - Layer layer = new Layer(result); - return layer; - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { - throw new Abort(ex); - } - } - - } - - private static class LayerHelper { - static Class layerClass; - static Method bootMethod; - static Method defineModulesWithOneLoaderMethod = null; - static Method configurationMethod; - - static Class getLayerClass() { - if (layerClass == null) { - try { - layerClass = Class.forName("java.lang.reflect.Layer", false, ClassLoader.getSystemClassLoader()); - } catch (ClassNotFoundException ex) { - throw new Abort(ex); - } - } - return layerClass; - } - - static Method getBootMethod() { - if (bootMethod == null) { - try { - bootMethod = getLayerClass().getDeclaredMethod("boot"); - } catch (NoSuchMethodException | SecurityException ex) { - throw new Abort(ex); - } - } - return bootMethod; - } - - static Method getDefineModulesWithOneLoaderMethod() { - if (defineModulesWithOneLoaderMethod == null) { - try { - defineModulesWithOneLoaderMethod = getLayerClass().getDeclaredMethod("defineModulesWithOneLoader", - ConfigurationHelper.getConfigurationClass(), - ClassLoader.class - ); - } catch (NoSuchMethodException | SecurityException ex) { - throw new Abort(ex); - } - } - return defineModulesWithOneLoaderMethod; - } - - static Method getConfigurationMethod() { - if (configurationMethod == null) { - try { - configurationMethod = getLayerClass().getDeclaredMethod("configuration"); - } catch (NoSuchMethodException | SecurityException ex) { - throw new Abort(ex); - } - } - return configurationMethod; - } - } -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java index 96d6dc19fcc..92865d1cb9e 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java @@ -429,6 +429,10 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { public boolean run() throws Util.Exit { + if (!javac_extras.contains("-XDsuppress-tool-removal-message")) { + log.println(getMessage("javah.misc.Deprecation")); + } + Util util = new Util(log, diagnosticListener); if (noArgs || help) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties index 6aa92c15fa5..2ddf5bcc12b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties @@ -164,3 +164,12 @@ err.ioerror=IO error: {0} err.missing.arg=value missing for {0} err.no.classes.specified=no classes specified err.unknown.option=unknown option: {0} + +# +# miscellaneous strings +# +javah.misc.Deprecation=\ + \nWarning:\u0020The javah tool is planned to be removed in the next major\n\ + JDK release. The tool has been superseded by the ''-h'' option added\n\ + to javac in JDK 8. Users are recommended to migrate to using the\n\ + javac ''-h'' option; see the javac man page for more information.\n diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotatedType.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotatedType.java index 01d07dbaa16..0066b693f6b 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotatedType.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotatedType.java @@ -36,7 +36,12 @@ package com.sun.javadoc; * * @author Mahmood Ali * @since 1.8 + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface AnnotatedType extends Type { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationDesc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationDesc.java index ed92848f006..d70635e8634 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationDesc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationDesc.java @@ -32,7 +32,13 @@ package com.sun.javadoc; * * @author Scott Seligman * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface AnnotationDesc { /** @@ -65,7 +71,13 @@ public interface AnnotationDesc { * * @author Scott Seligman * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ + @Deprecated public interface ElementValuePair { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationTypeDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationTypeDoc.java index 148fa8441a5..15559187340 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationTypeDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationTypeDoc.java @@ -31,7 +31,13 @@ package com.sun.javadoc; * * @author Scott Seligman * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface AnnotationTypeDoc extends ClassDoc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationTypeElementDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationTypeElementDoc.java index 6904f7a7eb6..51468cd64c4 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationTypeElementDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationTypeElementDoc.java @@ -31,7 +31,13 @@ package com.sun.javadoc; * * @author Scott Seligman * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface AnnotationTypeElementDoc extends MethodDoc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationValue.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationValue.java index d741c90e5a0..aae05d9a48c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationValue.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/AnnotationValue.java @@ -31,7 +31,13 @@ package com.sun.javadoc; * * @author Scott Seligman * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface AnnotationValue { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ClassDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ClassDoc.java index b6e89031270..b813fbc96a1 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ClassDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ClassDoc.java @@ -40,7 +40,13 @@ package com.sun.javadoc; * @since 1.2 * @author Kaiyang Liu (original) * @author Robert Field (rewrite) + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface ClassDoc extends ProgramElementDoc, Type { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ConstructorDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ConstructorDoc.java index f7f115b29e5..de06703c37e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ConstructorDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ConstructorDoc.java @@ -30,6 +30,12 @@ package com.sun.javadoc; * * @since 1.2 * @author Robert Field + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface ConstructorDoc extends ExecutableMemberDoc { } diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doc.java index 1ade63fe450..00e6af70473 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doc.java @@ -37,7 +37,13 @@ import java.util.Locale; * @since 1.2 * @author Robert Field * @author Scott Seligman (generics, enums, annotations) + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface Doc extends Comparable { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/DocErrorReporter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/DocErrorReporter.java index 7b79c4c8735..ebe2a7e2ff1 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/DocErrorReporter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/DocErrorReporter.java @@ -30,7 +30,13 @@ package com.sun.javadoc; * * @since 1.2 * @author Robert Field + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface DocErrorReporter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doclet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doclet.java index d7db96ebc08..9e42a75465a 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doclet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doclet.java @@ -47,7 +47,13 @@ package com.sun.javadoc; *

    To start the doclet, pass * {@code -doclet} followed by the fully-qualified * name of the starting class on the javadoc tool command line. + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public abstract class Doclet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ExecutableMemberDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ExecutableMemberDoc.java index 9104c08159b..e83cd3e8152 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ExecutableMemberDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ExecutableMemberDoc.java @@ -30,7 +30,13 @@ package com.sun.javadoc; * * @since 1.2 * @author Robert Field + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface ExecutableMemberDoc extends MemberDoc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/FieldDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/FieldDoc.java index 3039f24e959..a5dff4ce5a3 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/FieldDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/FieldDoc.java @@ -32,7 +32,13 @@ package com.sun.javadoc; * * @since 1.2 * @author Robert Field + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface FieldDoc extends MemberDoc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/LanguageVersion.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/LanguageVersion.java index 4e141f4852e..44fb0ac2e06 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/LanguageVersion.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/LanguageVersion.java @@ -36,7 +36,13 @@ package com.sun.javadoc; * affecting doclets is 1.5. * * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public enum LanguageVersion { /** 1.1 added nested classes and interfaces. */ diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/MemberDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/MemberDoc.java index 2eadeedafa0..852ad969c2b 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/MemberDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/MemberDoc.java @@ -37,7 +37,13 @@ package com.sun.javadoc; * * @author Kaiyang Liu (original) * @author Robert Field (rewrite) + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface MemberDoc extends ProgramElementDoc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/MethodDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/MethodDoc.java index dd447fa25e1..623c2da64f1 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/MethodDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/MethodDoc.java @@ -30,7 +30,13 @@ package com.sun.javadoc; * * @since 1.2 * @author Robert Field + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface MethodDoc extends ExecutableMemberDoc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/PackageDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/PackageDoc.java index 5d870551f70..6b060787cf5 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/PackageDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/PackageDoc.java @@ -36,7 +36,13 @@ package com.sun.javadoc; * @since 1.2 * @author Kaiyang Liu (original) * @author Robert Field (rewrite) + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface PackageDoc extends Doc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ParamTag.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ParamTag.java index 40b34e6d514..cee32bac10e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ParamTag.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ParamTag.java @@ -33,7 +33,12 @@ package com.sun.javadoc; * * @author Robert Field * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface ParamTag extends Tag { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Parameter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Parameter.java index f6d6a5dc9ed..b3880d7819c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Parameter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Parameter.java @@ -30,7 +30,13 @@ package com.sun.javadoc; * This includes a parameter type and parameter name. * * @author Robert Field + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface Parameter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ParameterizedType.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ParameterizedType.java index 3cef8d1bd5c..964d55ed307 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ParameterizedType.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ParameterizedType.java @@ -42,7 +42,13 @@ package com.sun.javadoc; * * @author Scott Seligman * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface ParameterizedType extends Type { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ProgramElementDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ProgramElementDoc.java index d7b195e45d1..6700c5c1ade 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ProgramElementDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ProgramElementDoc.java @@ -35,7 +35,13 @@ package com.sun.javadoc; * @see ClassDoc * * @author Robert Field + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface ProgramElementDoc extends Doc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/RootDoc.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/RootDoc.java index 8a86b5514cb..bdb58b8372c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/RootDoc.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/RootDoc.java @@ -34,7 +34,13 @@ package com.sun.javadoc; * * @since 1.2 * @author Robert Field + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface RootDoc extends Doc, DocErrorReporter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SeeTag.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SeeTag.java index 7bbdab50506..9edf8e7f574 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SeeTag.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SeeTag.java @@ -41,7 +41,12 @@ package com.sun.javadoc; * @author Robert Field (rewrite) * @author Atul M Dambalkar * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface SeeTag extends Tag { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SerialFieldTag.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SerialFieldTag.java index ebf41145b0f..b689d657388 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SerialFieldTag.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SerialFieldTag.java @@ -42,7 +42,13 @@ package com.sun.javadoc; * @author Joe Fialli * * @see java.io.ObjectStreamField + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface SerialFieldTag extends Tag, Comparable { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SourcePosition.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SourcePosition.java index 58a1ad6d566..f9925c40d5f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SourcePosition.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/SourcePosition.java @@ -33,7 +33,13 @@ import java.io.File; * * @since 1.4 * @author Neal M Gafter + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface SourcePosition { /** The source file. Returns null if no file information is * available. diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Tag.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Tag.java index 992a13f3c58..12d22e1446b 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Tag.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Tag.java @@ -44,7 +44,12 @@ import java.util.Locale; * @see SerialFieldTag * @see Doc#tags() * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface Tag { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ThrowsTag.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ThrowsTag.java index 8872a589027..cf478e44518 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ThrowsTag.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/ThrowsTag.java @@ -34,7 +34,12 @@ package com.sun.javadoc; * @author Atul M Dambalkar * @see ExecutableMemberDoc#throwsTags() * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface ThrowsTag extends Tag { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Type.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Type.java index 1700342ffee..9ab1b920088 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Type.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Type.java @@ -35,7 +35,13 @@ package com.sun.javadoc; * @author Kaiyang Liu (original) * @author Robert Field (rewrite) * @author Scott Seligman (generics) + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface Type { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/TypeVariable.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/TypeVariable.java index 90f57d456c4..e15c3b4fa4f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/TypeVariable.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/TypeVariable.java @@ -35,7 +35,13 @@ package com.sun.javadoc; * * @author Scott Seligman * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface TypeVariable extends Type { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/WildcardType.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/WildcardType.java index 3816f5886ff..ed14502a24e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/WildcardType.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/WildcardType.java @@ -38,7 +38,13 @@ package com.sun.javadoc; * * @author Scott Seligman * @since 1.5 + * + * @deprecated + * The declarations in this package have been superseded by those + * in the package {@code jdk.javadoc.doclet}. + * For more information, see the Migration Guide in the documentation for that package. */ +@Deprecated public interface WildcardType extends Type { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/package-info.java index 36a9f5c224c..3a58a8c7d79 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/package-info.java @@ -27,6 +27,7 @@

    Note: The declarations in this package have been superseded by those in the package {@code jdk.javadoc.doclet}. +For more information, see the Migration Guide in the documentation for that package.

    The Doclet API (also called the Javadoc API) provides a mechanism @@ -149,4 +150,5 @@ producing output like: @see com.sun.javadoc.Doclet @see com.sun.javadoc.RootDoc */ +@Deprecated package com.sun.javadoc; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java index 16578ea9ada..9165014d098 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java @@ -64,8 +64,11 @@ import com.sun.javadoc.*; * * @since 1.4 * @author Jamie Ho + * + * @deprecated + * This interface has been superseded by one in the new package {@code jdk.javadoc.doclet.taglet}. */ - +@Deprecated public interface Taglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java index 2e7cb7efae1..b86d03739f8 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public abstract class AbstractExecutableMemberWriter extends AbstractMemberWriter { public AbstractExecutableMemberWriter(SubWriterHolderWriter writer, diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java index 30a4e8d1acb..afcceca1990 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java @@ -50,6 +50,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class AbstractIndexWriter extends HtmlDocletWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java index 54d8046ff1d..b50374e7ba6 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java @@ -47,6 +47,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho (Re-write) * @author Bhavesh Patel (Modified) */ +@Deprecated public abstract class AbstractMemberWriter { protected final ConfigurationImpl configuration; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java index 3adbee4dd40..23b71ebcdda 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.util.DocPath; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java index cd4c70f47bb..920061c428f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Atul M Dambalkar */ +@Deprecated public abstract class AbstractTreeWriter extends HtmlDocletWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java index 32f30f3331b..db1fca799fd 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java @@ -48,6 +48,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Doug Kramer * @author Bhavesh Patel (Modified) */ +@Deprecated public class AllClassesFrameWriter extends HtmlDocletWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java index d5b9597f281..5a35613aadf 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * * @author Bhavesh Patel */ +@Deprecated public class AnnotationTypeFieldWriterImpl extends AbstractMemberWriter implements AnnotationTypeFieldWriter, MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java index 66f60f986d0..91064762b12 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @author Jamie Ho * @author Bhavesh Patel (Modified) */ +@Deprecated public class AnnotationTypeOptionalMemberWriterImpl extends AnnotationTypeRequiredMemberWriterImpl implements AnnotationTypeOptionalMemberWriter, MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java index 63ed9459a17..1b6f76d91cc 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @author Jamie Ho * @author Bhavesh Patel (Modified) */ +@Deprecated public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter implements AnnotationTypeRequiredMemberWriter, MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java index 447b93bdbf1..d77902733b0 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java @@ -51,6 +51,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Robert Field * @author Bhavesh Patel (Modified) */ +@Deprecated public class AnnotationTypeWriterImpl extends SubWriterHolderWriter implements AnnotationTypeWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java index 883e65795ae..04b163155cd 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java @@ -52,6 +52,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Robert G. Field * @author Bhavesh Patel (Modified) */ +@Deprecated public class ClassUseWriter extends SubWriterHolderWriter { final ClassDoc classdoc; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java index 348054f1269..8e14be9b376 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java @@ -55,6 +55,7 @@ import java.io.IOException; * @author Robert Field * @author Bhavesh Patel (Modified) */ +@Deprecated public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java index 83fc46a34e0..3164df0226d 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java @@ -65,6 +65,7 @@ import com.sun.tools.javadoc.main.RootDocImpl; * @author Jamie Ho * @author Bhavesh Patel (Modified) */ +@Deprecated public class ConfigurationImpl extends Configuration { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java index 10abd4b6cfd..733a8179d0c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.4 */ +@Deprecated public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements ConstantsSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java index e3d4077b0eb..4f1f770b1e7 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class ConstructorWriterImpl extends AbstractExecutableMemberWriter implements ConstructorWriter, MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java index 85c6dc8ec59..c77961a9bec 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class DeprecatedListWriter extends SubWriterHolderWriter { private static final String[] ANCHORS = new String[] { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java index 82ac9748ba1..9c280caf90a 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho * @author Bhavesh Patel (Modified) */ +@Deprecated public class EnumConstantWriterImpl extends AbstractMemberWriter implements EnumConstantWriter, MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java index 7d1455bfad0..a823bef9bbd 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho (rewrite) * @author Bhavesh Patel (Modified) */ +@Deprecated public class FieldWriterImpl extends AbstractMemberWriter implements FieldWriter, MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java index 66408158a9b..adf2f0f90a6 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java @@ -48,6 +48,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Atul M Dambalkar */ +@Deprecated public class FrameOutputWriter extends HtmlDocletWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java index d5b7c0f1b13..d4d685834ad 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Atul M Dambalkar */ +@Deprecated public class HelpWriter extends HtmlDocletWriter { HtmlTree mainTree = HtmlTree.MAIN(); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java index edae1473950..1820adfbff6 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho * */ +@Deprecated public class HtmlDoclet extends AbstractDoclet { // An instance will be created by validOptions, and used by start. private static HtmlDoclet docletToStart = null; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java index e2a60468303..387534cf205 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java @@ -53,6 +53,7 @@ import com.sun.tools.javac.util.StringUtils; * @author Robert Field * @author Bhavesh Patel (Modified) */ +@Deprecated public class HtmlDocletWriter extends HtmlDocWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java index 8597adaeba2..d9317c40812 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.taglets.*; * @author Joe Fialli * @author Bhavesh Patel (Modified) */ +@Deprecated public class HtmlSerialFieldWriter extends FieldWriterImpl implements SerializedFormWriter.SerialFieldWriter { ProgramElementDoc[] members = null; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java index 69e9af928d0..5e8b94fc286 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.taglets.*; * @author Joe Fialli * @author Bhavesh Patel (Modified) */ +@Deprecated public class HtmlSerialMethodWriter extends MethodWriterImpl implements SerializedFormWriter.SerialMethodWriter{ diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java index 3dd59058949..059ab6bd81f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.links.*; * @author Jamie Ho * @since 1.5 */ +@Deprecated public class LinkFactoryImpl extends LinkFactory { private HtmlDocletWriter m_writer; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java index e138aebe369..e0660d7a130 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java @@ -37,6 +37,7 @@ import com.sun.tools.doclets.internal.toolkit.util.links.*; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public class LinkInfoImpl extends LinkInfo { public enum Kind { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkOutputImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkOutputImpl.java index 11e2dfcb4bf..cca252c7b6d 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkOutputImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkOutputImpl.java @@ -38,6 +38,7 @@ import com.sun.tools.doclets.internal.toolkit.util.links.*; * @author Jamie Ho * @since 1.5 */ +@Deprecated public class LinkOutputImpl implements LinkOutput { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java index 0e833810bb7..7603ec30351 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java @@ -46,6 +46,7 @@ import com.sun.tools.javac.util.StringUtils; * @author Jamie Ho (rewrite) * @author Bhavesh Patel (Modified) */ +@Deprecated public class MethodWriterImpl extends AbstractExecutableMemberWriter implements MethodWriter, MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java index b93acd75569..f1f05e99522 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho (rewrite) * @author Bhavesh Patel (Modified) */ +@Deprecated public class NestedClassWriterImpl extends AbstractMemberWriter implements MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java index a86610636e7..d6192063ba3 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class PackageFrameWriter extends HtmlDocletWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java index 10b0a8b8cf0..21b65fcc810 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Atul M Dambalkar */ +@Deprecated public class PackageIndexFrameWriter extends AbstractPackageIndexWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java index 6cf48e41672..ef8c1cc5f4e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class PackageIndexWriter extends AbstractPackageIndexWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java index 4519ca7b834..ac13d789fcf 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class PackageTreeWriter extends AbstractTreeWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java index 1fdd5f6430a..ef01f9a3a38 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Robert G. Field * @author Bhavesh Patel (Modified) */ +@Deprecated public class PackageUseWriter extends SubWriterHolderWriter { final PackageDoc pkgdoc; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java index 1bab8c79c68..f9732f90084 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class PackageWriterImpl extends HtmlDocletWriter implements PackageSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PropertyWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PropertyWriterImpl.java index 2c9b4ff181b..1ce8e81fa20 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PropertyWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PropertyWriterImpl.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho (rewrite) * @author Bhavesh Patel (Modified) */ +@Deprecated public class PropertyWriterImpl extends AbstractMemberWriter implements PropertyWriter, MemberSummaryWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SearchIndexItem.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SearchIndexItem.java index 2c68967f091..e4e76c99bcc 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SearchIndexItem.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SearchIndexItem.java @@ -33,6 +33,7 @@ package com.sun.tools.doclets.formats.html; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public class SearchIndexItem { private String label = ""; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SectionName.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SectionName.java index b27949fe988..b281e4eb2ef 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SectionName.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SectionName.java @@ -35,6 +35,7 @@ package com.sun.tools.doclets.formats.html; * * @author Bhavesh Patel */ +@Deprecated public enum SectionName { ANNOTATION_TYPE_ELEMENT_DETAIL("annotation.type.element.detail"), diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java index c4c19101aca..f9de12b0b8d 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.DocletAbortException; * * @author Atul M Dambalkar */ +@Deprecated public class SerializedFormWriterImpl extends SubWriterHolderWriter implements SerializedFormWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java index 990f062b397..6d1176e3645 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class SingleIndexWriter extends AbstractIndexWriter { private List elements; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java index 216f0f7886a..fb2233d0d3c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -33,6 +33,7 @@ import com.sun.javadoc.*; import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.javadoc.main.SourcePositionImpl; /** * Converts Java Source Code to HTML. @@ -46,6 +47,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.4 */ +@Deprecated public class SourceToHTMLConverter { /** @@ -149,8 +151,8 @@ public class SourceToHTMLConverter { return; Reader r; // temp hack until we can update SourcePosition API. - if (sp instanceof com.sun.tools.javadoc.main.SourcePositionImpl) { - FileObject fo = ((com.sun.tools.javadoc.main.SourcePositionImpl) sp).fileObject(); + if (sp instanceof SourcePositionImpl) { + FileObject fo = ((SourcePositionImpl) sp).fileObject(); if (fo == null) return; r = fo.openReader(true); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java index 0415381041e..2d819866d10 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class SplitIndexWriter extends AbstractIndexWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java index 7778a1898c2..d519320847c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java @@ -53,6 +53,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public abstract class SubWriterHolderWriter extends HtmlDocletWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java index 9b671d1d3ae..1c8be3f8717 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java @@ -49,6 +49,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) */ +@Deprecated public class TagletWriterImpl extends TagletWriter { private final HtmlDocletWriter htmlWriter; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java index 13bd494d404..8f62376c075 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java @@ -47,6 +47,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class TreeWriter extends AbstractTreeWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java index f2401acb91d..d3ced42dd6e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho * @since 1.5 */ +@Deprecated public class WriterFactoryImpl implements WriterFactory { private final ConfigurationImpl configuration; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java index 7d68b3f8bfe..4d431c9cfbd 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Bhavesh Patel */ +@Deprecated public class Comment extends Content { private String commentText; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/ContentBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/ContentBuilder.java index 5d3cc530c83..d520cca4c78 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/ContentBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/ContentBuilder.java @@ -35,6 +35,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; /** * A sequence of Content nodes. */ +@Deprecated public class ContentBuilder extends Content { protected List contents = Collections.emptyList(); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java index 0a1285228fc..e87d2776287 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Bhavesh Patel */ +@Deprecated public class DocType extends Content { private String docType; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java index 5f389abc845..6c324eac7f2 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java @@ -37,6 +37,7 @@ import com.sun.tools.javac.util.StringUtils; * * @author Bhavesh Patel */ +@Deprecated public enum HtmlAttr { ALT, CLASS, diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java index e5addad2c77..54fedb0ef98 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java @@ -37,6 +37,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * * @author Bhavesh Patel */ +@Deprecated public class HtmlConstants { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java index bc2bc9e7966..7ea864f1394 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java @@ -53,6 +53,7 @@ import com.sun.tools.doclets.internal.toolkit.util.DocPaths; * @author Atul M Dambalkar * @author Robert Field */ +@Deprecated public abstract class HtmlDocWriter extends HtmlWriter { public static final String CONTENT_TYPE = "text/html"; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java index 1476b27d42d..b6aefd9067e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Bhavesh Patel */ +@Deprecated public class HtmlDocument extends Content { private List docContent = Collections.emptyList(); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java index 0d472ebc9f8..52a3b573f5f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java @@ -35,6 +35,7 @@ package com.sun.tools.doclets.formats.html.markup; * * @author Bhavesh Patel */ +@Deprecated public enum HtmlStyle { aboutLanguage, activeTableTab, diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java index 1f82922809f..d8fad045a0c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java @@ -37,6 +37,7 @@ import com.sun.tools.javac.util.StringUtils; * * @author Bhavesh Patel */ +@Deprecated public enum HtmlTag { A(BlockType.INLINE, EndTag.END), BLOCKQUOTE, diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java index 23e9c6d7a93..83d680c9822 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.formats.html.markup.HtmlAttr.Role; * * @author Bhavesh Patel */ +@Deprecated public class HtmlTree extends Content { private HtmlTag htmlTag; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlVersion.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlVersion.java index b16e8ffcd09..76b1f4bc8f9 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlVersion.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlVersion.java @@ -30,6 +30,7 @@ package com.sun.tools.doclets.formats.html.markup; * * @author Bhavesh Patel */ +@Deprecated public enum HtmlVersion { HTML4, HTML5, diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java index 19940dc2e4b..27bb1182fee 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Atul M Dambalkar * @author Bhavesh Patel (Modified) */ +@Deprecated public class HtmlWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java index a6e6408f3da..6949dd23e72 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Bhavesh Patel */ +@Deprecated public class RawHtml extends Content { private String rawHtmlContent; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java index 03bd4035c6a..43f9693e41d 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Bhavesh Patel */ +@Deprecated public class StringContent extends Content { private StringBuilder stringContent; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java index e4d62a10583..20fd386f9cc 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Jamie Ho */ +@Deprecated public abstract class AbstractDoclet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeFieldWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeFieldWriter.java index b556ccc7c86..b16f18303a8 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeFieldWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeFieldWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.8 */ +@Deprecated public interface AnnotationTypeFieldWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java index 18ada19f80b..c3ae75897c4 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java @@ -40,6 +40,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface AnnotationTypeOptionalMemberWriter extends AnnotationTypeRequiredMemberWriter { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java index 294d3217195..c4b3e9e01c2 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java @@ -42,6 +42,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface AnnotationTypeRequiredMemberWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java index d7ae8e335c7..63454a6fd05 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface AnnotationTypeWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java index 332679e1769..370ae3ddc57 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface ClassWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java index f86f874cba4..268a66211de 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java @@ -54,6 +54,7 @@ import com.sun.tools.javac.util.StringUtils; * @author Atul Dambalkar. * @author Jamie Ho */ +@Deprecated public abstract class Configuration { /** @@ -714,43 +715,43 @@ public abstract class Configuration { } public String getText(String key) { - try { - //Check the doclet specific properties file. - return getDocletSpecificMsg().getText(key); - } catch (Exception e) { - //Check the shared properties file. - return message.getText(key); + // Check the doclet specific properties file. + MessageRetriever docletMessage = getDocletSpecificMsg(); + if (docletMessage.containsKey(key)) { + return docletMessage.getText(key); } + // Check the shared properties file. + return message.getText(key); } public String getText(String key, String a1) { - try { - //Check the doclet specific properties file. - return getDocletSpecificMsg().getText(key, a1); - } catch (Exception e) { - //Check the shared properties file. - return message.getText(key, a1); + // Check the doclet specific properties file. + MessageRetriever docletMessage = getDocletSpecificMsg(); + if (docletMessage.containsKey(key)) { + return docletMessage.getText(key, a1); } + // Check the shared properties file. + return message.getText(key, a1); } public String getText(String key, String a1, String a2) { - try { - //Check the doclet specific properties file. - return getDocletSpecificMsg().getText(key, a1, a2); - } catch (Exception e) { - //Check the shared properties file. - return message.getText(key, a1, a2); + // Check the doclet specific properties file. + MessageRetriever docletMessage = getDocletSpecificMsg(); + if (docletMessage.containsKey(key)) { + return docletMessage.getText(key, a1, a2); } + // Check the shared properties file. + return message.getText(key, a1, a2); } public String getText(String key, String a1, String a2, String a3) { - try { - //Check the doclet specific properties file. - return getDocletSpecificMsg().getText(key, a1, a2, a3); - } catch (Exception e) { - //Check the shared properties file. - return message.getText(key, a1, a2, a3); + // Check the doclet specific properties file. + MessageRetriever docletMessage = getDocletSpecificMsg(); + if (docletMessage.containsKey(key)) { + return docletMessage.getText(key, a1, a2, a3); } + // Check the shared properties file. + return message.getText(key, a1, a2, a3); } public abstract Content newContent(); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java index 64404dcc8ca..f5e19d175b2 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java @@ -43,6 +43,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface ConstantsSummaryWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java index f784b4ae4ec..648168a30fd 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface ConstructorWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java index f5ba106e543..5a44a9a4c07 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Bhavesh Patel */ +@Deprecated public abstract class Content { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java index 987c52f07ad..76aa4f31a95 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface EnumConstantWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java index 554f1999e27..406d097003b 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface FieldWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java index ed7bf560704..f18d1106e99 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java @@ -42,6 +42,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface MemberSummaryWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java index ce4b90e1956..b57a791c016 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface MethodWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java index 4aea9097955..ca9fa5c1b3f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java @@ -40,6 +40,7 @@ import java.io.*; * @since 1.5 */ +@Deprecated public interface NestedClassWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java index fea2b02b40a..050e4b65770 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java @@ -42,6 +42,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface PackageSummaryWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/PropertyWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/PropertyWriter.java index 971af7cac31..40d7085f825 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/PropertyWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/PropertyWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.7 */ +@Deprecated public interface PropertyWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java index 6c72e57410e..a652c99ebb3 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @since 1.5 */ +@Deprecated public interface SerializedFormWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java index 865049f95d4..c24b8bf2238 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java @@ -40,6 +40,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @since 1.4 */ +@Deprecated public interface WriterFactory { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java index a95e0813771..e95ac5f7d98 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java @@ -52,6 +52,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @since 1.5 */ +@Deprecated public abstract class AbstractBuilder { public static class Context { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java index 590f3d47d8f..4acea626fe4 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho * @since 1.5 */ +@Deprecated public abstract class AbstractMemberBuilder extends AbstractBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java index 5f9de80f0d5..5d9a4df74d3 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class AnnotationTypeBuilder extends AbstractBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeFieldBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeFieldBuilder.java index d4efa8776e5..0e52d101611 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeFieldBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeFieldBuilder.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel * @since 1.8 */ +@Deprecated public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java index 9c28e9eae4d..c35d51f2b6d 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class AnnotationTypeOptionalMemberBuilder extends AnnotationTypeRequiredMemberBuilder { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java index c82644ba386..f1708495e1e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java index 972fc9eba39..3e4f4e4fa79 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @since 1.4 */ +@Deprecated public class BuilderFactory { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java index 2746020bff6..994e0e8831e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class ClassBuilder extends AbstractBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java index 702fb7725d1..89ff56e93b0 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class ConstantsSummaryBuilder extends AbstractBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java index 8a65a29ef65..594909fd124 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class ConstructorBuilder extends AbstractMemberBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java index 38832a66b72..2f759cb8862 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class EnumConstantBuilder extends AbstractMemberBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java index 2b206d9b58f..675ae28376f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class FieldBuilder extends AbstractMemberBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java index 662dc16ef9e..2e0783c455c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java @@ -49,6 +49,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @since 1.5 * @see SAXParser */ +@Deprecated public class LayoutParser extends DefaultHandler { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java index d6945d5c642..bab5f9f08c6 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class MemberSummaryBuilder extends AbstractMemberBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java index 1fea3e8fb42..abd7a757704 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class MethodBuilder extends AbstractMemberBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java index 11074d9a987..fad38eec48e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class PackageSummaryBuilder extends AbstractBuilder { /** * The root element of the package summary XML is {@value}. diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PropertyBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PropertyBuilder.java index 5a12f081b76..ba04ab2bd33 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PropertyBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PropertyBuilder.java @@ -43,6 +43,7 @@ import com.sun.javadoc.*; * @author Bhavesh Patel (Modified) * @since 1.7 */ +@Deprecated public class PropertyBuilder extends AbstractMemberBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java index 6bbc46610fe..983d3faf2ef 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java @@ -45,6 +45,7 @@ import com.sun.tools.javac.util.StringUtils; * @author Bhavesh Patel (Modified) * @since 1.5 */ +@Deprecated public class SerializedFormBuilder extends AbstractBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/XMLNode.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/XMLNode.java index 7c4f3b74c0c..f32bd6681fa 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/XMLNode.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/XMLNode.java @@ -38,6 +38,7 @@ import java.util.Map; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public class XMLNode { XMLNode(XMLNode parent, String qname) { this.parent = parent; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseExecutableMemberTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseExecutableMemberTaglet.java index ce15461cc99..403f0721049 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseExecutableMemberTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseExecutableMemberTaglet.java @@ -37,6 +37,7 @@ package com.sun.tools.doclets.internal.toolkit.taglets; * @author Jamie Ho * @since 1.4 */ +@Deprecated public abstract class BaseExecutableMemberTaglet extends BaseTaglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseInlineTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseInlineTaglet.java index 24383b8a0c2..e20b6761c11 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseInlineTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseInlineTaglet.java @@ -37,6 +37,7 @@ package com.sun.tools.doclets.internal.toolkit.taglets; * @since 1.4 */ +@Deprecated public abstract class BaseInlineTaglet extends BaseTaglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BasePropertyTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BasePropertyTaglet.java index e93c9028053..3a4fd36ec40 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BasePropertyTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BasePropertyTaglet.java @@ -38,6 +38,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * deletion without notice. * */ +@Deprecated public abstract class BasePropertyTaglet extends BaseTaglet { public BasePropertyTaglet() { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseTaglet.java index 01ba3ecc5d4..b12a5e71220 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/BaseTaglet.java @@ -39,6 +39,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @author Jamie Ho * @since 1.4 */ +@Deprecated public abstract class BaseTaglet implements Taglet { protected String name = "Default"; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/CodeTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/CodeTaglet.java index e6717e96b51..5cd44bee7e8 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/CodeTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/CodeTaglet.java @@ -50,6 +50,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @since 1.5 */ +@Deprecated public class CodeTaglet extends BaseInlineTaglet { private static final String NAME = "code"; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DeprecatedTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DeprecatedTaglet.java index 258fe7298a5..23f557b9675 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DeprecatedTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DeprecatedTaglet.java @@ -40,6 +40,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @since 1.5 */ +@Deprecated public class DeprecatedTaglet extends BaseTaglet{ public DeprecatedTaglet() { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DocRootTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DocRootTaglet.java index 1a64127358f..7d26b3739b3 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DocRootTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/DocRootTaglet.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @since 1.4 */ +@Deprecated public class DocRootTaglet extends BaseInlineTaglet { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/IndexTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/IndexTaglet.java index 16fa05230f4..16a94defeb3 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/IndexTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/IndexTaglet.java @@ -37,6 +37,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @author Bhavesh Patel */ +@Deprecated public class IndexTaglet extends BaseInlineTaglet { private static final String NAME = "index"; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritDocTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritDocTaglet.java index 4a09d3c4208..05e17d93590 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritDocTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritDocTaglet.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @since 1.4 */ +@Deprecated public class InheritDocTaglet extends BaseInlineTaglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritableTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritableTaglet.java index 89518e8f002..c29a0490505 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritableTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/InheritableTaglet.java @@ -39,6 +39,7 @@ import com.sun.tools.doclets.internal.toolkit.util.DocFinder; * @author Jamie Ho * @since 1.5 */ +@Deprecated public interface InheritableTaglet extends Taglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java index 2dfce45c157..f9bd360f427 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java @@ -47,6 +47,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @author Jamie Ho */ +@Deprecated public class LegacyTaglet implements Taglet { private com.sun.tools.doclets.Taglet legacyTaglet; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LiteralTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LiteralTaglet.java index 2bc9f99c8ce..b6898039701 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LiteralTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LiteralTaglet.java @@ -49,6 +49,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @since 1.5 */ +@Deprecated public class LiteralTaglet extends BaseInlineTaglet { private static final String NAME = "literal"; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ParamTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ParamTaglet.java index d84ed31dac2..54ca871c3d1 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ParamTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ParamTaglet.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho * @since 1.4 */ +@Deprecated public class ParamTaglet extends BaseTaglet implements InheritableTaglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertyGetterTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertyGetterTaglet.java index d41229e3255..b52ace4846f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertyGetterTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertyGetterTaglet.java @@ -34,6 +34,7 @@ package com.sun.tools.doclets.internal.toolkit.taglets; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public class PropertyGetterTaglet extends BasePropertyTaglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertySetterTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertySetterTaglet.java index 6da9af657ff..bc6f31bc7f8 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertySetterTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/PropertySetterTaglet.java @@ -34,6 +34,7 @@ package com.sun.tools.doclets.internal.toolkit.taglets; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public class PropertySetterTaglet extends BasePropertyTaglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ReturnTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ReturnTaglet.java index 0345fa3bcc5..35d2f20ce9c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ReturnTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ReturnTaglet.java @@ -40,6 +40,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho * @since 1.4 */ +@Deprecated public class ReturnTaglet extends BaseExecutableMemberTaglet implements InheritableTaglet { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SeeTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SeeTaglet.java index e8dff03cf7a..a7a13841b75 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SeeTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SeeTaglet.java @@ -40,6 +40,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho * @since 1.4 */ +@Deprecated public class SeeTaglet extends BaseTaglet implements InheritableTaglet { public SeeTaglet() { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SimpleTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SimpleTaglet.java index 1e47459fa9c..28f0d97bf06 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SimpleTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/SimpleTaglet.java @@ -41,6 +41,7 @@ import com.sun.tools.javac.util.StringUtils; * @author Jamie Ho */ +@Deprecated public class SimpleTaglet extends BaseTaglet implements InheritableTaglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/Taglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/Taglet.java index e10e21ab953..1a219971a05 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/Taglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/Taglet.java @@ -60,6 +60,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @author Jamie Ho */ +@Deprecated public interface Taglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java index 1b43a69ae06..aa5a2dc62e6 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java @@ -49,6 +49,7 @@ import com.sun.tools.javac.util.StringUtils; * @since 1.4 */ +@Deprecated public class TagletManager { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletWriter.java index e1764ff17bc..1a8e1957810 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletWriter.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho */ +@Deprecated public abstract class TagletWriter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ThrowsTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ThrowsTaglet.java index cae8165f0fb..17ce4b9878f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ThrowsTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ThrowsTaglet.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Jamie Ho * @since 1.4 */ +@Deprecated public class ThrowsTaglet extends BaseExecutableMemberTaglet implements InheritableTaglet { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java index 6f6ebdc66e5..4d70742bad1 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java @@ -50,6 +50,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @since 1.4 */ +@Deprecated public class ValueTaglet extends BaseInlineTaglet { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassDocCatalog.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassDocCatalog.java index 2ef9f36e570..301efdbc704 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassDocCatalog.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassDocCatalog.java @@ -44,31 +44,31 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; * @author Jamie Ho * @since 1.4 */ +@Deprecated +public class ClassDocCatalog { - public class ClassDocCatalog { - - /** - * Stores the set of packages that the classes specified on the command line - * belong to. Note that the default package is "". - */ - private Set packageSet; + /** + * Stores the set of packages that the classes specified on the command line + * belong to. Note that the default package is "". + */ + private Set packageSet; - /** - * Stores all classes for each package - */ - private Map> allClasses; + /** + * Stores all classes for each package + */ + private Map> allClasses; - /** - * Stores ordinary classes (excluding Exceptions and Errors) for each - * package - */ - private Map> ordinaryClasses; + /** + * Stores ordinary classes (excluding Exceptions and Errors) for each + * package + */ + private Map> ordinaryClasses; - /** - * Stores exceptions for each package - */ - private Map> exceptions; + /** + * Stores exceptions for each package + */ + private Map> exceptions; /** * Stores enums for each package. @@ -80,57 +80,57 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; */ private Map> annotationTypes; - /** - * Stores errors for each package - */ - private Map> errors; + /** + * Stores errors for each package + */ + private Map> errors; - /** - * Stores interfaces for each package - */ - private Map> interfaces; + /** + * Stores interfaces for each package + */ + private Map> interfaces; - private Configuration configuration; - private Utils utils; + private Configuration configuration; + private Utils utils; - /** - * Construct a new ClassDocCatalog. - * - * @param classdocs the array of ClassDocs to catalog - */ - public ClassDocCatalog (ClassDoc[] classdocs, Configuration config) { - init(); - this.configuration = config; - this.utils = config.utils; - for (ClassDoc classdoc : classdocs) { - addClassDoc(classdoc); - } - } + /** + * Construct a new ClassDocCatalog. + * + * @param classdocs the array of ClassDocs to catalog + */ + public ClassDocCatalog (ClassDoc[] classdocs, Configuration config) { + init(); + this.configuration = config; + this.utils = config.utils; + for (ClassDoc classdoc : classdocs) { + addClassDoc(classdoc); + } + } - /** - * Construct a new ClassDocCatalog. - * - */ - public ClassDocCatalog () { - init(); - } + /** + * Construct a new ClassDocCatalog. + * + */ + public ClassDocCatalog () { + init(); + } - private void init() { - allClasses = new HashMap<>(); - ordinaryClasses = new HashMap<>(); - exceptions = new HashMap<>(); - enums = new HashMap<>(); - annotationTypes = new HashMap<>(); - errors = new HashMap<>(); - interfaces = new HashMap<>(); - packageSet = new HashSet<>(); - } + private void init() { + allClasses = new HashMap<>(); + ordinaryClasses = new HashMap<>(); + exceptions = new HashMap<>(); + enums = new HashMap<>(); + annotationTypes = new HashMap<>(); + errors = new HashMap<>(); + interfaces = new HashMap<>(); + packageSet = new HashSet<>(); + } - /** - * Add the given class to the catalog. - * @param classdoc the ClassDoc to add to the catelog. - */ - public void addClassDoc(ClassDoc classdoc) { + /** + * Add the given class to the catalog. + * @param classdoc the ClassDoc to add to the catelog. + */ + public void addClassDoc(ClassDoc classdoc) { if (classdoc == null) { return; } @@ -148,139 +148,139 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; } else if (classdoc.isInterface()) { addClass(classdoc, interfaces); } - } + } - /** - * Add the given class to the given map. - * @param classdoc the ClassDoc to add to the catelog. - * @param map the Map to add the ClassDoc to. - */ - private void addClass(ClassDoc classdoc, Map> map) { + /** + * Add the given class to the given map. + * @param classdoc the ClassDoc to add to the catelog. + * @param map the Map to add the ClassDoc to. + */ + private void addClass(ClassDoc classdoc, Map> map) { - PackageDoc pkg = classdoc.containingPackage(); - if (pkg.isIncluded() || (configuration.nodeprecated && utils.isDeprecated(pkg))) { - //No need to catalog this class if it's package is - //included on the command line or if -nodeprecated option is set - // and the containing package is marked as deprecated. - return; - } - String key = utils.getPackageName(pkg); - Set s = map.get(key); - if (s == null) { - packageSet.add(key); - s = new HashSet<>(); - } - s.add(classdoc); - map.put(key, s); + PackageDoc pkg = classdoc.containingPackage(); + if (pkg.isIncluded() || (configuration.nodeprecated && utils.isDeprecated(pkg))) { + //No need to catalog this class if it's package is + //included on the command line or if -nodeprecated option is set + // and the containing package is marked as deprecated. + return; + } + String key = utils.getPackageName(pkg); + Set s = map.get(key); + if (s == null) { + packageSet.add(key); + s = new HashSet<>(); + } + s.add(classdoc); + map.put(key, s); - } + } - private ClassDoc[] getArray(Map> m, String key) { - Set s = m.get(key); - if (s == null) { - return new ClassDoc[] {}; - } else { - return s.toArray(new ClassDoc[] {}); - } - } + private ClassDoc[] getArray(Map> m, String key) { + Set s = m.get(key); + if (s == null) { + return new ClassDoc[] {}; + } else { + return s.toArray(new ClassDoc[] {}); + } + } - /** - * Return all of the classes specified on the command-line that - * belong to the given package. - * @param pkgDoc the package to return the classes for. - */ - public ClassDoc[] allClasses(PackageDoc pkgDoc) { - return pkgDoc.isIncluded() ? - pkgDoc.allClasses() : - getArray(allClasses, utils.getPackageName(pkgDoc)); - } + /** + * Return all of the classes specified on the command-line that + * belong to the given package. + * @param pkgDoc the package to return the classes for. + */ + public ClassDoc[] allClasses(PackageDoc pkgDoc) { + return pkgDoc.isIncluded() ? + pkgDoc.allClasses() : + getArray(allClasses, utils.getPackageName(pkgDoc)); + } - /** - * Return all of the classes specified on the command-line that - * belong to the given package. - * @param packageName the name of the package specified on the - * command-line. - */ - public ClassDoc[] allClasses(String packageName) { - return getArray(allClasses, packageName); - } + /** + * Return all of the classes specified on the command-line that + * belong to the given package. + * @param packageName the name of the package specified on the + * command-line. + */ + public ClassDoc[] allClasses(String packageName) { + return getArray(allClasses, packageName); + } - /** - * Return the array of package names that this catalog stores - * ClassDocs for. - */ - public String[] packageNames() { - return packageSet.toArray(new String[] {}); - } + /** + * Return the array of package names that this catalog stores + * ClassDocs for. + */ + public String[] packageNames() { + return packageSet.toArray(new String[] {}); + } - /** - * Return true if the given package is known to this catalog. - * @param packageName the name to check. - * @return true if this catalog has any information about - * classes in the given package. - */ - public boolean isKnownPackage(String packageName) { - return packageSet.contains(packageName); - } + /** + * Return true if the given package is known to this catalog. + * @param packageName the name to check. + * @return true if this catalog has any information about + * classes in the given package. + */ + public boolean isKnownPackage(String packageName) { + return packageSet.contains(packageName); + } - /** - * Return all of the errors specified on the command-line - * that belong to the given package. - * @param packageName the name of the package specified on the - * command-line. - */ - public ClassDoc[] errors(String packageName) { - return getArray(errors, packageName); - } + /** + * Return all of the errors specified on the command-line + * that belong to the given package. + * @param packageName the name of the package specified on the + * command-line. + */ + public ClassDoc[] errors(String packageName) { + return getArray(errors, packageName); + } - /** - * Return all of the exceptions specified on the command-line - * that belong to the given package. - * @param packageName the name of the package specified on the - * command-line. - */ - public ClassDoc[] exceptions(String packageName) { - return getArray(exceptions, packageName); - } + /** + * Return all of the exceptions specified on the command-line + * that belong to the given package. + * @param packageName the name of the package specified on the + * command-line. + */ + public ClassDoc[] exceptions(String packageName) { + return getArray(exceptions, packageName); + } - /** - * Return all of the enums specified on the command-line - * that belong to the given package. - * @param packageName the name of the package specified on the - * command-line. - */ - public ClassDoc[] enums(String packageName) { - return getArray(enums, packageName); - } + /** + * Return all of the enums specified on the command-line + * that belong to the given package. + * @param packageName the name of the package specified on the + * command-line. + */ + public ClassDoc[] enums(String packageName) { + return getArray(enums, packageName); + } - /** - * Return all of the annotation types specified on the command-line - * that belong to the given package. - * @param packageName the name of the package specified on the - * command-line. - */ - public ClassDoc[] annotationTypes(String packageName) { - return getArray(annotationTypes, packageName); - } + /** + * Return all of the annotation types specified on the command-line + * that belong to the given package. + * @param packageName the name of the package specified on the + * command-line. + */ + public ClassDoc[] annotationTypes(String packageName) { + return getArray(annotationTypes, packageName); + } - /** - * Return all of the interfaces specified on the command-line - * that belong to the given package. - * @param packageName the name of the package specified on the - * command-line. - */ - public ClassDoc[] interfaces(String packageName) { - return getArray(interfaces, packageName); - } + /** + * Return all of the interfaces specified on the command-line + * that belong to the given package. + * @param packageName the name of the package specified on the + * command-line. + */ + public ClassDoc[] interfaces(String packageName) { + return getArray(interfaces, packageName); + } - /** - * Return all of the ordinary classes specified on the command-line - * that belong to the given package. - * @param packageName the name of the package specified on the - * command-line. - */ - public ClassDoc[] ordinaryClasses(String packageName) { - return getArray(ordinaryClasses, packageName); - } + /** + * Return all of the ordinary classes specified on the command-line + * that belong to the given package. + * @param packageName the name of the package specified on the + * command-line. + */ + public ClassDoc[] ordinaryClasses(String packageName) { + return getArray(ordinaryClasses, packageName); + } } diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassTree.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassTree.java index bc6b74e7c89..3d23d0494a0 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassTree.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassTree.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @see com.sun.javadoc.ClassDoc * @author Atul M Dambalkar */ +@Deprecated public class ClassTree { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassUseMapper.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassUseMapper.java index 604fa9e0f3c..206bc69ae77 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassUseMapper.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassUseMapper.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.formats.html.ConfigurationImpl; * @since 1.2 * @author Robert G. Field */ +@Deprecated public class ClassUseMapper { private final ClassTree classtree; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DeprecatedAPIListBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DeprecatedAPIListBuilder.java index 1290345b3ec..e4f43fd7500 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DeprecatedAPIListBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DeprecatedAPIListBuilder.java @@ -40,6 +40,7 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; * * @author Atul M Dambalkar */ +@Deprecated public class DeprecatedAPIListBuilder { public static final int NUM_TYPES = 12; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java index 7bc33a8d916..16b438e09e7 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java @@ -52,6 +52,7 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; * * @since 8 */ +@Deprecated public abstract class DocFile { /** Create a DocFile for a directory. */ diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java index 8b71150643d..b3437ab8bfc 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; * * @since 1.8 */ +@Deprecated abstract class DocFileFactory { private static final Map factories = new WeakHashMap<>(); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFinder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFinder.java index e8cfea666db..8f9df7a5b26 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFinder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFinder.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.taglets.*; * @author Jamie Ho * @since 1.5 */ +@Deprecated public class DocFinder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocLink.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocLink.java index 48ff3d492bd..4bfc31104c6 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocLink.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocLink.java @@ -38,6 +38,7 @@ package com.sun.tools.doclets.internal.toolkit.util; * deletion without notice. * */ +@Deprecated public class DocLink { final String path; final String query; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPath.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPath.java index 055d449a862..4651eba7bee 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPath.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPath.java @@ -37,6 +37,7 @@ import com.sun.javadoc.PackageDoc; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public class DocPath { private final String path; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java index 06e5b275c77..452fa52ac7e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java @@ -35,6 +35,7 @@ package com.sun.tools.doclets.internal.toolkit.util; * * @since 8 */ +@Deprecated public class DocPaths { /** The name of the file for all classes, using frames. */ diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java index d1b23a579ac..573948dc99a 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java @@ -31,6 +31,7 @@ package com.sun.tools.doclets.internal.toolkit.util; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public class DocletAbortException extends RuntimeException { private static final long serialVersionUID = -9131058909576418984L; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletConstants.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletConstants.java index 5742cd0bf6a..b2970386fdb 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletConstants.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletConstants.java @@ -37,6 +37,7 @@ package com.sun.tools.doclets.internal.toolkit.util; * @author Jamie Ho * @since 1.5 */ +@Deprecated public class DocletConstants { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java index 88f3d929c8c..ef75a3ecedb 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java @@ -50,6 +50,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @author Atul M Dambalkar * @author Robert Field */ +@Deprecated public class Extern { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Group.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Group.java index 5c46cb40de9..87e0c3fa169 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Group.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Group.java @@ -56,6 +56,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * * @author Atul M Dambalkar */ +@Deprecated public class Group { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ImplementedMethods.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ImplementedMethods.java index da528ab7857..041d45a6eaf 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ImplementedMethods.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ImplementedMethods.java @@ -41,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; * * @author Atul M Dambalkar */ +@Deprecated public class ImplementedMethods { private final Map interfaces = new HashMap<>(); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/IndexBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/IndexBuilder.java index bd950bc8557..d9185a37b67 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/IndexBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/IndexBuilder.java @@ -45,6 +45,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @see java.lang.Character * @author Atul M Dambalkar */ +@Deprecated public class IndexBuilder { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java index e357556d5bf..ed7776e7638 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java @@ -44,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; * @author Atul M Dambalkar * @author Robert Field */ +@Deprecated public class MessageRetriever { /** * The global configuration information for this run. @@ -83,6 +84,34 @@ public class MessageRetriever { this.resourcelocation = resourcelocation; } + private ResourceBundle initRB() { + ResourceBundle bundle = messageRB; + if (bundle == null) { + try { + messageRB = bundle = + ResourceBundle.getBundle(resourcelocation, configuration.getLocale()); + } catch (MissingResourceException e) { + throw new Error("Fatal: Resource (" + resourcelocation + + ") for javadoc doclets is missing."); + } + } + return bundle; + } + + /** + * Determines whether the given key can be retrieved + * from this MessageRetriever + * + * @param key + * the resource key + * @return true if the given key is + * contained in the underlying ResourceBundle. + */ + public boolean containsKey(String key) { + ResourceBundle bundle = initRB(); + return bundle.containsKey(key); + } + /** * Get and format message string from resource * @@ -92,15 +121,8 @@ public class MessageRetriever { * exist in the properties file. */ public String getText(String key, Object... args) throws MissingResourceException { - if (messageRB == null) { - try { - messageRB = ResourceBundle.getBundle(resourcelocation); - } catch (MissingResourceException e) { - throw new Error("Fatal: Resource (" + resourcelocation + - ") for javadoc doclets is missing."); - } - } - String message = messageRB.getString(key); + ResourceBundle bundle = initRB(); + String message = bundle.getString(key); return MessageFormat.format(message, args); } diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java index 57758996c45..a3960fc93e3 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java @@ -43,6 +43,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * * @author Doug Kramer */ +@Deprecated public class MetaKeywords { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MethodTypes.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MethodTypes.java index 24254350a9e..d387bde21c0 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MethodTypes.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MethodTypes.java @@ -30,6 +30,7 @@ package com.sun.tools.doclets.internal.toolkit.util; * * @author Bhavesh Patel */ +@Deprecated public enum MethodTypes { ALL(0xffff, "doclet.All_Methods", "t0", true), STATIC(0x1, "doclet.Static_Methods", "t1", false), diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/PackageListWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/PackageListWriter.java index 9e1a0dc083f..10022992ca9 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/PackageListWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/PackageListWriter.java @@ -42,6 +42,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @see com.sun.javadoc.PackageDoc * @author Atul M Dambalkar */ +@Deprecated public class PackageListWriter extends PrintWriter { private final Configuration configuration; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java index f20012a5865..d018bf9fede 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java @@ -64,6 +64,7 @@ import com.sun.tools.javac.util.Assert; * * @since 1.8 */ +@Deprecated class StandardDocFileFactory extends DocFileFactory { private final StandardJavaFileManager fileManager; private Path destDir; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/TextTag.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/TextTag.java index af0a59344fe..881c92460a0 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/TextTag.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/TextTag.java @@ -39,6 +39,7 @@ import com.sun.javadoc.*; * @author Jamie Ho * @since 1.5 */ +@Deprecated public class TextTag implements Tag { protected final String text; protected final String name = "Text"; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java index 0a9acf8a1c8..0b75c7bc2c5 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java @@ -33,10 +33,8 @@ import java.text.Collator; import java.util.*; import javax.tools.JavaFileManager.Location; -import javax.tools.StandardLocation; import com.sun.javadoc.*; -import com.sun.javadoc.AnnotationDesc.ElementValuePair; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.javac.util.StringUtils; @@ -51,6 +49,7 @@ import com.sun.tools.javac.util.StringUtils; * @author Atul M Dambalkar * @author Jamie Ho */ +@Deprecated public class Utils { /** * Return array of class members whose documentation is to be generated. @@ -445,7 +444,7 @@ public class Utils { private boolean isDeclarationTarget(AnnotationDesc targetAnno) { // The error recovery steps here are analogous to TypeAnnotations - ElementValuePair[] elems = targetAnno.elementValues(); + AnnotationDesc.ElementValuePair[] elems = targetAnno.elementValues(); if (elems == null || elems.length != 1 || !"value".equals(elems[0].element().name()) diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java index 487215ca4a0..9c71003eec4 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java @@ -46,6 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * @author Atul M Dambalkar * @author Jamie Ho (rewrite) */ +@Deprecated public class VisibleMemberMap { private boolean noVisibleMembers = true; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkFactory.java index 6ecea31ffba..409e6d6746c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkFactory.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkFactory.java @@ -39,6 +39,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @author Jamie Ho * @since 1.5 */ +@Deprecated public abstract class LinkFactory { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkInfo.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkInfo.java index 842dd616d2b..78b18f01de7 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkInfo.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkInfo.java @@ -40,6 +40,7 @@ import com.sun.tools.doclets.internal.toolkit.Content; * @author Jamie Ho * @since 1.5 */ +@Deprecated public abstract class LinkInfo { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkOutput.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkOutput.java index 32160a2d33b..bc84ab398e8 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkOutput.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/LinkOutput.java @@ -36,6 +36,7 @@ package com.sun.tools.doclets.internal.toolkit.util.links; * @author Jamie Ho * @since 1.5 */ +@Deprecated public interface LinkOutput { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/standard/Standard.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/standard/Standard.java index 7e28d8f6eb2..67d9afd82fb 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/standard/Standard.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/standard/Standard.java @@ -28,7 +28,7 @@ package com.sun.tools.doclets.standard; import com.sun.javadoc.*; import com.sun.tools.doclets.formats.html.*; - +@Deprecated public class Standard { public static int optionLength(String option) { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java index 467fd2d34e0..9e7f1f7a5b0 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -38,8 +38,17 @@ import com.sun.tools.javadoc.main.Start; * This code and its internal interfaces are subject to change or * deletion without notice. * + * @deprecated + * This class is now deprecated and may be removed in a future release. + * See + * {@code javax.tools.ToolProvider::getSystemDocumentationTool} + * and + * {@code javax.tools.DocumentationTool} + * for replacement functionality. + * * @since 1.4 */ +@Deprecated public class Main { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AbstractTypeImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AbstractTypeImpl.java index c0570aa7516..6fafd3a0167 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AbstractTypeImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AbstractTypeImpl.java @@ -43,6 +43,7 @@ import com.sun.tools.javac.code.Type; * @author Scott Seligman * @since 1.5 */ +@Deprecated abstract class AbstractTypeImpl implements com.sun.javadoc.Type { protected final DocEnv env; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotatedTypeImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotatedTypeImpl.java index 982b8744ed5..ecfcb4a2299 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotatedTypeImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotatedTypeImpl.java @@ -37,6 +37,7 @@ import com.sun.tools.javac.util.List; * @author Mahmood Ali * @since 1.8 */ +@Deprecated public class AnnotatedTypeImpl extends AbstractTypeImpl implements AnnotatedType { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationDescImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationDescImpl.java index d348f35ec02..3c1fa11bc29 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationDescImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationDescImpl.java @@ -48,6 +48,7 @@ import com.sun.tools.javac.util.Pair; * @since 1.5 */ +@Deprecated public class AnnotationDescImpl implements AnnotationDesc { private final DocEnv env; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeDocImpl.java index d691959f4c3..3f023a19b85 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeDocImpl.java @@ -48,6 +48,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; * @since 1.5 */ +@Deprecated public class AnnotationTypeDocImpl extends ClassDocImpl implements AnnotationTypeDoc { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeElementDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeElementDocImpl.java index bd0f8284c2d..39cb25e092c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeElementDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeElementDocImpl.java @@ -42,6 +42,7 @@ import com.sun.tools.javac.code.Symbol.*; * @since 1.5 */ +@Deprecated public class AnnotationTypeElementDocImpl extends MethodDocImpl implements AnnotationTypeElementDoc { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationValueImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationValueImpl.java index 036f2b40a88..fe0c9d7bfed 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationValueImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationValueImpl.java @@ -43,6 +43,7 @@ import static com.sun.tools.javac.code.TypeTag.BOOLEAN; * @since 1.5 */ +@Deprecated public class AnnotationValueImpl implements AnnotationValue { private final DocEnv env; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ClassDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ClassDocImpl.java index c1437e007ed..5d57373a2f4 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ClassDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ClassDocImpl.java @@ -86,6 +86,7 @@ import static com.sun.tools.javac.tree.JCTree.Tag.*; * @author Scott Seligman (generics, enums, annotations) */ +@Deprecated public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc { public final ClassType type; // protected->public for debugging diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Comment.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Comment.java index ade553baba9..5df6a5b34e4 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Comment.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Comment.java @@ -45,6 +45,7 @@ import com.sun.tools.javac.util.ListBuffer; * @author Atul M Dambalkar * @author Neal Gafter (rewrite) */ +@Deprecated class Comment { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ConstructorDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ConstructorDocImpl.java index ca53d182e6c..13b473cd111 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ConstructorDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ConstructorDocImpl.java @@ -44,6 +44,7 @@ import com.sun.tools.javac.code.Symbol.MethodSymbol; * @author Neal Gafter (rewrite) */ +@Deprecated public class ConstructorDocImpl extends ExecutableMemberDocImpl implements ConstructorDoc { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java index d123013013b..aaba6fff5ed 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java @@ -72,6 +72,7 @@ import com.sun.tools.javac.util.Names; * @author Neal Gafter (rewrite) * @author Scott Seligman (generics) */ +@Deprecated public class DocEnv { protected static final Context.Key docEnvKey = new Context.Key<>(); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocImpl.java index 0f085e7eeef..9b866df4124 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocImpl.java @@ -56,6 +56,7 @@ import com.sun.tools.javac.util.Position; * @author Atul M Dambalkar * @author Neal Gafter (rewrite) */ +@Deprecated public abstract class DocImpl implements Doc, Comparable { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocLocale.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocLocale.java index 4460d7e311c..b626822abe3 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocLocale.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocLocale.java @@ -40,6 +40,7 @@ import java.util.Locale; * @since 1.4 * @author Robert Field */ +@Deprecated class DocLocale { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocletInvoker.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocletInvoker.java index 402e67ef70b..46265861e33 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocletInvoker.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocletInvoker.java @@ -45,9 +45,6 @@ import com.sun.javadoc.*; import com.sun.tools.javac.util.ClientCodeException; import com.sun.tools.javac.util.List; -import static com.sun.javadoc.LanguageVersion.*; - - /** * Class creates, controls and invokes doclets. * @@ -58,6 +55,7 @@ import static com.sun.javadoc.LanguageVersion.*; * * @author Neal Gafter (rewrite) */ +@Deprecated public class DocletInvoker { private final Class docletClass; @@ -283,16 +281,16 @@ public class DocletInvoker { Class[] paramTypes = new Class[0]; Object[] params = new Object[0]; try { - retVal = invoke(methodName, JAVA_1_1, paramTypes, params); + retVal = invoke(methodName, LanguageVersion.JAVA_1_1, paramTypes, params); } catch (DocletInvokeException exc) { - return JAVA_1_1; + return LanguageVersion.JAVA_1_1; } if (retVal instanceof LanguageVersion) { return (LanguageVersion)retVal; } else { messager.error(Messager.NOPOS, "main.must_return_languageversion", docletClassName, methodName); - return JAVA_1_1; + return LanguageVersion.JAVA_1_1; } } catch (NoClassDefFoundError ex) { // for boostrapping, no Enum class. return null; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ExecutableMemberDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ExecutableMemberDocImpl.java index 30075a96d78..d7120cb8290 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ExecutableMemberDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ExecutableMemberDocImpl.java @@ -51,6 +51,7 @@ import com.sun.tools.javac.util.ListBuffer; * @author Scott Seligman (generics, annotations) */ +@Deprecated public abstract class ExecutableMemberDocImpl extends MemberDocImpl implements ExecutableMemberDoc { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/FieldDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/FieldDocImpl.java index c3432633dc8..1b2c7011427 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/FieldDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/FieldDocImpl.java @@ -51,6 +51,7 @@ import static com.sun.tools.javac.code.TypeTag.BOOLEAN; * @author Neal Gafter (rewrite) * @author Scott Seligman (generics, enums, annotations) */ +@Deprecated public class FieldDocImpl extends MemberDocImpl implements FieldDoc { protected final VarSymbol sym; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocClassFinder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocClassFinder.java index 997b8d97759..b776c36b11d 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocClassFinder.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocClassFinder.java @@ -41,6 +41,7 @@ import com.sun.tools.javac.util.Context; * * @author Neal Gafter */ +@Deprecated public class JavadocClassFinder extends ClassFinder { public static JavadocClassFinder instance(Context context) { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java index a49abaeabb6..56940b2973c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java @@ -48,6 +48,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; * * @author Neal Gafter */ +@Deprecated public class JavadocEnter extends Enter { public static JavadocEnter instance(Context context) { Enter instance = context.get(enterKey); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocMemberEnter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocMemberEnter.java index 452cc614938..96f647b230b 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocMemberEnter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocMemberEnter.java @@ -47,6 +47,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; * * @author Neal Gafter */ +@Deprecated public class JavadocMemberEnter extends MemberEnter { public static JavadocMemberEnter instance0(Context context) { MemberEnter instance = context.get(memberEnterKey); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTodo.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTodo.java index 88ab1ad1dd2..0094ddd9679 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTodo.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTodo.java @@ -39,6 +39,7 @@ import com.sun.tools.javac.util.*; * * @author Neal Gafter */ +@Deprecated public class JavadocTodo extends Todo { public static void preRegister(Context context) { context.put(todoKey, new Context.Factory() { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java index fa358ddf47d..c99769bbda8 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java @@ -67,6 +67,7 @@ import com.sun.tools.javac.util.ListBuffer; * * @author Neal Gafter */ +@Deprecated public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { DocEnv docenv; @@ -187,8 +188,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { syms.unnamedModule.complete(); // TEMP to force reading all named modules // Build up the complete list of any packages to be documented - Location location = - modules.multiModuleMode && !modules.noModules ? StandardLocation.MODULE_SOURCE_PATH + Location location = modules.multiModuleMode ? StandardLocation.MODULE_SOURCE_PATH : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MemberDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MemberDocImpl.java index d87c0ae01f1..661c427e52e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MemberDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MemberDocImpl.java @@ -49,6 +49,7 @@ import com.sun.tools.javac.code.Symbol; * @author Neal Gafter */ +@Deprecated public abstract class MemberDocImpl extends ProgramElementDocImpl implements MemberDoc { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Messager.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Messager.java index d181fb2a82d..416df5a1aa1 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Messager.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Messager.java @@ -52,6 +52,7 @@ import com.sun.tools.javac.util.Log; * @see java.text.MessageFormat * @author Neal Gafter (rewrite) */ +@Deprecated public class Messager extends Log implements DocErrorReporter { public static final SourcePosition NOPOS = null; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MethodDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MethodDocImpl.java index 391eab2b8d3..bf91be66c65 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MethodDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MethodDocImpl.java @@ -47,6 +47,7 @@ import static com.sun.tools.javac.code.TypeTag.CLASS; * @author Neal Gafter (rewrite) */ +@Deprecated public class MethodDocImpl extends ExecutableMemberDocImpl implements MethodDoc { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ModifierFilter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ModifierFilter.java index 76624e64f60..a29ee99db82 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ModifierFilter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ModifierFilter.java @@ -42,6 +42,7 @@ import static com.sun.tools.javac.code.Flags.*; * @author Robert Field */ +@Deprecated public class ModifierFilter { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PackageDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PackageDocImpl.java index a5683240e67..d5bfcfba4e4 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PackageDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PackageDocImpl.java @@ -62,6 +62,7 @@ import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; * @author Scott Seligman (package-info.java) */ +@Deprecated public class PackageDocImpl extends DocImpl implements PackageDoc { public final PackageSymbol sym; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParamTagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParamTagImpl.java index 56cf966f62f..66cd4c54c8d 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParamTagImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParamTagImpl.java @@ -41,6 +41,7 @@ import com.sun.javadoc.*; * @author Robert Field * */ +@Deprecated class ParamTagImpl extends TagImpl implements ParamTag { private static final Pattern typeParamRE = Pattern.compile("<([^<>]+)>"); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterImpl.java index ce047b59c37..c44e86c86b7 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterImpl.java @@ -43,6 +43,7 @@ import com.sun.tools.javac.code.Symbol.VarSymbol; * @author Robert Field (rewrite) * @author Scott Seligman (generics, annotations) */ +@Deprecated class ParameterImpl implements Parameter { private final DocEnv env; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterizedTypeImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterizedTypeImpl.java index e7c8875f76b..0aad1cb8b71 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterizedTypeImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterizedTypeImpl.java @@ -46,6 +46,7 @@ import static com.sun.tools.javac.code.TypeTag.CLASS; * @author Scott Seligman * @since 1.5 */ +@Deprecated public class ParameterizedTypeImpl extends AbstractTypeImpl implements ParameterizedType { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PrimitiveType.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PrimitiveType.java index 79d2a3a246f..97162912782 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PrimitiveType.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PrimitiveType.java @@ -33,6 +33,7 @@ import com.sun.javadoc.*; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated class PrimitiveType implements com.sun.javadoc.Type { private final String name; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ProgramElementDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ProgramElementDocImpl.java index 663263ee166..acacf97d26f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ProgramElementDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ProgramElementDocImpl.java @@ -55,6 +55,7 @@ import com.sun.tools.javac.util.Position; * @author Neal Gafter (rewrite) * @author Scott Seligman (generics, enums, annotations) */ +@Deprecated public abstract class ProgramElementDocImpl extends DocImpl implements ProgramElementDoc { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java index 03157373e7f..0a1053ccd3c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java @@ -54,6 +54,7 @@ import com.sun.tools.javac.util.Position; * @author Atul M Dambalkar * @author Neal Gafter (rewrite) */ +@Deprecated public class RootDocImpl extends DocImpl implements RootDoc { /** diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SeeTagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SeeTagImpl.java index 626a54d81b1..b9e19748368 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SeeTagImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SeeTagImpl.java @@ -50,6 +50,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; * @author Atul M Dambalkar * */ +@Deprecated class SeeTagImpl extends TagImpl implements SeeTag, LayoutCharacters { //### TODO: Searching for classes, fields, and methods diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerialFieldTagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerialFieldTagImpl.java index a7dc95da462..04573c53c60 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerialFieldTagImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerialFieldTagImpl.java @@ -51,6 +51,7 @@ import com.sun.javadoc.*; * * @see java.io.ObjectStreamField */ +@Deprecated class SerialFieldTagImpl extends TagImpl implements SerialFieldTag, Comparable diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerializedForm.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerializedForm.java index f06987ce89e..320df1a83e5 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerializedForm.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerializedForm.java @@ -66,6 +66,7 @@ import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; * @author Joe Fialli * @author Neal Gafter (rewrite but not too proud) */ +@Deprecated class SerializedForm { ListBuffer methods = new ListBuffer<>(); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SourcePositionImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SourcePositionImpl.java index 911e57c8f99..abb73eb293a 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SourcePositionImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SourcePositionImpl.java @@ -43,6 +43,7 @@ import com.sun.tools.javac.util.Position; * @author Neal M Gafter * @author Michael Van De Vanter (position representation changed to char offsets) */ +@Deprecated public class SourcePositionImpl implements SourcePosition { FileObject filename; int position; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Start.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Start.java index 188c6b5fd84..cd07780c6ae 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Start.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Start.java @@ -69,6 +69,7 @@ import static com.sun.tools.javac.code.Flags.*; * @author Robert Field * @author Neal Gafter (rewrite) */ +@Deprecated public class Start extends ToolOption.Helper { /** Context for this invocation. */ private final Context context; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TagImpl.java index 352c9fc7152..b4822b88c2a 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TagImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TagImpl.java @@ -48,6 +48,7 @@ import com.sun.javadoc.*; * @see Doc#tags() * */ +@Deprecated class TagImpl implements Tag { protected final String text; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ThrowsTagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ThrowsTagImpl.java index e92d871263b..3fa552445ff 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ThrowsTagImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ThrowsTagImpl.java @@ -43,6 +43,7 @@ import com.sun.javadoc.*; * @see ExecutableMemberDocImpl#throwsTags() * */ +@Deprecated class ThrowsTagImpl extends TagImpl implements ThrowsTag { private final String exceptionName; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ToolOption.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ToolOption.java index 180f99b5162..47afb073ee5 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ToolOption.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ToolOption.java @@ -43,6 +43,7 @@ import com.sun.tools.javac.util.Options; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public enum ToolOption { // ----- options for underlying compiler ----- diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeMaker.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeMaker.java index 7c18ce120b2..3010c108512 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeMaker.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeMaker.java @@ -42,6 +42,7 @@ import static com.sun.tools.javac.code.TypeTag.ARRAY; * This code and its internal interfaces are subject to change or * deletion without notice. */ +@Deprecated public class TypeMaker { public static com.sun.javadoc.Type getType(DocEnv env, Type t) { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeVariableImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeVariableImpl.java index 8207695e285..d66434a73ab 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeVariableImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeVariableImpl.java @@ -52,6 +52,7 @@ import com.sun.tools.javac.util.Names; * @author Scott Seligman * @since 1.5 */ +@Deprecated public class TypeVariableImpl extends AbstractTypeImpl implements TypeVariable { TypeVariableImpl(DocEnv env, TypeVar type) { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/WildcardTypeImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/WildcardTypeImpl.java index f3b4138e9d7..790216a042a 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/WildcardTypeImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/WildcardTypeImpl.java @@ -44,6 +44,7 @@ import com.sun.tools.javac.util.List; * @author Scott Seligman * @since 1.5 */ +@Deprecated public class WildcardTypeImpl extends AbstractTypeImpl implements WildcardType { WildcardTypeImpl(DocEnv env, Type.WildcardType type) { diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/package-info.java similarity index 75% rename from jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/package-info.java index c9ff689a931..36ef3d78915 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,10 +20,17 @@ * * Please 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.net.http; - -public interface HttpHeaders1 extends HttpHeaders { - public void makeUnmodifiable(); -} +/** + * This package and its contents are deprecated and + * may be removed in a future release. + * See + * {@code javax.tools.ToolProvider.getSystemDocumentationTool} + * and + * {@code javax.tools.DocumentationTool} + * for replacement functionality. + */ +@Deprecated +package com.sun.tools.javadoc; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java index 34eced11854..96f55499fdc 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java @@ -894,43 +894,43 @@ public abstract class Configuration { } public String getText(String key) { - try { - //Check the doclet specific properties file. - return getDocletSpecificMsg().getText(key); - } catch (Exception e) { - //Check the shared properties file. - return message.getText(key); + // Check the doclet specific properties file. + MessageRetriever docletMessage = getDocletSpecificMsg(); + if (docletMessage.containsKey(key)) { + return docletMessage.getText(key); } + // Check the shared properties file. + return message.getText(key); } public String getText(String key, String a1) { - try { - //Check the doclet specific properties file. - return getDocletSpecificMsg().getText(key, a1); - } catch (MissingResourceException e) { - //Check the shared properties file. - return message.getText(key, a1); + // Check the doclet specific properties file. + MessageRetriever docletMessage = getDocletSpecificMsg(); + if (docletMessage.containsKey(key)) { + return docletMessage.getText(key, a1); } + // Check the shared properties file. + return message.getText(key, a1); } public String getText(String key, String a1, String a2) { - try { - //Check the doclet specific properties file. - return getDocletSpecificMsg().getText(key, a1, a2); - } catch (MissingResourceException e) { - //Check the shared properties file. - return message.getText(key, a1, a2); + // Check the doclet specific properties file. + MessageRetriever docletMessage = getDocletSpecificMsg(); + if (docletMessage.containsKey(key)) { + return docletMessage.getText(key, a1, a2); } + // Check the shared properties file. + return message.getText(key, a1, a2); } public String getText(String key, String a1, String a2, String a3) { - try { - //Check the doclet specific properties file. - return getDocletSpecificMsg().getText(key, a1, a2, a3); - } catch (MissingResourceException e) { - //Check the shared properties file. - return message.getText(key, a1, a2, a3); + // Check the doclet specific properties file. + MessageRetriever docletMessage = getDocletSpecificMsg(); + if (docletMessage.containsKey(key)) { + return docletMessage.getText(key, a1, a2, a3); } + // Check the shared properties file. + return message.getText(key, a1, a2, a3); } public abstract Content newContent(); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MessageRetriever.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MessageRetriever.java index 46d9a92123f..63f2ce78cdb 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MessageRetriever.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MessageRetriever.java @@ -86,15 +86,32 @@ public class MessageRetriever { this.resourcelocation = resourcelocation; } - private void initRB() { - if (messageRB == null) { + private ResourceBundle initRB() { + ResourceBundle bundle = messageRB; + if (bundle == null) { try { - messageRB = ResourceBundle.getBundle(resourcelocation, configuration.getLocale()); + messageRB = bundle = + ResourceBundle.getBundle(resourcelocation, configuration.getLocale()); } catch (MissingResourceException e) { throw new Error("Fatal: Resource (" + resourcelocation + ") for javadoc doclets is missing."); } } + return bundle; + } + + /** + * Determines whether the given key can be retrieved + * from this MessageRetriever + * + * @param key + * the resource key + * @return true if the given key is + * contained in the underlying ResourceBundle. + */ + public boolean containsKey(String key) { + ResourceBundle bundle = initRB(); + return bundle.containsKey(key); } /** @@ -107,8 +124,8 @@ public class MessageRetriever { * exist in the properties file. */ public String getText(String key, Object... args) throws MissingResourceException { - initRB(); - String message = messageRB.getString(key); + ResourceBundle bundle = initRB(); + String message = bundle.getString(key); return MessageFormat.format(message, args); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index aaa601e839a..fc3223eb80a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1596,7 +1596,7 @@ public class Utils { first = false; } } catch (SecurityException | IOException exc) { - throw new com.sun.tools.doclets.internal.toolkit.util.DocletAbortException(exc); + throw new DocletAbortException(exc); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java index 227063a25ba..67ca3d7e0ec 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java @@ -192,8 +192,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { syms.unnamedModule.complete(); // TEMP to force reading all named modules // Build up the complete list of any packages to be documented - Location location = - modules.multiModuleMode && !modules.noModules ? StandardLocation.MODULE_SOURCE_PATH + Location location = modules.multiModuleMode ? StandardLocation.MODULE_SOURCE_PATH : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java index a0058e15b0d..3b33fee1691 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java @@ -81,6 +81,7 @@ import static com.sun.tools.javac.main.Option.*; */ public class Start extends ToolOption.Helper { + @SuppressWarnings("deprecation") private static final Class OldStdDoclet = com.sun.tools.doclets.standard.Standard.class; @@ -221,6 +222,7 @@ public class Start extends ToolOption.Helper { * this is to minimize argument processing and most importantly the impact * of class loader creation, needed to detect the doclet/taglet class variants. */ + @SuppressWarnings("deprecation") int begin(String... argv) { // Preprocess @file arguments try { @@ -254,6 +256,7 @@ public class Start extends ToolOption.Helper { return begin(opts, fileObjects); } + @SuppressWarnings("deprecation") private boolean begin(List options, Iterable fileObjects) { fileManager = context.get(JavaFileManager.class); if (fileManager == null) { @@ -270,7 +273,6 @@ public class Start extends ToolOption.Helper { initMessager(); messager.setLocale(locale); try { - @SuppressWarnings("deprecation") Object o = docletClass.newInstance(); doclet = (Doclet) o; } catch (InstantiationException | IllegalAccessException exc) { @@ -563,6 +565,7 @@ public class Start extends ToolOption.Helper { * all other conditions including errors it returns false, allowing * nature to take its own course. */ + @SuppressWarnings("deprecation") private boolean hasOldTaglet(List tagletNames, List tagletPaths) { if (!fileManager.hasLocation(TAGLET_PATH)) { try { diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java index c6fe442e9e3..5de014a08c7 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import com.sun.tools.classfile.Dependency.Filter; @@ -561,13 +562,10 @@ public class Dependencies { } static abstract class BasicDependencyFinder implements Finder { - private Map locations = new HashMap<>(); + private Map locations = new ConcurrentHashMap<>(); Location getLocation(String className) { - Location l = locations.get(className); - if (l == null) - locations.put(className, l = new SimpleLocation(className)); - return l; + return locations.computeIfAbsent(className, cn -> new SimpleLocation(cn)); } class Visitor implements ConstantPool.Visitor, Type.Visitor { diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java index 122862252d0..c39f5f274e6 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java @@ -25,23 +25,24 @@ package com.sun.tools.jdeps; -import java.io.PrintStream; -import java.util.ArrayList; +import static com.sun.tools.jdeps.JdepsConfiguration.*; + +import com.sun.tools.classfile.Dependency.Location; +import java.io.IOException; +import java.io.UncheckedIOException; import java.util.Collections; import java.util.Comparator; -import java.util.Deque; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; import java.util.Map; +import java.util.MissingResourceException; import java.util.Objects; +import java.util.Optional; +import java.util.ResourceBundle; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.sun.tools.classfile.Dependency.Location; - /** * Dependency Analyzer. */ @@ -52,6 +53,7 @@ public class Analyzer { */ public enum Type { SUMMARY, + MODULE, // equivalent to summary in addition, print module descriptor PACKAGE, CLASS, VERBOSE @@ -62,9 +64,11 @@ public class Analyzer { * Only the accepted dependencies are recorded. */ interface Filter { - boolean accepts(Location origin, Archive originArchive, Location target, Archive targetArchive); + boolean accepts(Location origin, Archive originArchive, + Location target, Archive targetArchive); } + protected final JdepsConfiguration configuration; protected final Type type; protected final Filter filter; protected final Map results = new HashMap<>(); @@ -78,7 +82,8 @@ public class Analyzer { * @param type Type of the dependency analysis * @param filter */ - public Analyzer(Type type, Filter filter) { + Analyzer(JdepsConfiguration config, Type type, Filter filter) { + this.configuration = config; this.type = type; this.filter = filter; } @@ -86,16 +91,10 @@ public class Analyzer { /** * Performs the dependency analysis on the given archives. */ - public boolean run(Stream archives) { - return run(archives.collect(Collectors.toList())); - } - - /** - * Performs the dependency analysis on the given archives. - */ - public boolean run(Iterable archives) { - // build a map from Location to Archive - buildLocationArchiveMap(archives); + boolean run(Iterable archives, + Map locationMap) + { + this.locationToArchive.putAll(locationMap); // traverse and analyze all dependencies for (Archive archive : archives) { @@ -106,40 +105,50 @@ public class Analyzer { return true; } - protected void buildLocationArchiveMap(Iterable archives) { - // build a map from Location to Archive - for (Archive archive: archives) { - archive.getClasses() - .forEach(l -> locationToArchive.putIfAbsent(l, archive)); - } + /** + * Returns the analyzed archives + */ + Set archives() { + return results.keySet(); } - public boolean hasDependences(Archive archive) { + /** + * Returns true if the given archive has dependences. + */ + boolean hasDependences(Archive archive) { if (results.containsKey(archive)) { return results.get(archive).dependencies().size() > 0; } return false; } - public Set dependences(Archive source) { + /** + * Returns the dependences, either class name or package name + * as specified in the given verbose level, from the given source. + */ + Set dependences(Archive source) { if (!results.containsKey(source)) { return Collections.emptySet(); } - Dependences result = results.get(source); - return result.dependencies().stream() - .map(Dep::target) - .collect(Collectors.toSet()); + + return results.get(source).dependencies() + .stream() + .map(Dep::target) + .collect(Collectors.toSet()); } - public Stream requires(Archive source) { + /** + * Returns the direct dependences of the given source + */ + Stream requires(Archive source) { if (!results.containsKey(source)) { return Stream.empty(); } - Dependences result = results.get(source); - return result.requires().stream().filter(a -> !a.isEmpty()); + return results.get(source).requires() + .stream(); } - public interface Visitor { + interface Visitor { /** * Visits a recorded dependency from origin to target which can be * a fully-qualified classname, a package name, a module or @@ -153,7 +162,7 @@ public class Analyzer { * Visit the dependencies of the given source. * If the requested level is SUMMARY, it will visit the required archives list. */ - public void visitDependences(Archive source, Visitor v, Type level) { + void visitDependences(Archive source, Visitor v, Type level) { if (level == Type.SUMMARY) { final Dependences result = results.get(source); final Set reqs = result.requires(); @@ -187,7 +196,7 @@ public class Analyzer { } } - public void visitDependences(Archive source, Visitor v) { + void visitDependences(Archive source, Visitor v) { visitDependences(source, v, type); } @@ -224,14 +233,28 @@ public class Analyzer { } } + /* + * Returns the archive that contains the given location. + */ Archive findArchive(Location t) { + // local in this archive if (archive.getClasses().contains(t)) return archive; - return locationToArchive.computeIfAbsent(t, _k -> NOT_FOUND); + Archive target; + if (locationToArchive.containsKey(t)) { + target = locationToArchive.get(t); + } else { + // special case JDK removed API + target = configuration.findClass(t) + .orElseGet(() -> REMOVED_JDK_INTERNALS.contains(t) + ? REMOVED_JDK_INTERNALS + : NOT_FOUND); + } + return locationToArchive.computeIfAbsent(t, _k -> target); } - // return classname or package name depedning on the level + // return classname or package name depending on the level private String getLocationName(Location o) { if (level == Type.CLASS || level == Type.VERBOSE) { return o.getClassName(); @@ -345,4 +368,71 @@ public class Analyzer { target, targetArchive.getName()); } } + + static final JdkInternals REMOVED_JDK_INTERNALS = new JdkInternals(); + + static class JdkInternals extends Module { + private final String BUNDLE = "com.sun.tools.jdeps.resources.jdkinternals"; + + private final Set jdkinternals; + private final Set jdkUnsupportedClasses; + private JdkInternals() { + super("JDK removed internal API"); + + try { + ResourceBundle rb = ResourceBundle.getBundle(BUNDLE); + this.jdkinternals = rb.keySet(); + } catch (MissingResourceException e) { + throw new InternalError("Cannot find jdkinternals resource bundle"); + } + + this.jdkUnsupportedClasses = getUnsupportedClasses(); + } + + public boolean contains(Location location) { + if (jdkUnsupportedClasses.contains(location.getName() + ".class")) { + return false; + } + + String cn = location.getClassName(); + int i = cn.lastIndexOf('.'); + String pn = i > 0 ? cn.substring(0, i) : ""; + return jdkinternals.contains(cn) || jdkinternals.contains(pn); + } + + @Override + public String name() { + return getName(); + } + + @Override + public boolean isJDK() { + return true; + } + + @Override + public boolean isExported(String pn) { + return false; + } + + private Set getUnsupportedClasses() { + // jdk.unsupported may not be observable + Optional om = Profile.FULL_JRE.findModule(JDK_UNSUPPORTED); + if (om.isPresent()) { + return om.get().reader().entries(); + } + + // find from local run-time image + SystemModuleFinder system = new SystemModuleFinder(); + if (system.find(JDK_UNSUPPORTED).isPresent()) { + try { + return system.getClassReader(JDK_UNSUPPORTED).entries(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + return Collections.emptySet(); + } + } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java index 90e4890b2b6..fd5b9a2ed90 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java @@ -27,6 +27,7 @@ package com.sun.tools.jdeps; import com.sun.tools.classfile.Dependency.Location; +import java.io.Closeable; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URI; @@ -38,11 +39,12 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Stream; /** * Represents the source of the class files. */ -public class Archive { +public class Archive implements Closeable { public static Archive getInstance(Path p) { try { return new Archive(p, ClassFileReader.newInstance(p)); @@ -86,6 +88,10 @@ public class Archive { return Module.UNNAMED_MODULE; } + public boolean contains(String entry) { + return reader.entries().contains(entry); + } + public void addClass(Location origin) { deps.computeIfAbsent(origin, _k -> new HashSet<>()); } @@ -98,6 +104,15 @@ public class Archive { return deps.keySet(); } + public Stream getDependencies() { + return deps.values().stream() + .flatMap(Set::stream); + } + + public boolean hasDependences() { + return getDependencies().count() > 0; + } + public void visitDependences(Visitor v) { for (Map.Entry> e: deps.entrySet()) { for (Location target : e.getValue()) { @@ -164,6 +179,13 @@ public class Archive { private boolean isJrt() { return location != null && location.getScheme().equals("jrt"); } + + @Override + public void close() throws IOException { + if (reader != null) + reader.close(); + } + interface Visitor { void visit(Location origin, Location target); } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java index aa2e6ffe7a0..c1b4311a7f1 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java @@ -29,6 +29,7 @@ import com.sun.tools.classfile.ClassFile; import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.Dependencies.ClassFileError; +import java.io.Closeable; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -48,17 +49,18 @@ import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * ClassFileReader reads ClassFile(s) of a given path that can be * a .class file, a directory, or a JAR file. */ -public class ClassFileReader { +public class ClassFileReader implements Closeable { /** * Returns a ClassFileReader instance of a given path. */ public static ClassFileReader newInstance(Path path) throws IOException { - if (!Files.exists(path)) { + if (Files.notExists(path)) { throw new FileNotFoundException(path.toString()); } @@ -173,7 +175,11 @@ public class ClassFileReader { static boolean isClass(Path file) { String fn = file.getFileName().toString(); - return fn.endsWith(".class") && !fn.equals(MODULE_INFO); + return fn.endsWith(".class"); + } + + @Override + public void close() throws IOException { } class FileIterator implements Iterator { @@ -218,13 +224,12 @@ public class ClassFileReader { } protected Set scan() { - try { - return Files.walk(path, Integer.MAX_VALUE) - .filter(ClassFileReader::isClass) - .map(f -> path.relativize(f)) - .map(Path::toString) - .map(p -> p.replace(File.separatorChar, '/')) - .collect(Collectors.toSet()); + try (Stream stream = Files.walk(path, Integer.MAX_VALUE)) { + return stream.filter(ClassFileReader::isClass) + .map(f -> path.relativize(f)) + .map(Path::toString) + .map(p -> p.replace(File.separatorChar, '/')) + .collect(Collectors.toSet()); } catch (IOException e) { throw new UncheckedIOException(e); } @@ -235,7 +240,7 @@ public class ClassFileReader { int i = name.lastIndexOf('.'); String pathname = name.replace(".", fsSep) + ".class"; Path p = path.resolve(pathname); - if (!Files.exists(p)) { + if (Files.notExists(p)) { p = path.resolve(pathname.substring(0, i) + "$" + pathname.substring(i+1, pathname.length())); } @@ -261,13 +266,16 @@ public class ClassFileReader { } class DirectoryIterator implements Iterator { - private List entries; + private final List entries; private int index = 0; DirectoryIterator() throws IOException { - entries = Files.walk(path, Integer.MAX_VALUE) - .filter(ClassFileReader::isClass) - .collect(Collectors.toList()); - index = 0; + List paths = null; + try (Stream stream = Files.walk(path, Integer.MAX_VALUE)) { + paths = stream.filter(ClassFileReader::isClass) + .collect(Collectors.toList()); + } + this.entries = paths; + this.index = 0; } public boolean hasNext() { @@ -303,10 +311,15 @@ public class ClassFileReader { this.jarfile = jf; } + @Override + public void close() throws IOException { + jarfile.close(); + } + protected Set scan() { try (JarFile jf = new JarFile(path.toFile())) { return jf.stream().map(JarEntry::getName) - .filter(n -> n.endsWith(".class") && !n.endsWith(MODULE_INFO)) + .filter(n -> n.endsWith(".class")) .collect(Collectors.toSet()); } catch (IOException e) { throw new UncheckedIOException(e); @@ -409,7 +422,7 @@ public class ClassFileReader { while (entries.hasMoreElements()) { JarEntry e = entries.nextElement(); String name = e.getName(); - if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { + if (name.endsWith(".class")) { return e; } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java index 086e13ac1df..fbcb9a0d955 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java @@ -24,360 +24,285 @@ */ package com.sun.tools.jdeps; +import static com.sun.tools.jdeps.Module.*; +import static com.sun.tools.jdeps.Analyzer.NOT_FOUND; +import static java.util.stream.Collectors.*; + import com.sun.tools.classfile.AccessFlags; import com.sun.tools.classfile.ClassFile; import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.Dependencies; import com.sun.tools.classfile.Dependency; +import com.sun.tools.classfile.Dependency.Location; import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; +import java.io.UncheckedIOException; import java.util.Deque; import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; +import java.util.HashSet; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; -import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.sun.tools.jdeps.Module.*; -import static com.sun.tools.jdeps.ModulePaths.SystemModulePath.JAVA_BASE; +/** + * Parses class files and finds dependences + */ +class DependencyFinder { + private static Finder API_FINDER = new Finder(true); + private static Finder CLASS_FINDER = new Finder(false); -public class DependencyFinder { - private final List roots = new ArrayList<>(); - private final List classpaths = new ArrayList<>(); - private final List modulepaths = new ArrayList<>(); - private final List classes = new ArrayList<>(); - private final boolean compileTimeView; + private final JdepsConfiguration configuration; + private final JdepsFilter filter; - DependencyFinder(boolean compileTimeView) { - this.compileTimeView = compileTimeView; + private final Map> parsedArchives = new ConcurrentHashMap<>(); + private final Map parsedClasses = new ConcurrentHashMap<>(); + + private final ExecutorService pool = Executors.newFixedThreadPool(2); + private final Deque>> tasks = new ConcurrentLinkedDeque<>(); + + DependencyFinder(JdepsConfiguration configuration, + JdepsFilter filter) { + this.configuration = configuration; + this.filter = filter; + this.parsedArchives.put(API_FINDER, new ConcurrentLinkedDeque<>()); + this.parsedArchives.put(CLASS_FINDER, new ConcurrentLinkedDeque<>()); } - /* - * Adds a class name to the root set - */ - void addClassName(String cn) { - classes.add(cn); - } - - /* - * Adds the archive of the given path to the root set - */ - void addRoot(Path path) { - addRoot(Archive.getInstance(path)); - } - - /* - * Adds the given archive to the root set - */ - void addRoot(Archive archive) { - Objects.requireNonNull(archive); - if (!roots.contains(archive)) - roots.add(archive); + Map locationToArchive() { + return parsedClasses; } /** - * Add an archive specified in the classpath. + * Returns the modules of all dependencies found */ - void addClassPathArchive(Path path) { - addClassPathArchive(Archive.getInstance(path)); + Stream getDependences(Archive source) { + return source.getDependencies() + .map(this::locationToArchive) + .filter(a -> a != source); } /** - * Add an archive specified in the classpath. - */ - void addClassPathArchive(Archive archive) { - Objects.requireNonNull(archive); - classpaths.add(archive); - } - - /** - * Add an archive specified in the modulepath. - */ - void addModule(Module m) { - Objects.requireNonNull(m); - modulepaths.add(m); - } - - /** - * Returns the root set. - */ - List roots() { - return roots; - } - - /** - * Returns a stream of all archives including the root set, module paths, - * and classpath. + * Returns the location to archive map; or NOT_FOUND. * - * This only returns the archives with classes parsed. + * Location represents a parsed class. */ - Stream archives() { - Stream archives = Stream.concat(roots.stream(), modulepaths.stream()); - archives = Stream.concat(archives, classpaths.stream()); - return archives.filter(a -> !a.isEmpty()) - .distinct(); + Archive locationToArchive(Location location) { + return parsedClasses.containsKey(location) + ? parsedClasses.get(location) + : configuration.findClass(location).orElse(NOT_FOUND); } /** - * Finds dependencies - * - * @param apiOnly API only - * @param maxDepth depth of transitive dependency analysis; zero indicates - * @throws IOException + * Returns a map from an archive to its required archives */ - void findDependencies(JdepsFilter filter, boolean apiOnly, int maxDepth) - throws IOException - { - Dependency.Finder finder = - apiOnly ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED) - : Dependencies.getClassDependencyFinder(); + Map> dependences() { + Map> map = new HashMap<>(); + parsedArchives.values().stream() + .flatMap(Deque::stream) + .filter(a -> !a.isEmpty()) + .forEach(source -> { + Set deps = getDependences(source).collect(toSet()); + if (!deps.isEmpty()) { + map.put(source, deps); + } + }); + return map; + } - // list of archives to be analyzed - Set roots = new LinkedHashSet<>(this.roots); + boolean isParsed(Location location) { + return parsedClasses.containsKey(location); + } - // include java.base in root set - roots.add(JAVA_BASE); + /** + * Parses all class files from the given archive stream and returns + * all target locations. + */ + public Set parse(Stream archiveStream) { + archiveStream.forEach(archive -> parse(archive, CLASS_FINDER)); + return waitForTasksCompleted(); + } - // If -include pattern specified, classes may be in module path or class path. - // To get compile time view analysis, all classes are analyzed. - // add all modules except JDK modules to root set - modulepaths.stream() - .filter(filter::matches) - .forEach(roots::add); + /** + * Parses the exported API class files from the given archive stream and + * returns all target locations. + */ + public Set parseExportedAPIs(Stream archiveStream) { + archiveStream.forEach(archive -> parse(archive, API_FINDER)); + return waitForTasksCompleted(); + } - // add classpath to the root set - classpaths.stream() - .filter(filter::matches) - .forEach(roots::add); - - // transitive dependency - int depth = maxDepth > 0 ? maxDepth : Integer.MAX_VALUE; - - // Work queue of names of classfiles to be searched. - // Entries will be unique, and for classes that do not yet have - // dependencies in the results map. - ConcurrentLinkedDeque deque = new ConcurrentLinkedDeque<>(); - ConcurrentSkipListSet doneClasses = new ConcurrentSkipListSet<>(); - - TaskExecutor executor = new TaskExecutor(finder, filter, apiOnly, deque, doneClasses); + /** + * Parses the named class from the given archive and + * returns all target locations the named class references. + */ + public Set parse(Archive archive, String name) { try { - // get the immediate dependencies of the input files - for (Archive source : roots) { - executor.task(source, deque); - } - executor.waitForTasksCompleted(); - - List archives = Stream.concat(Stream.concat(roots.stream(), - modulepaths.stream()), - classpaths.stream()) - .collect(Collectors.toList()); - - // Additional pass to find archive where dependences are identified - // and also any specified classes, if any. - // If -R is specified, perform transitive dependency analysis. - Deque unresolved = new LinkedList<>(classes); - do { - String name; - while ((name = unresolved.poll()) != null) { - if (doneClasses.contains(name)) { - continue; - } - if (compileTimeView) { - final String cn = name + ".class"; - // parse all classes in the source archive - Optional source = archives.stream() - .filter(a -> a.reader().entries().contains(cn)) - .findFirst(); - trace("%s compile time view %s%n", name, source.map(Archive::getName).orElse(" not found")); - if (source.isPresent()) { - executor.runTask(source.get(), deque); - } - } - ClassFile cf = null; - for (Archive archive : archives) { - cf = archive.reader().getClassFile(name); - - if (cf != null) { - String classFileName; - try { - classFileName = cf.getName(); - } catch (ConstantPoolException e) { - throw new Dependencies.ClassFileError(e); - } - if (!doneClasses.contains(classFileName)) { - // if name is a fully-qualified class name specified - // from command-line, this class might already be parsed - doneClasses.add(classFileName); - for (Dependency d : finder.findDependencies(cf)) { - if (depth == 0) { - // ignore the dependency - archive.addClass(d.getOrigin()); - break; - } else if (filter.accepts(d) && filter.accept(archive)) { - // continue analysis on non-JDK classes - archive.addClass(d.getOrigin(), d.getTarget()); - String cn = d.getTarget().getName(); - if (!doneClasses.contains(cn) && !deque.contains(cn)) { - deque.add(cn); - } - } else { - // ensure that the parsed class is added the archive - archive.addClass(d.getOrigin()); - } - } - } - break; - } - } - if (cf == null) { - doneClasses.add(name); - } - } - unresolved = deque; - deque = new ConcurrentLinkedDeque<>(); - } while (!unresolved.isEmpty() && depth-- > 0); - } finally { - executor.shutdown(); + return parse(archive, CLASS_FINDER, name); + } catch (IOException e) { + throw new UncheckedIOException(e); } - } + } /** - * TaskExecutor creates FutureTask to analyze all classes in a given archive + * Parses the exported API of the named class from the given archive and + * returns all target locations the named class references. */ - private class TaskExecutor { - final ExecutorService pool; - final Dependency.Finder finder; - final JdepsFilter filter; - final boolean apiOnly; - final Set doneClasses; - final Map> tasks = new HashMap<>(); - - TaskExecutor(Dependency.Finder finder, - JdepsFilter filter, - boolean apiOnly, - ConcurrentLinkedDeque deque, - Set doneClasses) { - this.pool = Executors.newFixedThreadPool(2); - this.finder = finder; - this.filter = filter; - this.apiOnly = apiOnly; - this.doneClasses = doneClasses; + public Set parseExportedAPIs(Archive archive, String name) + { + try { + return parse(archive, API_FINDER, name); + } catch (IOException e) { + throw new UncheckedIOException(e); } + } - /** - * Creates a new task to analyze class files in the given archive. - * The dependences are added to the given deque for analysis. - */ - FutureTask task(Archive archive, final ConcurrentLinkedDeque deque) { - trace("parsing %s %s%n", archive.getName(), archive.path()); - FutureTask task = new FutureTask(new Callable() { - public Void call() throws Exception { - for (ClassFile cf : archive.reader().getClassFiles()) { - String classFileName; - try { - classFileName = cf.getName(); - } catch (ConstantPoolException e) { - throw new Dependencies.ClassFileError(e); - } + private Optional>> parse(Archive archive, Finder finder) { + if (parsedArchives.get(finder).contains(archive)) + return Optional.empty(); - // tests if this class matches the -include - String cn = classFileName.replace('/', '.'); - if (!filter.matches(cn)) - continue; + parsedArchives.get(finder).add(archive); - // if -apionly is specified, analyze only exported and public types - if (apiOnly && !(isExported(archive, cn) && cf.access_flags.is(AccessFlags.ACC_PUBLIC))) - continue; - - if (!doneClasses.contains(classFileName)) { - doneClasses.add(classFileName); - } - - for (Dependency d : finder.findDependencies(cf)) { - if (filter.accepts(d) && filter.accept(archive)) { - String name = d.getTarget().getName(); - if (!doneClasses.contains(name) && !deque.contains(name)) { - deque.add(name); - } - archive.addClass(d.getOrigin(), d.getTarget()); - } else { - // ensure that the parsed class is added the archive - archive.addClass(d.getOrigin()); - } - } + trace("parsing %s %s%n", archive.getName(), archive.path()); + FutureTask> task = new FutureTask<>(new Callable<>() { + public Set call() throws Exception { + Set targets = new HashSet<>(); + for (ClassFile cf : archive.reader().getClassFiles()) { + String classFileName; + try { + classFileName = cf.getName(); + } catch (ConstantPoolException e) { + throw new Dependencies.ClassFileError(e); } - return null; - } - }); - tasks.put(archive, task); - pool.submit(task); - return task; - } - /* - * This task will parse all class files of the given archive, if it's a new task. - * This method waits until the task is completed. - */ - void runTask(Archive archive, final ConcurrentLinkedDeque deque) { - if (tasks.containsKey(archive)) - return; - - FutureTask task = task(archive, deque); - try { - // wait for completion - task.get(); - } catch (InterruptedException|ExecutionException e) { - throw new Error(e); - } - } - - /* - * Waits until all submitted tasks are completed. - */ - void waitForTasksCompleted() { - try { - for (FutureTask t : tasks.values()) { - if (t.isDone()) + // filter source class/archive + String cn = classFileName.replace('/', '.'); + if (!finder.accept(archive, cn, cf.access_flags)) continue; - // wait for completion - t.get(); + // tests if this class matches the -include + if (!filter.matches(cn)) + continue; + + for (Dependency d : finder.findDependencies(cf)) { + if (filter.accepts(d)) { + archive.addClass(d.getOrigin(), d.getTarget()); + targets.add(d.getTarget()); + } else { + // ensure that the parsed class is added the archive + archive.addClass(d.getOrigin()); + } + parsedClasses.putIfAbsent(d.getOrigin(), archive); + } } - } catch (InterruptedException|ExecutionException e) { - throw new Error(e); + + return targets; } + }); + tasks.add(task); + pool.submit(task); + return Optional.of(task); + } + + private Set parse(Archive archive, Finder finder, String name) + throws IOException + { + ClassFile cf = archive.reader().getClassFile(name); + if (cf == null) { + throw new IllegalArgumentException(archive.getName() + " does not contain " + name); } - /* - * Shutdown the executor service. - */ - void shutdown() { - pool.shutdown(); + Set targets = new HashSet<>(); + String cn; + try { + cn = cf.getName().replace('/', '.'); + } catch (ConstantPoolException e) { + throw new Dependencies.ClassFileError(e); } - /** - * Tests if the given class name is exported by the given archive. - * - * All packages are exported in unnamed module. - */ - private boolean isExported(Archive archive, String classname) { - int i = classname.lastIndexOf('.'); - String pn = i > 0 ? classname.substring(0, i) : ""; - return archive.getModule().isExported(pn); + if (!finder.accept(archive, cn, cf.access_flags)) + return targets; + + // tests if this class matches the -include + if (!filter.matches(cn)) + return targets; + + // skip checking filter.matches + for (Dependency d : finder.findDependencies(cf)) { + if (filter.accepts(d)) { + targets.add(d.getTarget()); + archive.addClass(d.getOrigin(), d.getTarget()); + } else { + // ensure that the parsed class is added the archive + archive.addClass(d.getOrigin()); + } + parsedClasses.putIfAbsent(d.getOrigin(), archive); + } + return targets; + } + + /* + * Waits until all submitted tasks are completed. + */ + private Set waitForTasksCompleted() { + try { + Set targets = new HashSet<>(); + FutureTask> task; + while ((task = tasks.poll()) != null) { + // wait for completion + if (!task.isDone()) + targets.addAll(task.get()); + } + return targets; + } catch (InterruptedException|ExecutionException e) { + throw new Error(e); + } + } + + /* + * Shutdown the executor service. + */ + void shutdown() { + pool.shutdown(); + } + + private interface SourceFilter { + boolean accept(Archive archive, String cn, AccessFlags accessFlags); + } + + private static class Finder implements Dependency.Finder, SourceFilter { + private final Dependency.Finder finder; + private final boolean apiOnly; + Finder(boolean apiOnly) { + this.apiOnly = apiOnly; + this.finder = apiOnly + ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED) + : Dependencies.getClassDependencyFinder(); + + } + + @Override + public boolean accept(Archive archive, String cn, AccessFlags accessFlags) { + int i = cn.lastIndexOf('.'); + String pn = i > 0 ? cn.substring(0, i) : ""; + + // if -apionly is specified, analyze only exported and public types + // All packages are exported in unnamed module. + return apiOnly ? archive.getModule().isExported(pn) && + accessFlags.is(AccessFlags.ACC_PUBLIC) + : true; + } + + @Override + public Iterable findDependencies(ClassFile classfile) { + return finder.findDependencies(classfile); } } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java new file mode 100644 index 00000000000..c7444c70d0f --- /dev/null +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java @@ -0,0 +1,392 @@ +/* + * 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 com.sun.tools.jdeps; + +import com.sun.tools.classfile.Dependency.Location; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.sun.tools.jdeps.Analyzer.Type.CLASS; +import static com.sun.tools.jdeps.Analyzer.Type.VERBOSE; +import static com.sun.tools.jdeps.Module.trace; +import static java.util.stream.Collectors.*; + +/** + * Dependency Analyzer. + * + * Type of filters: + * source filter: -include + * target filter: -package, -regex, -requires + * + * The initial archive set for analysis includes + * 1. archives specified in the command line arguments + * 2. observable modules matching the source filter + * 3. classpath archives matching the source filter or target filter + * 4. -addmods and -m root modules + */ +public class DepsAnalyzer { + final JdepsConfiguration configuration; + final JdepsFilter filter; + final JdepsWriter writer; + final Analyzer.Type verbose; + final boolean apiOnly; + + final DependencyFinder finder; + final Analyzer analyzer; + final List rootArchives = new ArrayList<>(); + + // parsed archives + final Set archives = new LinkedHashSet<>(); + + public DepsAnalyzer(JdepsConfiguration config, + JdepsFilter filter, + JdepsWriter writer, + Analyzer.Type verbose, + boolean apiOnly) { + this.configuration = config; + this.filter = filter; + this.writer = writer; + this.verbose = verbose; + this.apiOnly = apiOnly; + + this.finder = new DependencyFinder(config, filter); + this.analyzer = new Analyzer(configuration, verbose, filter); + + // determine initial archives to be analyzed + this.rootArchives.addAll(configuration.initialArchives()); + + // if -include pattern is specified, add the matching archives on + // classpath to the root archives + if (filter.hasIncludePattern() || filter.hasTargetFilter()) { + configuration.getModules().values().stream() + .filter(source -> filter.include(source) && filter.matches(source)) + .forEach(this.rootArchives::add); + } + + // class path archives + configuration.classPathArchives().stream() + .filter(filter::matches) + .forEach(this.rootArchives::add); + + // Include the root modules for analysis + this.rootArchives.addAll(configuration.rootModules()); + + trace("analyze root archives: %s%n", this.rootArchives); + } + + /* + * Perform runtime dependency analysis + */ + public boolean run() throws IOException { + return run(false, 1); + } + + /** + * Perform compile-time view or run-time view dependency analysis. + * + * @param compileTimeView + * @param maxDepth depth of recursive analysis. depth == 0 if -R is set + */ + public boolean run(boolean compileTimeView, int maxDepth) throws IOException { + try { + // parse each packaged module or classpath archive + if (apiOnly) { + finder.parseExportedAPIs(rootArchives.stream()); + } else { + finder.parse(rootArchives.stream()); + } + archives.addAll(rootArchives); + + int depth = maxDepth > 0 ? maxDepth : Integer.MAX_VALUE; + + // transitive analysis + if (depth > 1) { + if (compileTimeView) + transitiveArchiveDeps(depth-1); + else + transitiveDeps(depth-1); + } + + Set archives = archives(); + + // analyze the dependencies collected + analyzer.run(archives, finder.locationToArchive()); + + writer.generateOutput(archives, analyzer); + } finally { + finder.shutdown(); + } + return true; + } + + /** + * Returns the archives for reporting that has matching dependences. + * + * If -requires is set, they should be excluded. + */ + Set archives() { + if (filter.requiresFilter().isEmpty()) { + return archives.stream() + .filter(filter::include) + .filter(Archive::hasDependences) + .collect(Collectors.toSet()); + } else { + // use the archives that have dependences and not specified in -requires + return archives.stream() + .filter(filter::include) + .filter(source -> !filter.requiresFilter().contains(source)) + .filter(source -> + source.getDependencies() + .map(finder::locationToArchive) + .anyMatch(a -> a != source)) + .collect(Collectors.toSet()); + } + } + + /** + * Returns the dependences, either class name or package name + * as specified in the given verbose level. + */ + Stream dependences() { + return analyzer.archives().stream() + .map(analyzer::dependences) + .flatMap(Set::stream) + .distinct(); + } + + /** + * Returns the archives that contains the given locations and + * not parsed and analyzed. + */ + private Set unresolvedArchives(Stream locations) { + return locations.filter(l -> !finder.isParsed(l)) + .distinct() + .map(configuration::findClass) + .flatMap(Optional::stream) + .filter(filter::include) + .collect(toSet()); + } + + /* + * Recursively analyzes entire module/archives. + */ + private void transitiveArchiveDeps(int depth) throws IOException { + Stream deps = archives.stream() + .flatMap(Archive::getDependencies); + + // start with the unresolved archives + Set unresolved = unresolvedArchives(deps); + do { + // parse all unresolved archives + Set targets = apiOnly + ? finder.parseExportedAPIs(unresolved.stream()) + : finder.parse(unresolved.stream()); + archives.addAll(unresolved); + + // Add dependencies to the next batch for analysis + unresolved = unresolvedArchives(targets.stream()); + } while (!unresolved.isEmpty() && depth-- > 0); + } + + /* + * Recursively analyze the class dependences + */ + private void transitiveDeps(int depth) throws IOException { + Stream deps = archives.stream() + .flatMap(Archive::getDependencies); + + Deque unresolved = deps.collect(Collectors.toCollection(LinkedList::new)); + ConcurrentLinkedDeque deque = new ConcurrentLinkedDeque<>(); + do { + Location target; + while ((target = unresolved.poll()) != null) { + if (finder.isParsed(target)) + continue; + + Archive archive = configuration.findClass(target).orElse(null); + if (archive != null && filter.include(archive)) { + archives.add(archive); + + String name = target.getName(); + Set targets = apiOnly + ? finder.parseExportedAPIs(archive, name) + : finder.parse(archive, name); + + // build unresolved dependencies + targets.stream() + .filter(t -> !finder.isParsed(t)) + .forEach(deque::add); + } + } + unresolved = deque; + deque = new ConcurrentLinkedDeque<>(); + } while (!unresolved.isEmpty() && depth-- > 0); + } + + // ----- for testing purpose ----- + + public static enum Info { + REQUIRES, + REQUIRES_PUBLIC, + EXPORTED_API, + MODULE_PRIVATE, + QUALIFIED_EXPORTED_API, + INTERNAL_API, + JDK_INTERNAL_API, + JDK_REMOVED_INTERNAL_API + } + + public static class Node { + public final String name; + public final String source; + public final Info info; + Node(String name, Info info) { + this(name, name, info); + } + Node(String name, String source, Info info) { + this.name = name; + this.source = source; + this.info = info; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (info != Info.REQUIRES && info != Info.REQUIRES_PUBLIC) + sb.append(source).append("/"); + + sb.append(name); + if (info == Info.QUALIFIED_EXPORTED_API) + sb.append(" (qualified)"); + else if (info == Info.JDK_INTERNAL_API) + sb.append(" (JDK internal)"); + else if (info == Info.INTERNAL_API) + sb.append(" (internal)"); + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Node)) + return false; + + Node other = (Node)o; + return this.name.equals(other.name) && + this.source.equals(other.source) && + this.info.equals(other.info); + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + source.hashCode(); + result = 31 * result + info.hashCode(); + return result; + } + } + + /** + * Returns a graph of module dependences. + * + * Each Node represents a module and each edge is a dependence. + * No analysis on "requires public". + */ + public Graph moduleGraph() { + Graph.Builder builder = new Graph.Builder<>(); + + archives().stream() + .forEach(m -> { + Node u = new Node(m.getName(), Info.REQUIRES); + builder.addNode(u); + analyzer.requires(m) + .map(req -> new Node(req.getName(), Info.REQUIRES)) + .forEach(v -> builder.addEdge(u, v)); + }); + return builder.build(); + } + + /** + * Returns a graph of dependences. + * + * Each Node represents a class or package per the specified verbose level. + * Each edge indicates + */ + public Graph dependenceGraph() { + Graph.Builder builder = new Graph.Builder<>(); + + archives().stream() + .map(analyzer.results::get) + .filter(deps -> !deps.dependencies().isEmpty()) + .flatMap(deps -> deps.dependencies().stream()) + .forEach(d -> addEdge(builder, d)); + return builder.build(); + } + + private void addEdge(Graph.Builder builder, Analyzer.Dep dep) { + Archive source = dep.originArchive(); + Archive target = dep.targetArchive(); + String pn = dep.target(); + if ((verbose == CLASS || verbose == VERBOSE)) { + int i = dep.target().lastIndexOf('.'); + pn = i > 0 ? dep.target().substring(0, i) : ""; + } + final Info info; + if (source == target) { + info = Info.MODULE_PRIVATE; + } else if (!target.getModule().isNamed()) { + info = Info.EXPORTED_API; + } else if (target.getModule().isExported(pn)) { + info = Info.EXPORTED_API; + } else { + Module module = target.getModule(); + if (module == Analyzer.REMOVED_JDK_INTERNALS) { + info = Info.JDK_REMOVED_INTERNAL_API; + } else if (!source.getModule().isJDK() && module.isJDK()) + info = Info.JDK_INTERNAL_API; + // qualified exports or inaccessible + else if (module.isExported(pn, source.getModule().name())) + info = Info.QUALIFIED_EXPORTED_API; + else + info = Info.INTERNAL_API; + } + + Node u = new Node(dep.origin(), source.getName(), info); + Node v = new Node(dep.target(), target.getName(), info); + builder.addEdge(u, v); + } + +} diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Graph.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Graph.java new file mode 100644 index 00000000000..5e9450c5eb5 --- /dev/null +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Graph.java @@ -0,0 +1,401 @@ +/* + * 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 com.sun.tools.jdeps; + +import java.io.PrintWriter; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReference; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public final class Graph { + private final Set nodes; + private final Map> edges; + + public Graph(Set nodes, Map> edges) { + this.nodes = Collections.unmodifiableSet(nodes); + this.edges = Collections.unmodifiableMap(edges); + } + + public Set nodes() { + return nodes; + } + + public Map> edges() { + return edges; + } + + public Set adjacentNodes(T u) { + return edges.get(u); + } + + public boolean contains(T u) { + return nodes.contains(u); + } + + public Set> edgesFrom(T u) { + return edges.get(u).stream() + .map(v -> new Edge(u, v)) + .collect(Collectors.toSet()); + } + + /** + * Returns a new Graph after transitive reduction + */ + public Graph reduce() { + Builder builder = new Builder<>(); + nodes.stream() + .forEach(u -> { + builder.addNode(u); + edges.get(u).stream() + .filter(v -> !pathExists(u, v, false)) + .forEach(v -> builder.addEdge(u, v)); + }); + return builder.build(); + } + + /** + * Returns a new Graph after transitive reduction. All edges in + * the given g takes precedence over this graph. + * + * @throw IllegalArgumentException g must be a subgraph this graph + */ + public Graph reduce(Graph g) { + boolean subgraph = nodes.containsAll(g.nodes) && + g.edges.keySet().stream() + .allMatch(u -> adjacentNodes(u).containsAll(g.adjacentNodes(u))); + if (!subgraph) { + throw new IllegalArgumentException(g + " is not a subgraph of " + this); + } + + Builder builder = new Builder<>(); + nodes.stream() + .forEach(u -> { + builder.addNode(u); + // filter the edge if there exists a path from u to v in the given g + // or there exists another path from u to v in this graph + edges.get(u).stream() + .filter(v -> !g.pathExists(u, v) && !pathExists(u, v, false)) + .forEach(v -> builder.addEdge(u, v)); + }); + + // add the overlapped edges from this graph and the given g + g.edges().keySet().stream() + .forEach(u -> g.adjacentNodes(u).stream() + .filter(v -> isAdjacent(u, v)) + .forEach(v -> builder.addEdge(u, v))); + return builder.build(); + } + + /** + * Returns nodes sorted in topological order. + */ + public Stream orderedNodes() { + TopoSorter sorter = new TopoSorter<>(this); + return sorter.result.stream(); + } + + /** + * Traverse this graph and performs the given action in topological order + */ + public void ordered(Consumer action) { + TopoSorter sorter = new TopoSorter<>(this); + sorter.ordered(action); + } + + /** + * Traverses this graph and performs the given action in reverse topological order + */ + public void reverse(Consumer action) { + TopoSorter sorter = new TopoSorter<>(this); + sorter.reverse(action); + } + + /** + * Returns a transposed graph from this graph + */ + public Graph transpose() { + Builder builder = new Builder<>(); + builder.addNodes(nodes); + // reverse edges + edges.keySet().forEach(u -> { + edges.get(u).stream() + .forEach(v -> builder.addEdge(v, u)); + }); + return builder.build(); + } + + /** + * Returns all nodes reachable from the given set of roots. + */ + public Set dfs(Set roots) { + Deque deque = new LinkedList<>(roots); + Set visited = new HashSet<>(); + while (!deque.isEmpty()) { + T u = deque.pop(); + if (!visited.contains(u)) { + visited.add(u); + if (contains(u)) { + adjacentNodes(u).stream() + .filter(v -> !visited.contains(v)) + .forEach(deque::push); + } + } + } + return visited; + } + + private boolean isAdjacent(T u, T v) { + return edges.containsKey(u) && edges.get(u).contains(v); + } + + private boolean pathExists(T u, T v) { + return pathExists(u, v, true); + } + + /** + * Returns true if there exists a path from u to v in this graph. + * If includeAdjacent is false, it returns true if there exists + * another path from u to v of distance > 1 + */ + private boolean pathExists(T u, T v, boolean includeAdjacent) { + if (!nodes.contains(u) || !nodes.contains(v)) { + return false; + } + if (includeAdjacent && isAdjacent(u, v)) { + return true; + } + Deque stack = new LinkedList<>(); + Set visited = new HashSet<>(); + stack.push(u); + while (!stack.isEmpty()) { + T node = stack.pop(); + if (node.equals(v)) { + return true; + } + if (!visited.contains(node)) { + visited.add(node); + edges.get(node).stream() + .filter(e -> includeAdjacent || !node.equals(u) || !e.equals(v)) + .forEach(e -> stack.push(e)); + } + } + assert !visited.contains(v); + return false; + } + + public void printGraph(PrintWriter out) { + out.println("graph for " + nodes); + nodes.stream() + .forEach(u -> adjacentNodes(u).stream() + .forEach(v -> out.format(" %s -> %s%n", u, v))); + } + + @Override + public String toString() { + return nodes.toString(); + } + + static class Edge { + final T u; + final T v; + Edge(T u, T v) { + this.u = u; + this.v = v; + } + + @Override + public String toString() { + return String.format("%s -> %s", u, v); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || !(o instanceof Edge)) + return false; + + @SuppressWarnings("unchecked") + Edge edge = (Edge) o; + + return u.equals(edge.u) && v.equals(edge.v); + } + + @Override + public int hashCode() { + int result = u.hashCode(); + result = 31 * result + v.hashCode(); + return result; + } + } + + static class Builder { + final Set nodes = new HashSet<>(); + final Map> edges = new HashMap<>(); + + public void addNode(T node) { + if (nodes.contains(node)) { + return; + } + nodes.add(node); + edges.computeIfAbsent(node, _e -> new HashSet<>()); + } + + public void addNodes(Set nodes) { + nodes.addAll(nodes); + } + + public void addEdge(T u, T v) { + addNode(u); + addNode(v); + edges.get(u).add(v); + } + + public Graph build() { + return new Graph(nodes, edges); + } + } + + /** + * Topological sort + */ + static class TopoSorter { + final Deque result = new LinkedList<>(); + final Deque nodes; + final Graph graph; + TopoSorter(Graph graph) { + this.graph = graph; + this.nodes = new LinkedList<>(graph.nodes); + sort(); + } + + public void ordered(Consumer action) { + result.iterator().forEachRemaining(action); + } + + public void reverse(Consumer action) { + result.descendingIterator().forEachRemaining(action); + } + + private void sort() { + Deque visited = new LinkedList<>(); + Deque done = new LinkedList<>(); + T node; + while ((node = nodes.poll()) != null) { + if (!visited.contains(node)) { + visit(node, visited, done); + } + } + } + + private void visit(T node, Deque visited, Deque done) { + if (visited.contains(node)) { + if (!done.contains(node)) { + throw new IllegalArgumentException("Cyclic detected: " + + node + " " + graph.edges().get(node)); + } + return; + } + visited.add(node); + graph.edges().get(node).stream() + .forEach(x -> visit(x, visited, done)); + done.add(node); + result.addLast(node); + } + } + + public static class DotGraph { + static final String ORANGE = "#e76f00"; + static final String BLUE = "#437291"; + static final String GRAY = "#dddddd"; + + static final String REEXPORTS = ""; + static final String REQUIRES = "style=\"dashed\""; + static final String REQUIRES_BASE = "color=\"" + GRAY + "\""; + + static final Set javaModules = modules(name -> + (name.startsWith("java.") && !name.equals("java.smartcardio"))); + static final Set jdkModules = modules(name -> + (name.startsWith("java.") || + name.startsWith("jdk.") || + name.startsWith("javafx.")) && !javaModules.contains(name)); + + private static Set modules(Predicate predicate) { + return ModuleFinder.ofSystem().findAll() + .stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .filter(predicate) + .collect(Collectors.toSet()); + } + + static void printAttributes(PrintWriter out) { + out.format(" size=\"25,25\";%n"); + out.format(" nodesep=.5;%n"); + out.format(" ranksep=1.5;%n"); + out.format(" pencolor=transparent;%n"); + out.format(" node [shape=plaintext, fontname=\"DejaVuSans\", fontsize=36, margin=\".2,.2\"];%n"); + out.format(" edge [penwidth=4, color=\"#999999\", arrowhead=open, arrowsize=2];%n"); + } + + static void printNodes(PrintWriter out, Graph graph) { + out.format(" subgraph se {%n"); + graph.nodes().stream() + .filter(javaModules::contains) + .forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n", + mn, ORANGE, "java")); + out.format(" }%n"); + graph.nodes().stream() + .filter(jdkModules::contains) + .forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n", + mn, BLUE, "jdk")); + + graph.nodes().stream() + .filter(mn -> !javaModules.contains(mn) && !jdkModules.contains(mn)) + .forEach(mn -> out.format(" \"%s\";%n", mn)); + } + + static void printEdges(PrintWriter out, Graph graph, + String node, Set requiresPublic) { + graph.adjacentNodes(node).forEach(dn -> { + String attr = dn.equals("java.base") ? REQUIRES_BASE + : (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES); + out.format(" \"%s\" -> \"%s\" [%s];%n", node, dn, attr); + }); + } + } + + +} diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/InverseDepsAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/InverseDepsAnalyzer.java new file mode 100644 index 00000000000..7e640d06aaa --- /dev/null +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/InverseDepsAnalyzer.java @@ -0,0 +1,250 @@ +/* + * 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 com.sun.tools.jdeps; + +import static com.sun.tools.jdeps.JdepsFilter.DEFAULT_FILTER; +import static com.sun.tools.jdeps.Module.trace; +import static com.sun.tools.jdeps.Graph.*; + +import java.lang.module.ModuleDescriptor.Requires; +import java.io.IOException; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Inverse transitive dependency analysis (compile-time view) + */ +public class InverseDepsAnalyzer extends DepsAnalyzer { + // the end points for the resulting paths to be reported + private final Map> endPoints = new HashMap<>(); + // target archives for inverse transitive dependence analysis + private final Set targets = new HashSet<>(); + + public InverseDepsAnalyzer(JdepsConfiguration config, + JdepsFilter filter, + JdepsWriter writer, + Analyzer.Type verbose, + boolean apiOnly) { + super(config, filter, writer, verbose, apiOnly); + } + + public boolean run() throws IOException { + try { + if (apiOnly) { + finder.parseExportedAPIs(rootArchives.stream()); + } else { + finder.parse(rootArchives.stream()); + } + archives.addAll(rootArchives); + + Set archives = archives(); + + // If -package or -regex is specified, the archives that reference + // the matching types are used as the targets for inverse + // transitive analysis. If -requires is specified, the + // specified modules are the targets. + + if (filter.requiresFilter().isEmpty()) { + targets.addAll(archives); + } else { + filter.requiresFilter().stream() + .map(configuration::findModule) + .flatMap(Optional::stream) + .forEach(targets::add); + } + + // If -package or -regex is specified, the end points are + // the matching archives. If -requires is specified, + // the end points are the modules specified in -requires. + if (filter.requiresFilter().isEmpty()) { + Map> dependences = finder.dependences(); + targets.forEach(source -> endPoints.put(source, dependences.get(source))); + } else { + targets.forEach(t -> endPoints.put(t, Collections.emptySet())); + } + + analyzer.run(archives, finder.locationToArchive()); + + // print the first-level of dependencies + if (writer != null) { + writer.generateOutput(archives, analyzer); + } + + } finally { + finder.shutdown(); + } + return true; + } + + /** + * Returns the target archives determined from the dependency analysis. + * + * Inverse transitive dependency will find all nodes that depend + * upon the returned set of archives directly and indirectly. + */ + public Set targets() { + return Collections.unmodifiableSet(targets); + } + + /** + * Finds all inverse transitive dependencies using the given requires set + * as the targets, if non-empty. If the given requires set is empty, + * use the archives depending the packages specified in -regex or -p options. + */ + public Set> inverseDependences() throws IOException { + // create a new dependency finder to do the analysis + DependencyFinder dependencyFinder = new DependencyFinder(configuration, DEFAULT_FILTER); + try { + // parse all archives in unnamed module to get compile-time dependences + Stream archives = + Stream.concat(configuration.initialArchives().stream(), + configuration.classPathArchives().stream()); + if (apiOnly) { + dependencyFinder.parseExportedAPIs(archives); + } else { + dependencyFinder.parse(archives); + } + + Graph.Builder builder = new Graph.Builder<>(); + // include all target nodes + targets().forEach(builder::addNode); + + // transpose the module graph - may filter JDK module + configuration.getModules().values().stream() + .filter(filter::include) + .forEach(m -> { + builder.addNode(m); + m.descriptor().requires().stream() + .map(Requires::name) + .map(configuration::findModule) // must be present + .forEach(v -> builder.addEdge(v.get(), m)); + }); + + // add the dependences from the analysis + Map> dependences = dependencyFinder.dependences(); + dependences.entrySet().stream() + .forEach(e -> { + Archive u = e.getKey(); + builder.addNode(u); + e.getValue().forEach(v -> builder.addEdge(v, u)); + }); + + // transposed dependence graph. + Graph graph = builder.build(); + trace("targets: %s%n", targets()); + + // Traverse from the targets and find all paths + // rebuild a graph with all nodes that depends on targets + // targets directly and indirectly + return targets().stream() + .map(t -> findPaths(graph, t)) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + } finally { + dependencyFinder.shutdown(); + } + } + + /** + * Returns all paths reachable from the given targets. + */ + private Set> findPaths(Graph graph, Archive target) { + + // path is in reversed order + Deque path = new LinkedList<>(); + path.push(target); + + Set> visited = new HashSet<>(); + + Deque> deque = new LinkedList<>(); + deque.addAll(graph.edgesFrom(target)); + if (deque.isEmpty()) { + return makePaths(path).collect(Collectors.toSet()); + } + + Set> allPaths = new HashSet<>(); + while (!deque.isEmpty()) { + Edge edge = deque.pop(); + + if (visited.contains(edge)) + continue; + + Archive node = edge.v; + path.addLast(node); + visited.add(edge); + + Set> unvisitedDeps = graph.edgesFrom(node) + .stream() + .filter(e -> !visited.contains(e)) + .collect(Collectors.toSet()); + + trace("visiting %s %s (%s)%n", edge, path, unvisitedDeps); + if (unvisitedDeps.isEmpty()) { + makePaths(path).forEach(allPaths::add); + path.removeLast(); + } + + // push unvisited adjacent edges + unvisitedDeps.stream().forEach(deque::push); + + + // when the adjacent edges of a node are visited, pop it from the path + while (!path.isEmpty()) { + if (visited.containsAll(graph.edgesFrom(path.peekLast()))) + path.removeLast(); + else + break; + } + } + + return allPaths; + } + + /** + * Prepend end point to the path + */ + private Stream> makePaths(Deque path) { + Set nodes = endPoints.get(path.peekFirst()); + if (nodes == null || nodes.isEmpty()) { + return Stream.of(new LinkedList<>(path)); + } else { + return nodes.stream().map(n -> { + Deque newPath = new LinkedList<>(); + newPath.addFirst(n); + newPath.addAll(path); + return newPath; + }); + } + } +} diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java new file mode 100644 index 00000000000..a4186d27d8d --- /dev/null +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java @@ -0,0 +1,620 @@ +/* + * 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 + * 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 com.sun.tools.jdeps; + +import static com.sun.tools.jdeps.Module.trace; +import static java.util.stream.Collectors.*; + +import com.sun.tools.classfile.Dependency; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.lang.module.Configuration; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.lang.module.ResolvedModule; +import java.net.URI; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; + +public class JdepsConfiguration implements AutoCloseable { + // the token for "all modules on the module path" + public static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; + public static final String ALL_DEFAULT = "ALL-DEFAULT"; + public static final String MODULE_INFO = "module-info.class"; + + private final SystemModuleFinder system; + private final ModuleFinder finder; + + private final Map nameToModule = new LinkedHashMap<>(); + private final Map packageToModule = new HashMap<>(); + private final Map> packageToUnnamedModule = new HashMap<>(); + + private final List classpathArchives = new ArrayList<>(); + private final List initialArchives = new ArrayList<>(); + private final Set rootModules = new HashSet<>(); + private final Configuration configuration; + + private JdepsConfiguration(SystemModuleFinder systemModulePath, + ModuleFinder finder, + Set roots, + List classpaths, + List initialArchives, + boolean allDefaultModules) + throws IOException + { + trace("root: %s%n", roots); + + this.system = systemModulePath; + this.finder = finder; + + // build root set for resolution + Set mods = new HashSet<>(roots); + + // add default modules to the root set + // unnamed module + if (!initialArchives.isEmpty() || !classpaths.isEmpty() || + roots.isEmpty() || allDefaultModules) { + mods.addAll(systemModulePath.defaultSystemRoots()); + } + + this.configuration = Configuration.empty() + .resolveRequires(finder, ModuleFinder.of(), mods); + + this.configuration.modules().stream() + .map(ResolvedModule::reference) + .forEach(this::addModuleReference); + + // packages in unnamed module + initialArchives.forEach(archive -> { + addPackagesInUnnamedModule(archive); + this.initialArchives.add(archive); + }); + + // classpath archives + for (Path p : classpaths) { + if (Files.exists(p)) { + Archive archive = Archive.getInstance(p); + addPackagesInUnnamedModule(archive); + classpathArchives.add(archive); + } + } + + // all roots specified in -addmods or -m are included + // as the initial set for analysis. + roots.stream() + .map(nameToModule::get) + .forEach(this.rootModules::add); + + initProfiles(); + + trace("resolved modules: %s%n", nameToModule.keySet().stream() + .sorted().collect(joining("\n", "\n", ""))); + } + + private void initProfiles() { + // other system modules are not observed and not added in nameToModule map + Map systemModules = + system.moduleNames() + .collect(toMap(Function.identity(), (mn) -> { + Module m = nameToModule.get(mn); + if (m == null) { + ModuleReference mref = finder.find(mn).get(); + m = toModule(mref); + } + return m; + })); + Profile.init(systemModules); + } + + private void addModuleReference(ModuleReference mref) { + Module module = toModule(mref); + nameToModule.put(mref.descriptor().name(), module); + mref.descriptor().packages() + .forEach(pn -> packageToModule.putIfAbsent(pn, module)); + } + + private void addPackagesInUnnamedModule(Archive archive) { + archive.reader().entries().stream() + .filter(e -> e.endsWith(".class") && !e.equals(MODULE_INFO)) + .map(this::toPackageName) + .distinct() + .forEach(pn -> packageToUnnamedModule + .computeIfAbsent(pn, _n -> new ArrayList<>()).add(archive)); + } + + private String toPackageName(String name) { + int i = name.lastIndexOf('/'); + return i > 0 ? name.replace('/', '.').substring(0, i) : ""; + } + + public Optional findModule(String name) { + Objects.requireNonNull(name); + Module m = nameToModule.get(name); + return m!= null ? Optional.of(m) : Optional.empty(); + + } + + public Optional findModuleDescriptor(String name) { + Objects.requireNonNull(name); + Module m = nameToModule.get(name); + return m!= null ? Optional.of(m.descriptor()) : Optional.empty(); + } + + boolean isSystem(Module m) { + return system.find(m.name()).isPresent(); + } + + boolean isValidToken(String name) { + return ALL_MODULE_PATH.equals(name) || ALL_DEFAULT.equals(name); + } + + /** + * Returns the modules that the given module can read + */ + public Stream reads(Module module) { + return configuration.findModule(module.name()).get() + .reads().stream() + .map(ResolvedModule::name) + .map(nameToModule::get); + } + + /** + * Returns the list of packages that split between resolved module and + * unnamed module + */ + public Map> splitPackages() { + Set splitPkgs = packageToModule.keySet().stream() + .filter(packageToUnnamedModule::containsKey) + .collect(toSet()); + if (splitPkgs.isEmpty()) + return Collections.emptyMap(); + + return splitPkgs.stream().collect(toMap(Function.identity(), (pn) -> { + Set sources = new LinkedHashSet<>(); + sources.add(packageToModule.get(pn).getModule().location().toString()); + packageToUnnamedModule.get(pn).stream() + .map(Archive::getPathName) + .forEach(sources::add); + return sources; + })); + } + + /** + * Returns an optional archive containing the given Location + */ + public Optional findClass(Dependency.Location location) { + String name = location.getName(); + int i = name.lastIndexOf('/'); + String pn = i > 0 ? name.substring(0, i).replace('/', '.') : ""; + Archive archive = packageToModule.get(pn); + if (archive != null) { + return archive.contains(name + ".class") + ? Optional.of(archive) + : Optional.empty(); + } + + if (packageToUnnamedModule.containsKey(pn)) { + return packageToUnnamedModule.get(pn).stream() + .filter(a -> a.contains(name + ".class")) + .findFirst(); + } + return Optional.empty(); + } + + /** + * Returns the list of Modules that can be found in the specified + * module paths. + */ + public Map getModules() { + return nameToModule; + } + + public Stream resolve(Set roots) { + if (roots.isEmpty()) { + return nameToModule.values().stream(); + } else { + return Configuration.empty() + .resolveRequires(finder, ModuleFinder.of(), roots) + .modules().stream() + .map(ResolvedModule::name) + .map(nameToModule::get); + } + } + + public List classPathArchives() { + return classpathArchives; + } + + public List initialArchives() { + return initialArchives; + } + + public Set rootModules() { + return rootModules; + } + + public Module toModule(ModuleReference mref) { + try { + String mn = mref.descriptor().name(); + URI location = mref.location().orElseThrow(FileNotFoundException::new); + ModuleDescriptor md = mref.descriptor(); + Module.Builder builder = new Module.Builder(md, system.find(mn).isPresent()); + + final ClassFileReader reader; + if (location.getScheme().equals("jrt")) { + reader = system.getClassReader(mn); + } else { + reader = ClassFileReader.newInstance(Paths.get(location)); + } + + builder.classes(reader); + builder.location(location); + + return builder.build(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /* + * Close all archives e.g. JarFile + */ + @Override + public void close() throws IOException { + for (Archive archive : initialArchives) + archive.close(); + for (Archive archive : classpathArchives) + archive.close(); + for (Module module : nameToModule.values()) + module.close(); + } + + static class SystemModuleFinder implements ModuleFinder { + private static final String JAVA_HOME = System.getProperty("java.home"); + private static final String JAVA_SE = "java.se"; + + private final FileSystem fileSystem; + private final Path root; + private final Map systemModules; + + SystemModuleFinder() { + if (Files.isRegularFile(Paths.get(JAVA_HOME, "lib", "modules"))) { + // jrt file system + this.fileSystem = FileSystems.getFileSystem(URI.create("jrt:/")); + this.root = fileSystem.getPath("/modules"); + this.systemModules = walk(root); + } else { + // exploded image + this.fileSystem = FileSystems.getDefault(); + root = Paths.get(JAVA_HOME, "modules"); + this.systemModules = ModuleFinder.ofSystem().findAll().stream() + .collect(toMap(mref -> mref.descriptor().name(), Function.identity())); + } + } + + SystemModuleFinder(String javaHome) throws IOException { + if (javaHome == null) { + // -system none + this.fileSystem = null; + this.root = null; + this.systemModules = Collections.emptyMap(); + } else { + if (Files.isRegularFile(Paths.get(javaHome, "lib", "modules"))) + throw new IllegalArgumentException("Invalid java.home: " + javaHome); + + // alternate java.home + Map env = new HashMap<>(); + env.put("java.home", javaHome); + // a remote run-time image + this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), env); + this.root = fileSystem.getPath("/modules"); + this.systemModules = walk(root); + } + } + + private Map walk(Path root) { + try (Stream stream = Files.walk(root, 1)) { + return stream.filter(path -> !path.equals(root)) + .map(this::toModuleReference) + .collect(toMap(mref -> mref.descriptor().name(), + Function.identity())); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private ModuleReference toModuleReference(Path path) { + Path minfo = path.resolve(MODULE_INFO); + try (InputStream in = Files.newInputStream(minfo); + BufferedInputStream bin = new BufferedInputStream(in)) { + + ModuleDescriptor descriptor = dropHashes(ModuleDescriptor.read(bin)); + String mn = descriptor.name(); + URI uri = URI.create("jrt:/" + path.getFileName().toString()); + Supplier readerSupplier = new Supplier<>() { + @Override + public ModuleReader get() { + return new ModuleReader() { + @Override + public Optional find(String name) throws IOException { + return name.equals(mn) + ? Optional.of(uri) : Optional.empty(); + } + + @Override + public void close() throws IOException { + } + }; + } + }; + + return new ModuleReference(descriptor, uri, readerSupplier); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private ModuleDescriptor dropHashes(ModuleDescriptor md) { + ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(md.name()); + md.requires().forEach(builder::requires); + md.exports().forEach(builder::exports); + md.provides().values().stream().forEach(builder::provides); + md.uses().stream().forEach(builder::uses); + builder.conceals(md.conceals()); + return builder.build(); + } + + @Override + public Set findAll() { + return systemModules.values().stream().collect(toSet()); + } + + @Override + public Optional find(String mn) { + return systemModules.containsKey(mn) + ? Optional.of(systemModules.get(mn)) : Optional.empty(); + } + + public Stream moduleNames() { + return systemModules.values().stream() + .map(mref -> mref.descriptor().name()); + } + + public ClassFileReader getClassReader(String modulename) throws IOException { + Path mp = root.resolve(modulename); + if (Files.exists(mp) && Files.isDirectory(mp)) { + return ClassFileReader.newInstance(fileSystem, mp); + } else { + throw new FileNotFoundException(mp.toString()); + } + } + + public Set defaultSystemRoots() { + Set roots = new HashSet<>(); + boolean hasJava = false; + if (systemModules.containsKey(JAVA_SE)) { + // java.se is a system module + hasJava = true; + roots.add(JAVA_SE); + } + + for (ModuleReference mref : systemModules.values()) { + String mn = mref.descriptor().name(); + if (hasJava && mn.startsWith("java.")) + continue; + + // add as root if observable and exports at least one package + ModuleDescriptor descriptor = mref.descriptor(); + for (ModuleDescriptor.Exports e : descriptor.exports()) { + if (!e.isQualified()) { + roots.add(mn); + break; + } + } + } + return roots; + } + } + + public static class Builder { + + final SystemModuleFinder systemModulePath; + final Set rootModules = new HashSet<>(); + final List initialArchives = new ArrayList<>(); + final List paths = new ArrayList<>(); + final List classPaths = new ArrayList<>(); + + ModuleFinder upgradeModulePath; + ModuleFinder appModulePath; + boolean addAllApplicationModules; + boolean addAllDefaultModules; + + public Builder() { + this.systemModulePath = new SystemModuleFinder(); + } + + public Builder(String javaHome) throws IOException { + this.systemModulePath = SystemModuleFinder.JAVA_HOME.equals(javaHome) + ? new SystemModuleFinder() + : new SystemModuleFinder(javaHome); + } + + public Builder upgradeModulePath(String upgradeModulePath) { + this.upgradeModulePath = createModulePathFinder(upgradeModulePath); + return this; + } + + public Builder appModulePath(String modulePath) { + this.appModulePath = createModulePathFinder(modulePath); + return this; + } + + public Builder addmods(Set addmods) { + for (String mn : addmods) { + switch (mn) { + case ALL_MODULE_PATH: + this.addAllApplicationModules = true; + break; + case ALL_DEFAULT: + this.addAllDefaultModules = true; + break; + default: + this.rootModules.add(mn); + } + } + return this; + } + + /* + * This method is for -check option to find all target modules specified + * in qualified exports. + * + * Include all system modules and modules found on modulepath + */ + public Builder allModules() { + systemModulePath.moduleNames() + .forEach(this.rootModules::add); + this.addAllApplicationModules = true; + return this; + } + + public Builder addRoot(Path path) { + Archive archive = Archive.getInstance(path); + if (archive.contains(MODULE_INFO)) { + paths.add(path); + } else { + initialArchives.add(archive); + } + return this; + } + + public Builder addClassPath(String classPath) { + this.classPaths.addAll(getClassPaths(classPath)); + return this; + } + + public JdepsConfiguration build() throws IOException { + ModuleFinder finder = systemModulePath; + if (upgradeModulePath != null) { + finder = ModuleFinder.compose(upgradeModulePath, systemModulePath); + } + if (appModulePath != null) { + finder = ModuleFinder.compose(finder, appModulePath); + } + if (!paths.isEmpty()) { + ModuleFinder otherModulePath = ModuleFinder.of(paths.toArray(new Path[0])); + + finder = ModuleFinder.compose(finder, otherModulePath); + // add modules specified on command-line (convenience) as root set + otherModulePath.findAll().stream() + .map(mref -> mref.descriptor().name()) + .forEach(rootModules::add); + } + if (addAllApplicationModules && appModulePath != null) { + appModulePath.findAll().stream() + .map(mref -> mref.descriptor().name()) + .forEach(rootModules::add); + } + + return new JdepsConfiguration(systemModulePath, + finder, + rootModules, + classPaths, + initialArchives, + addAllDefaultModules); + } + + private static ModuleFinder createModulePathFinder(String mpaths) { + if (mpaths == null) { + return null; + } else { + String[] dirs = mpaths.split(File.pathSeparator); + Path[] paths = new Path[dirs.length]; + int i = 0; + for (String dir : dirs) { + paths[i++] = Paths.get(dir); + } + return ModuleFinder.of(paths); + } + } + + /* + * Returns the list of Archive specified in cpaths and not included + * initialArchives + */ + private List getClassPaths(String cpaths) { + if (cpaths.isEmpty()) { + return Collections.emptyList(); + } + List paths = new ArrayList<>(); + for (String p : cpaths.split(File.pathSeparator)) { + if (p.length() > 0) { + // wildcard to parse all JAR files e.g. -classpath dir/* + int i = p.lastIndexOf(".*"); + if (i > 0) { + Path dir = Paths.get(p.substring(0, i)); + try (DirectoryStream stream = Files.newDirectoryStream(dir, "*.jar")) { + for (Path entry : stream) { + paths.add(entry); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } else { + paths.add(Paths.get(p)); + } + } + } + return paths; + } + } + +} diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java index 84b04e2e713..585ec524724 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java @@ -41,22 +41,27 @@ import java.util.stream.Stream; * 2. -filter:package to filter out same-package dependencies * This filter is applied when jdeps parses the class files * and filtered dependencies are not stored in the Analyzer. - * 3. -module specifies to match target dependencies from the given module + * 3. -requires specifies to match target dependence from the given module * This gets expanded into package lists to be filtered. * 4. -filter:archive to filter out same-archive dependencies * This filter is applied later in the Analyzer as the * containing archive of a target class may not be known until * the entire archive */ -class JdepsFilter implements Dependency.Filter, Analyzer.Filter { +public class JdepsFilter implements Dependency.Filter, Analyzer.Filter { + + public static final JdepsFilter DEFAULT_FILTER = + new JdepsFilter.Builder().filter(true, true).build(); + private final Dependency.Filter filter; private final Pattern filterPattern; private final boolean filterSamePackage; private final boolean filterSameArchive; private final boolean findJDKInternals; private final Pattern includePattern; - private final Set includePackages; - private final Set excludeModules; + private final Pattern includeSystemModules; + + private final Set requires; private JdepsFilter(Dependency.Filter filter, Pattern filterPattern, @@ -64,16 +69,16 @@ class JdepsFilter implements Dependency.Filter, Analyzer.Filter { boolean filterSameArchive, boolean findJDKInternals, Pattern includePattern, - Set includePackages, - Set excludeModules) { + Pattern includeSystemModules, + Set requires) { this.filter = filter; this.filterPattern = filterPattern; this.filterSamePackage = filterSamePackage; this.filterSameArchive = filterSameArchive; this.findJDKInternals = findJDKInternals; this.includePattern = includePattern; - this.includePackages = includePackages; - this.excludeModules = excludeModules; + this.includeSystemModules = includeSystemModules; + this.requires = requires; } /** @@ -82,12 +87,7 @@ class JdepsFilter implements Dependency.Filter, Analyzer.Filter { * @param cn fully-qualified name */ public boolean matches(String cn) { - if (includePackages.isEmpty() && includePattern == null) - return true; - - int i = cn.lastIndexOf('.'); - String pn = i > 0 ? cn.substring(0, i) : ""; - if (includePackages.contains(pn)) + if (includePattern == null) return true; if (includePattern != null) @@ -97,29 +97,39 @@ class JdepsFilter implements Dependency.Filter, Analyzer.Filter { } /** - * Tests if the given source includes classes specified in includePattern - * or includePackages filters. + * Tests if the given source includes classes specified in -include option * * This method can be used to determine if the given source should eagerly * be processed. */ public boolean matches(Archive source) { - if (!includePackages.isEmpty() && source.getModule().isNamed()) { - boolean found = source.getModule().packages() - .stream() - .filter(pn -> includePackages.contains(pn)) - .findAny().isPresent(); - if (found) - return true; + if (includePattern != null) { + return source.reader().entries().stream() + .map(name -> name.replace('/', '.')) + .filter(name -> !name.equals("module-info.class")) + .anyMatch(this::matches); } - if (!includePackages.isEmpty() || includePattern != null) { - return source.reader().entries() - .stream() - .map(name -> name.replace('/', '.')) - .filter(this::matches) - .findAny().isPresent(); - } - return false; + return hasTargetFilter(); + } + + public boolean include(Archive source) { + Module module = source.getModule(); + // skip system module by default; or if includeSystemModules is set + // only include the ones matching the pattern + return !module.isSystem() || (includeSystemModules != null && + includeSystemModules.matcher(module.name()).matches()); + } + + public boolean hasIncludePattern() { + return includePattern != null || includeSystemModules != null; + } + + public boolean hasTargetFilter() { + return filter != null; + } + + public Set requiresFilter() { + return requires; } // ----- Dependency.Filter ----- @@ -164,42 +174,35 @@ class JdepsFilter implements Dependency.Filter, Analyzer.Filter { return true; } - /** - * Returns true if dependency should be recorded for the given source. - */ - public boolean accept(Archive source) { - return !excludeModules.contains(source.getName()); - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("exclude modules: ") - .append(excludeModules.stream().sorted().collect(Collectors.joining(","))) - .append("\n"); + sb.append("include pattern: ").append(includePattern).append("\n"); sb.append("filter same archive: ").append(filterSameArchive).append("\n"); sb.append("filter same package: ").append(filterSamePackage).append("\n"); + sb.append("requires: ").append(requires).append("\n"); return sb.toString(); } - static class Builder { - Dependency.Filter filter; + public static class Builder { + static Pattern SYSTEM_MODULE_PATTERN = Pattern.compile("java\\..*|jdk\\..*|javafx\\..*"); Pattern filterPattern; + Pattern regex; boolean filterSamePackage; boolean filterSameArchive; boolean findJDKInterals; // source filters Pattern includePattern; - Set includePackages = new HashSet<>(); - Set includeModules = new HashSet<>(); - Set excludeModules = new HashSet<>(); + Pattern includeSystemModules; + Set requires = new HashSet<>(); + Set targetPackages = new HashSet<>(); public Builder packages(Set packageNames) { - this.filter = Dependencies.getPackageFilter(packageNames, false); + this.targetPackages.addAll(packageNames); return this; } public Builder regex(Pattern regex) { - this.filter = Dependencies.getRegexFilter(regex); + this.regex = regex; return this; } public Builder filter(Pattern regex) { @@ -211,6 +214,13 @@ class JdepsFilter implements Dependency.Filter, Analyzer.Filter { this.filterSameArchive = sameArchive; return this; } + public Builder requires(String name, Set packageNames) { + this.requires.add(name); + this.targetPackages.addAll(packageNames); + + includeIfSystemModule(name); + return this; + } public Builder findJDKInternals(boolean value) { this.findJDKInterals = value; return this; @@ -219,30 +229,33 @@ class JdepsFilter implements Dependency.Filter, Analyzer.Filter { this.includePattern = regex; return this; } - public Builder includePackage(String pn) { - this.includePackages.add(pn); + public Builder includeSystemModules(Pattern regex) { + this.includeSystemModules = regex; return this; } - public Builder includeModules(Set includes) { - this.includeModules.addAll(includes); - return this; - } - public Builder excludeModules(Set excludes) { - this.excludeModules.addAll(excludes); + public Builder includeIfSystemModule(String name) { + if (includeSystemModules == null && + SYSTEM_MODULE_PATTERN.matcher(name).matches()) { + this.includeSystemModules = SYSTEM_MODULE_PATTERN; + } return this; } - JdepsFilter build() { + public JdepsFilter build() { + Dependency.Filter filter = null; + if (regex != null) + filter = Dependencies.getRegexFilter(regex); + else if (!targetPackages.isEmpty()) { + filter = Dependencies.getPackageFilter(targetPackages, false); + } return new JdepsFilter(filter, filterPattern, filterSamePackage, filterSameArchive, findJDKInterals, includePattern, - includePackages, - excludeModules.stream() - .filter(mn -> !includeModules.contains(mn)) - .collect(Collectors.toSet())); + includeSystemModules, + requires); } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java index 649e53e0a2c..edaafa2637b 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java @@ -25,31 +25,30 @@ package com.sun.tools.jdeps; +import static com.sun.tools.jdeps.Analyzer.NOT_FOUND; +import static com.sun.tools.jdeps.Analyzer.REMOVED_JDK_INTERNALS; import static com.sun.tools.jdeps.Analyzer.Type.*; import static com.sun.tools.jdeps.JdepsWriter.*; -import static com.sun.tools.jdeps.ModuleAnalyzer.Graph; +import static com.sun.tools.jdeps.JdepsConfiguration.ALL_MODULE_PATH; -import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.lang.module.ResolutionException; -import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; +import java.util.Comparator; +import java.util.Deque; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; -import java.util.Optional; import java.util.ResourceBundle; import java.util.Set; -import java.util.TreeMap; +import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -58,7 +57,12 @@ import java.util.stream.Stream; * Implementation for the jdeps tool for static class dependency analysis. */ class JdepsTask { - static class BadArgs extends Exception { + static interface BadArguments { + String getKey(); + Object[] getArgs(); + boolean showUsage(); + } + static class BadArgs extends Exception implements BadArguments { static final long serialVersionUID = 8765093759964640721L; BadArgs(String key, Object... args) { super(JdepsTask.getMessage(key, args)); @@ -73,6 +77,44 @@ class JdepsTask { final String key; final Object[] args; boolean showUsage; + + @Override + public String getKey() { + return key; + } + + @Override + public Object[] getArgs() { + return args; + } + + @Override + public boolean showUsage() { + return showUsage; + } + } + + static class UncheckedBadArgs extends RuntimeException implements BadArguments { + static final long serialVersionUID = -1L; + final BadArgs cause; + UncheckedBadArgs(BadArgs cause) { + super(cause); + this.cause = cause; + } + @Override + public String getKey() { + return cause.key; + } + + @Override + public Object[] getArgs() { + return cause.args; + } + + @Override + public boolean showUsage() { + return cause.showUsage; + } } static abstract class Option { @@ -126,7 +168,7 @@ class JdepsTask { if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) { throw new BadArgs("err.invalid.path", arg); } - task.options.dotOutputDir = arg; + task.options.dotOutputDir = Paths.get(arg);; } }, new Option(false, "-s", "-summary") { @@ -136,8 +178,9 @@ class JdepsTask { } }, new Option(false, "-v", "-verbose", - "-verbose:package", - "-verbose:class") { + "-verbose:module", + "-verbose:package", + "-verbose:class") { void process(JdepsTask task, String opt, String arg) throws BadArgs { switch (opt) { case "-v": @@ -146,6 +189,9 @@ class JdepsTask { task.options.filterSameArchive = false; task.options.filterSamePackage = false; break; + case "-verbose:module": + task.options.verbose = MODULE; + break; case "-verbose:package": task.options.verbose = PACKAGE; break; @@ -157,6 +203,80 @@ class JdepsTask { } } }, + new Option(false, "-apionly") { + void process(JdepsTask task, String opt, String arg) { + task.options.apiOnly = true; + } + }, + new Option(true, "-check") { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + Set mods = Set.of(arg.split(",")); + task.options.checkModuleDeps = mods; + task.options.addmods.addAll(mods); + } + }, + new Option(true, "-genmoduleinfo") { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + Path p = Paths.get(arg); + if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) { + throw new BadArgs("err.invalid.path", arg); + } + task.options.genModuleInfo = Paths.get(arg); + } + }, + new Option(false, "-jdkinternals") { + void process(JdepsTask task, String opt, String arg) { + task.options.findJDKInternals = true; + task.options.verbose = CLASS; + if (task.options.includePattern == null) { + task.options.includePattern = Pattern.compile(".*"); + } + } + }, + + // ---- paths option ---- + new Option(true, "-cp", "-classpath") { + void process(JdepsTask task, String opt, String arg) { + task.options.classpath = arg; + } + }, + new Option(true, "-mp", "-modulepath") { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + task.options.modulePath = arg; + } + }, + new Option(true, "-upgrademodulepath") { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + task.options.upgradeModulePath = arg; + } + }, + new Option(true, "-system") { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (arg.equals("none")) { + task.options.systemModulePath = null; + } else { + Path path = Paths.get(arg); + if (Files.isRegularFile(path.resolve("lib").resolve("modules"))) + task.options.systemModulePath = arg; + else + throw new BadArgs("err.invalid.path", arg); + } + } + }, + new Option(true, "-addmods") { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + Set mods = Set.of(arg.split(",")); + task.options.addmods.addAll(mods); + } + }, + new Option(true, "-m") { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + task.options.rootModule = arg; + task.options.addmods.add(arg); + } + }, + + // ---- Target filtering options ---- new Option(true, "-p", "-package") { void process(JdepsTask task, String opt, String arg) { task.options.packageNames.add(arg); @@ -167,7 +287,7 @@ class JdepsTask { task.options.regex = Pattern.compile(arg); } }, - new Option(true, "-module") { + new Option(true, "-requires") { void process(JdepsTask task, String opt, String arg) { task.options.requires.add(arg); } @@ -198,28 +318,27 @@ class JdepsTask { } } }, + + // ---- Source filtering options ---- new Option(true, "-include") { void process(JdepsTask task, String opt, String arg) throws BadArgs { task.options.includePattern = Pattern.compile(arg); } }, + + // Another alternative to list modules in -addmods option + new HiddenOption(true, "-include-system-modules") { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + task.options.includeSystemModulePattern = Pattern.compile(arg); + } + }, + new Option(false, "-P", "-profile") { void process(JdepsTask task, String opt, String arg) throws BadArgs { task.options.showProfile = true; - task.options.showModule = false; - } - }, - new Option(false, "-M") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - task.options.showModule = true; - task.options.showProfile = false; - } - }, - new Option(false, "-apionly") { - void process(JdepsTask task, String opt, String arg) { - task.options.apiOnly = true; } }, + new Option(false, "-R", "-recursive") { void process(JdepsTask task, String opt, String arg) { task.options.depth = 0; @@ -228,15 +347,17 @@ class JdepsTask { task.options.filterSamePackage = false; } }, - new Option(true, "-genmoduleinfo") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - Path p = Paths.get(arg); - if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) { - throw new BadArgs("err.invalid.path", arg); - } - task.options.genModuleInfo = arg; + + new Option(false, "-I", "-inverse") { + void process(JdepsTask task, String opt, String arg) { + task.options.inverse = true; + // equivalent to the inverse of compile-time view analysis + task.options.compileTimeView = true; + task.options.filterSamePackage = true; + task.options.filterSameArchive = true; } }, + new Option(false, "-ct", "-compile-time") { void process(JdepsTask task, String opt, String arg) { task.options.compileTimeView = true; @@ -245,62 +366,11 @@ class JdepsTask { task.options.depth = 0; } }, - new Option(false, "-jdkinternals") { - void process(JdepsTask task, String opt, String arg) { - task.options.findJDKInternals = true; - task.options.verbose = CLASS; - if (task.options.includePattern == null) { - task.options.includePattern = Pattern.compile(".*"); - } - } - }, - new Option(true, "-cp", "-classpath") { - void process(JdepsTask task, String opt, String arg) { - task.options.classpath = arg; - } - }, - new Option(true, "-mp", "-modulepath") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - task.options.modulePath = arg; - task.options.showModule = true; - } - }, - new Option(true, "-upgrademodulepath") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - task.options.upgradeModulePath = arg; - task.options.showModule = true; - } - }, - new Option(true, "-m") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - task.options.rootModule = arg; - task.options.includes.add(arg); - task.options.showModule = true; - } - }, - new Option(false, "-check") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - task.options.checkModuleDeps = true; - } - }, - new HiddenOption(true, "-include-modules") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - Arrays.stream(arg.split(",")) - .forEach(task.options.includes::add); - task.options.showModule = true; - } - }, - new HiddenOption(true, "-exclude-modules") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - Arrays.stream(arg.split(",")) - .forEach(task.options.excludes::add); - task.options.showModule = true; - } - }, + new Option(false, "-q", "-quiet") { void process(JdepsTask task, String opt, String arg) { - task.options.nowarning = true; - } + task.options.nowarning = true; + } }, new Option(false, "-version") { @@ -318,7 +388,11 @@ class JdepsTask { task.options.showLabel = true; } }, - + new HiddenOption(false, "-hide-module") { + void process(JdepsTask task, String opt, String arg) { + task.options.showModule = false; + } + }, new HiddenOption(true, "-depth") { void process(JdepsTask task, String opt, String arg) throws BadArgs { try { @@ -332,7 +406,7 @@ class JdepsTask { private static final String PROGNAME = "jdeps"; private final Options options = new Options(); - private final List classes = new ArrayList<>(); + private final List inputArgs = new ArrayList<>(); private PrintWriter log; void setLog(PrintWriter out) { @@ -342,13 +416,13 @@ class JdepsTask { /** * Result codes. */ - 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. - EXIT_ABNORMAL = 4;// terminated abnormally + 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. + EXIT_ABNORMAL = 4; // terminated abnormally - int run(String[] args) { + int run(String... args) { if (log == null) { log = new PrintWriter(System.out); } @@ -360,15 +434,11 @@ class JdepsTask { if (options.version || options.fullVersion) { showVersion(options.fullVersion); } - if (options.rootModule != null && !classes.isEmpty()) { - reportError("err.invalid.module.option", options.rootModule, classes); - return EXIT_CMDERR; + if (!inputArgs.isEmpty() && options.rootModule != null) { + reportError("err.invalid.arg.for.option", "-m"); } - if (options.checkModuleDeps && options.rootModule == null) { - reportError("err.root.module.not.set"); - return EXIT_CMDERR; - } - if (classes.isEmpty() && options.rootModule == null && options.includePattern == null) { + if (inputArgs.isEmpty() && options.addmods.isEmpty() && options.includePattern == null + && options.includeSystemModulePattern == null && options.checkModuleDeps == null) { if (options.help || options.version || options.fullVersion) { return EXIT_OK; } else { @@ -377,19 +447,10 @@ class JdepsTask { } } if (options.genModuleInfo != null) { - if (options.dotOutputDir != null || !options.classpath.isEmpty() || options.hasFilter()) { + if (options.dotOutputDir != null || options.classpath != null || options.hasFilter()) { showHelp(); return EXIT_CMDERR; } - // default to compile time view analysis - options.compileTimeView = true; - for (String fn : classes) { - Path p = Paths.get(fn); - if (!Files.exists(p) || !fn.endsWith(".jar")) { - reportError("err.genmoduleinfo.not.jarfile", fn); - return EXIT_CMDERR; - } - } } if (options.numFilters() > 1) { @@ -397,6 +458,16 @@ class JdepsTask { return EXIT_CMDERR; } + if (options.inverse && options.depth != 1) { + reportError("err.invalid.inverse.option", "-R"); + return EXIT_CMDERR; + } + + if (options.inverse && options.numFilters() == 0) { + reportError("err.invalid.filters"); + return EXIT_CMDERR; + } + if ((options.findJDKInternals) && (options.hasFilter() || options.showSummary)) { showHelp(); return EXIT_CMDERR; @@ -405,12 +476,15 @@ class JdepsTask { showHelp(); return EXIT_CMDERR; } + if (options.checkModuleDeps != null && !inputArgs.isEmpty()) { + reportError("err.invalid.module.option", inputArgs, "-check"); + } boolean ok = run(); return ok ? EXIT_OK : EXIT_ERROR; - } catch (BadArgs e) { - reportError(e.key, e.args); - if (e.showUsage) { + } catch (BadArgs|UncheckedBadArgs e) { + reportError(e.getKey(), e.getArgs()); + if (e.showUsage()) { log.println(getMessage("main.usage.summary", PROGNAME)); } return EXIT_CMDERR; @@ -419,176 +493,216 @@ class JdepsTask { return EXIT_CMDERR; } catch (IOException e) { e.printStackTrace(); - return EXIT_ABNORMAL; + return EXIT_CMDERR; } finally { log.flush(); } } - private ModulePaths modulePaths; - private boolean run() throws BadArgs, IOException { - DependencyFinder dependencyFinder = - new DependencyFinder(options.compileTimeView); + boolean run() throws IOException { + try (JdepsConfiguration config = buildConfig()) { - buildArchive(dependencyFinder); + // detect split packages + config.splitPackages().entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .forEach(e -> System.out.format("split package: %s %s%n", e.getKey(), + e.getValue().toString())); - if (options.rootModule != null && - (options.checkModuleDeps || (options.dotOutputDir != null && - options.verbose == SUMMARY))) { - // -dotfile -s prints the configuration of the given root - // -checkModuleDeps prints the suggested module-info.java - return analyzeModules(dependencyFinder); - } + // check if any module specified in -requires is missing + Stream.concat(options.addmods.stream(), options.requires.stream()) + .filter(mn -> !config.isValidToken(mn)) + .forEach(mn -> config.findModule(mn).orElseThrow(() -> + new UncheckedBadArgs(new BadArgs("err.module.not.found", mn)))); - // otherwise analyze the dependencies - if (options.genModuleInfo != null) { - return genModuleInfo(dependencyFinder); - } else { - return analyzeDeps(dependencyFinder); + // -genmoduleinfo + if (options.genModuleInfo != null) { + return genModuleInfo(config); + } + + // -check + if (options.checkModuleDeps != null) { + return new ModuleAnalyzer(config, log, options.checkModuleDeps).run(); + } + + if (options.dotOutputDir != null && + (options.verbose == SUMMARY || options.verbose == MODULE) && + !options.addmods.isEmpty() && inputArgs.isEmpty()) { + return new ModuleAnalyzer(config, log).genDotFiles(options.dotOutputDir); + } + + if (options.inverse) { + return analyzeInverseDeps(config); + } else { + return analyzeDeps(config); + } } } - private void buildArchive(DependencyFinder dependencyFinder) - throws BadArgs, IOException - { - // If -genmoduleinfo is specified, the input arguments must be JAR files - // Treat them as automatic modules for analysis - List jarfiles = options.genModuleInfo != null - ? classes.stream().map(Paths::get) - .collect(Collectors.toList()) - : Collections.emptyList(); - // Set module paths - this.modulePaths = new ModulePaths(options.upgradeModulePath, options.modulePath, jarfiles); + private JdepsConfiguration buildConfig() throws IOException { + JdepsConfiguration.Builder builder = + new JdepsConfiguration.Builder(options.systemModulePath); - // add modules to dependency finder for analysis - Map modules = modulePaths.getModules(); - modules.values().stream() - .forEach(dependencyFinder::addModule); + builder.upgradeModulePath(options.upgradeModulePath) + .appModulePath(options.modulePath) + .addmods(options.addmods); - // If -m option is set, add the specified module and its transitive dependences - // to the root set - if (options.rootModule != null) { - modulePaths.dependences(options.rootModule) - .forEach(dependencyFinder::addRoot); + if (options.checkModuleDeps != null) { + // check all system modules in the image + builder.allModules(); } - // check if any module specified in -requires is missing - Optional req = options.requires.stream() - .filter(mn -> !modules.containsKey(mn)) - .findFirst(); - if (req.isPresent()) { - throw new BadArgs("err.module.not.found", req.get()); - } + if (options.classpath != null) + builder.addClassPath(options.classpath); - // classpath - for (Path p : getClassPaths(options.classpath)) { + // build the root set of archives to be analyzed + for (String s : inputArgs) { + Path p = Paths.get(s); if (Files.exists(p)) { - dependencyFinder.addClassPathArchive(p); + builder.addRoot(p); } } - // if -genmoduleinfo is not set, the input arguments are considered as - // unnamed module. Add them to the root set - if (options.genModuleInfo == null) { - // add root set - for (String s : classes) { - Path p = Paths.get(s); - if (Files.exists(p)) { - // add to the initial root set - dependencyFinder.addRoot(p); - } else { - if (isValidClassName(s)) { - dependencyFinder.addClassName(s); - } else { - warning("warn.invalid.arg", s); - } - } - } - } + return builder.build(); } - private boolean analyzeDeps(DependencyFinder dependencyFinder) throws IOException { - JdepsFilter filter = dependencyFilter(); - - // parse classfiles and find all dependencies - findDependencies(dependencyFinder, filter, options.apiOnly); - - // analyze the dependencies collected - Analyzer analyzer = new Analyzer(options.verbose, filter); - analyzer.run(dependencyFinder.archives()); - + private boolean analyzeDeps(JdepsConfiguration config) throws IOException { // output result final JdepsWriter writer; if (options.dotOutputDir != null) { - Path dir = Paths.get(options.dotOutputDir); - Files.createDirectories(dir); - writer = new DotFileWriter(dir, options.verbose, + writer = new DotFileWriter(options.dotOutputDir, + options.verbose, options.showProfile, options.showModule, options.showLabel); } else { - writer = new SimpleWriter(log, options.verbose, + writer = new SimpleWriter(log, + options.verbose, options.showProfile, options.showModule); } - // Targets for reporting - include the root sets and other analyzed archives - final List targets; - if (options.rootModule == null) { - // no module as the root set - targets = dependencyFinder.archives() - .filter(filter::accept) - .filter(a -> !a.getModule().isNamed()) - .collect(Collectors.toList()); - } else { - // named modules in topological order - Stream modules = dependencyFinder.archives() - .filter(a -> a.getModule().isNamed()) - .map(Archive::getModule); - Graph graph = ModuleAnalyzer.graph(modulePaths, modules.toArray(Module[]::new)); - // then add unnamed module - targets = graph.orderedNodes() - .filter(filter::accept) - .collect(Collectors.toList()); + // analyze the dependencies + DepsAnalyzer analyzer = new DepsAnalyzer(config, + dependencyFilter(config), + writer, + options.verbose, + options.apiOnly); - // in case any reference not found - dependencyFinder.archives() - .filter(a -> !a.getModule().isNamed()) - .forEach(targets::add); - } + boolean ok = analyzer.run(options.compileTimeView, options.depth); + + // print skipped entries, if any + analyzer.archives() + .forEach(archive -> archive.reader() + .skippedEntries().stream() + .forEach(name -> warning("warn.skipped.entry", + name, archive.getPathName()))); - writer.generateOutput(targets, analyzer); if (options.findJDKInternals && !options.nowarning) { - showReplacements(targets, analyzer); + Map jdkInternals = analyzer.dependences() + .collect(Collectors.toMap(Function.identity(), this::replacementFor)); + + if (!jdkInternals.isEmpty()) { + log.println(); + warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url")); + + if (jdkInternals.values().stream().anyMatch(repl -> repl != null)) { + log.println(); + log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement"); + log.format("%-40s %s%n", "----------------", "---------------------"); + jdkInternals.entrySet().stream() + .filter(e -> e.getValue() != null) + .sorted(Map.Entry.comparingByKey()) + .forEach(e -> log.format("%-40s %s%n", e.getKey(), e.getValue())); + } + } + } - return true; + return ok; } - private JdepsFilter dependencyFilter() { - // Filter specified by -filter, -package, -regex, and -module options - JdepsFilter.Builder builder = new JdepsFilter.Builder(); + private boolean analyzeInverseDeps(JdepsConfiguration config) throws IOException { + JdepsWriter writer = new SimpleWriter(log, + options.verbose, + options.showProfile, + options.showModule); - // Exclude JDK modules from analysis and reporting if -m specified. - modulePaths.getModules().values().stream() - .filter(m -> m.isJDK()) - .map(Module::name) - .forEach(options.excludes::add); + InverseDepsAnalyzer analyzer = new InverseDepsAnalyzer(config, + dependencyFilter(config), + writer, + options.verbose, + options.apiOnly); + boolean ok = analyzer.run(); + + log.println(); + if (!options.requires.isEmpty()) + log.format("Inverse transitive dependences on %s%n", options.requires); + else + log.format("Inverse transitive dependences matching %s%n", + options.regex != null + ? options.regex.toString() + : "packages " + options.packageNames); + + analyzer.inverseDependences().stream() + .sorted(Comparator.comparing(this::sortPath)) + .forEach(path -> log.println(path.stream() + .map(Archive::getName) + .collect(Collectors.joining(" <- ")))); + return ok; + } + + private String sortPath(Deque path) { + return path.peekFirst().getName(); + } + + private boolean genModuleInfo(JdepsConfiguration config) throws IOException { + ModuleInfoBuilder builder + = new ModuleInfoBuilder(config, inputArgs, options.genModuleInfo); + boolean ok = builder.run(); + + builder.modules().forEach(module -> { + if (module.packages().contains("")) { + reportError("ERROR: %s contains unnamed package. " + + "module-info.java not generated%n", module.getPathName()); + } + }); + + if (!ok && !options.nowarning) { + log.println("ERROR: missing dependencies"); + builder.visitMissingDeps( + new Analyzer.Visitor() { + @Override + public void visitDependence(String origin, Archive originArchive, + String target, Archive targetArchive) { + if (builder.notFound(targetArchive)) + log.format(" %-50s -> %-50s %s%n", + origin, target, targetArchive.getName()); + } + }); + } + return ok; + } + + /** + * Returns a filter used during dependency analysis + */ + private JdepsFilter dependencyFilter(JdepsConfiguration config) { + // Filter specified by -filter, -package, -regex, and -requires options + JdepsFilter.Builder builder = new JdepsFilter.Builder(); // source filters builder.includePattern(options.includePattern); - builder.includeModules(options.includes); - builder.excludeModules(options.excludes); + builder.includeSystemModules(options.includeSystemModulePattern); builder.filter(options.filterSamePackage, options.filterSameArchive); builder.findJDKInternals(options.findJDKInternals); - // -module + // -requires if (!options.requires.isEmpty()) { - Map modules = modulePaths.getModules(); - builder.packages(options.requires.stream() - .map(modules::get) - .flatMap(m -> m.packages().stream()) - .collect(Collectors.toSet())); + options.requires.stream() + .forEach(mn -> { + Module m = config.findModule(mn).get(); + builder.requires(mn, m.packages()); + }); } // -regex if (options.regex != null) @@ -600,62 +714,14 @@ class JdepsTask { if (options.filterRegex != null) builder.filter(options.filterRegex); + // check if system module is set + config.rootModules().stream() + .map(Module::name) + .forEach(builder::includeIfSystemModule); + return builder.build(); } - private void findDependencies(DependencyFinder dependencyFinder, - JdepsFilter filter, - boolean apiOnly) - throws IOException - { - dependencyFinder.findDependencies(filter, apiOnly, options.depth); - - // print skipped entries, if any - for (Archive a : dependencyFinder.roots()) { - for (String name : a.reader().skippedEntries()) { - warning("warn.skipped.entry", name, a.getPathName()); - } - } - } - - private boolean genModuleInfo(DependencyFinder dependencyFinder) throws IOException { - ModuleInfoBuilder builder = new ModuleInfoBuilder(modulePaths, dependencyFinder); - boolean result = builder.run(options.verbose, options.nowarning); - builder.build(Paths.get(options.genModuleInfo)); - return result; - } - - private boolean analyzeModules(DependencyFinder dependencyFinder) - throws IOException - { - ModuleAnalyzer analyzer = new ModuleAnalyzer(modulePaths, - dependencyFinder, - options.rootModule); - if (options.checkModuleDeps) { - return analyzer.run(); - } - if (options.dotOutputDir != null && options.verbose == SUMMARY) { - Path dir = Paths.get(options.dotOutputDir); - Files.createDirectories(dir); - analyzer.genDotFile(dir); - return true; - } - return false; - } - - private boolean isValidClassName(String name) { - if (!Character.isJavaIdentifierStart(name.charAt(0))) { - return false; - } - for (int i=1; i < name.length(); i++) { - char c = name.charAt(i); - if (c != '.' && !Character.isJavaIdentifierPart(c)) { - return false; - } - } - return true; - } - public void handleOptions(String[] args) throws BadArgs { // process options for (int i=0; i < args.length; i++) { @@ -684,7 +750,7 @@ class JdepsTask { if (name.charAt(0) == '-') { throw new BadArgs("err.option.after.class", name).showUsage(true); } - classes.add(name); + inputArgs.add(name); } } } @@ -703,7 +769,7 @@ class JdepsTask { log.println(getMessage("error.prefix") + " " + getMessage(key, args)); } - private void warning(String key, Object... args) { + void warning(String key, Object... args) { log.println(getMessage("warn.prefix") + " " + getMessage(key, args)); } @@ -749,7 +815,7 @@ class JdepsTask { boolean version; boolean fullVersion; boolean showProfile; - boolean showModule; + boolean showModule = true; boolean showSummary; boolean apiOnly; boolean showLabel; @@ -761,22 +827,23 @@ class JdepsTask { boolean filterSamePackage = true; boolean filterSameArchive = false; Pattern filterRegex; - String dotOutputDir; - String genModuleInfo; - String classpath = ""; + Path dotOutputDir; + Path genModuleInfo; + String classpath; int depth = 1; Set requires = new HashSet<>(); Set packageNames = new HashSet<>(); Pattern regex; // apply to the dependences - Pattern includePattern; // apply to classes + Pattern includePattern; + Pattern includeSystemModulePattern; + boolean inverse = false; boolean compileTimeView = false; - boolean checkModuleDeps = false; + Set checkModuleDeps; + String systemModulePath = System.getProperty("java.home"); String upgradeModulePath; String modulePath; String rootModule; - // modules to be included or excluded - Set includes = new HashSet<>(); - Set excludes = new HashSet<>(); + Set addmods = new HashSet<>(); boolean hasFilter() { return numFilters() > 0; @@ -789,11 +856,8 @@ class JdepsTask { if (packageNames.size() > 0) count++; return count; } - - boolean isRootModule() { - return rootModule != null; - } } + private static class ResourceBundleHelper { static final ResourceBundle versionRB; static final ResourceBundle bundle; @@ -819,35 +883,6 @@ class JdepsTask { } } - /* - * Returns the list of Archive specified in cpaths and not included - * initialArchives - */ - private List getClassPaths(String cpaths) throws IOException - { - if (cpaths.isEmpty()) { - return Collections.emptyList(); - } - List paths = new ArrayList<>(); - for (String p : cpaths.split(File.pathSeparator)) { - if (p.length() > 0) { - // wildcard to parse all JAR files e.g. -classpath dir/* - int i = p.lastIndexOf(".*"); - if (i > 0) { - Path dir = Paths.get(p.substring(0, i)); - try (DirectoryStream stream = Files.newDirectoryStream(dir, "*.jar")) { - for (Path entry : stream) { - paths.add(entry); - } - } - } else { - paths.add(Paths.get(p)); - } - } - } - return paths; - } - /** * Returns the recommended replacement API for the given classname; * or return null if replacement API is not known. @@ -865,32 +900,5 @@ class JdepsTask { } } return value; - }; - - private void showReplacements(List archives, Analyzer analyzer) { - Map jdkinternals = new TreeMap<>(); - boolean useInternals = false; - for (Archive source : archives) { - useInternals = useInternals || analyzer.hasDependences(source); - for (String cn : analyzer.dependences(source)) { - String repl = replacementFor(cn); - if (repl != null) { - jdkinternals.putIfAbsent(cn, repl); - } - } - } - if (useInternals) { - log.println(); - warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url")); - } - if (!jdkinternals.isEmpty()) { - log.println(); - log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement"); - log.format("%-40s %s%n", "----------------", "---------------------"); - for (Map.Entry e : jdkinternals.entrySet()) { - log.format("%-40s %s%n", e.getKey(), e.getValue()); - } - } } - } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java index 06449fa5480..fdfb3705e0e 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java @@ -24,23 +24,33 @@ */ package com.sun.tools.jdeps; +import static com.sun.tools.jdeps.Analyzer.Type.*; + import java.io.IOException; import java.io.PrintWriter; import java.io.UncheckedIOException; +import java.lang.module.ModuleDescriptor.Requires; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.Map; -import static com.sun.tools.jdeps.Analyzer.Type.*; - public abstract class JdepsWriter { + public static JdepsWriter newDotWriter(Path outputdir, Analyzer.Type type) { + return new DotFileWriter(outputdir, type, false, true, false); + } + + public static JdepsWriter newSimpleWriter(PrintWriter writer, Analyzer.Type type) { + return new SimpleWriter(writer, type, false, true); + } + final Analyzer.Type type; final boolean showProfile; final boolean showModule; - JdepsWriter(Analyzer.Type type, boolean showProfile, boolean showModule) { + private JdepsWriter(Analyzer.Type type, boolean showProfile, boolean showModule) { this.type = type; this.showProfile = showProfile; this.showModule = showModule; @@ -48,7 +58,7 @@ public abstract class JdepsWriter { abstract void generateOutput(Collection archives, Analyzer analyzer) throws IOException; - public static class DotFileWriter extends JdepsWriter { + static class DotFileWriter extends JdepsWriter { final boolean showLabel; final Path outputDir; DotFileWriter(Path dir, Analyzer.Type type, @@ -62,8 +72,10 @@ public abstract class JdepsWriter { void generateOutput(Collection archives, Analyzer analyzer) throws IOException { + Files.createDirectories(outputDir); + // output individual .dot file for each archive - if (type != SUMMARY) { + if (type != SUMMARY && type != MODULE) { archives.stream() .filter(analyzer::hasDependences) .forEach(archive -> { @@ -85,13 +97,13 @@ public abstract class JdepsWriter { { // If verbose mode (-v or -verbose option), // the summary.dot file shows package-level dependencies. - Analyzer.Type summaryType = - (type == PACKAGE || type == SUMMARY) ? SUMMARY : PACKAGE; + boolean isSummary = type == PACKAGE || type == SUMMARY || type == MODULE; + Analyzer.Type summaryType = isSummary ? SUMMARY : PACKAGE; Path summary = outputDir.resolve("summary.dot"); try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary)); SummaryDotFile dotfile = new SummaryDotFile(sw, summaryType)) { for (Archive archive : archives) { - if (type == PACKAGE || type == SUMMARY) { + if (isSummary) { if (showLabel) { // build labels listing package-level dependencies analyzer.visitDependences(archive, dotfile.labelBuilder(), PACKAGE); @@ -208,19 +220,22 @@ public abstract class JdepsWriter { void generateOutput(Collection archives, Analyzer analyzer) { RawOutputFormatter depFormatter = new RawOutputFormatter(writer); RawSummaryFormatter summaryFormatter = new RawSummaryFormatter(writer); - for (Archive archive : archives) { - // print summary - if (showModule && archive.getModule().isNamed()) { - summaryFormatter.showModuleRequires(archive.getModule()); - } else { + archives.stream() + .filter(analyzer::hasDependences) + .sorted(Comparator.comparing(Archive::getName)) + .forEach(archive -> { + if (showModule && archive.getModule().isNamed() && type != SUMMARY) { + // print module-info except -summary + summaryFormatter.printModuleDescriptor(archive.getModule()); + } + // print summary analyzer.visitDependences(archive, summaryFormatter, SUMMARY); - } - if (analyzer.hasDependences(archive) && type != SUMMARY) { - // print the class-level or package-level dependences - analyzer.visitDependences(archive, depFormatter); - } - } + if (analyzer.hasDependences(archive) && type != SUMMARY) { + // print the class-level or package-level dependences + analyzer.visitDependences(archive, depFormatter); + } + }); } class RawOutputFormatter implements Analyzer.Visitor { @@ -269,20 +284,16 @@ public abstract class JdepsWriter { writer.format("%n"); } - public void showModuleRequires(Module module) { + public void printModuleDescriptor(Module module) { if (!module.isNamed()) return; - writer.format("module %s", module.name()); - if (module.isAutomatic()) - writer.format(" (automatic)"); - writer.println(); - module.requires().keySet() + writer.format("%s%s%n", module.name(), module.isAutomatic() ? " automatic" : ""); + writer.format(" [%s]%n", module.location()); + module.descriptor().requires() .stream() - .sorted() - .forEach(req -> writer.format(" requires %s%s%n", - module.requires.get(req) ? "public " : "", - req)); + .sorted(Comparator.comparing(Requires::name)) + .forEach(req -> writer.format(" requires %s%n", req)); } } } @@ -307,7 +318,7 @@ public abstract class JdepsWriter { } // exported API - boolean jdkunsupported = Module.isJDKUnsupported(module, pn); + boolean jdkunsupported = Module.JDK_UNSUPPORTED.equals(module.name()); if (module.isExported(pn) && !jdkunsupported) { return showProfileOrModule(module); } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java index a3ede30992b..4f67a7357e9 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java @@ -25,67 +25,56 @@ package com.sun.tools.jdeps; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UncheckedIOException; import java.lang.module.ModuleDescriptor; import java.net.URI; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.Optional; import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.stream.Collectors; /** - * JDeps internal representation of module for dependency analysis. + * Jdeps internal representation of module for dependency analysis. */ class Module extends Archive { - static final boolean traceOn = Boolean.getBoolean("jdeps.debug"); + static final Module UNNAMED_MODULE = new UnnamedModule(); + static final String JDK_UNSUPPORTED = "jdk.unsupported"; + + static final boolean DEBUG = Boolean.getBoolean("jdeps.debug"); static void trace(String fmt, Object... args) { + trace(DEBUG, fmt, args); + } + + static void trace(boolean traceOn, String fmt, Object... args) { if (traceOn) { System.err.format(fmt, args); } } - /* - * Returns true if the given package name is JDK critical internal API - * in jdk.unsupported module - */ - static boolean isJDKUnsupported(Module m, String pn) { - return JDK_UNSUPPORTED.equals(m.name()) || unsupported.contains(pn); - }; + private final ModuleDescriptor descriptor; + private final Map> exports; + private final boolean isSystem; + private final URI location; - protected final ModuleDescriptor descriptor; - protected final Map requires; - protected final Map> exports; - protected final Set packages; - protected final boolean isJDK; - protected final URI location; + protected Module(String name) { + super(name); + this.descriptor = null; + this.location = null; + this.exports = Collections.emptyMap(); + this.isSystem = true; + } private Module(String name, URI location, ModuleDescriptor descriptor, - Map requires, Map> exports, - Set packages, - boolean isJDK, + boolean isSystem, ClassFileReader reader) { super(name, location, reader); this.descriptor = descriptor; this.location = location; - this.requires = Collections.unmodifiableMap(requires); this.exports = Collections.unmodifiableMap(exports); - this.packages = Collections.unmodifiableSet(packages); - this.isJDK = isJDK; + this.isSystem = isSystem; } /** @@ -111,31 +100,35 @@ class Module extends Archive { return descriptor; } - public boolean isJDK() { - return isJDK; + public URI location() { + return location; } - public Map requires() { - return requires; + public boolean isJDK() { + String mn = name(); + return isSystem && + (mn.startsWith("java.") || mn.startsWith("jdk.") || mn.startsWith("javafx.")); + } + + public boolean isSystem() { + return isSystem; } public Map> exports() { return exports; } - public Map> provides() { - return descriptor.provides().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().providers())); - } - public Set packages() { - return packages; + return descriptor.packages(); } /** * Tests if the package of the given name is exported. */ public boolean isExported(String pn) { + if (JDK_UNSUPPORTED.equals(this.name())) { + return false; + } return exports.containsKey(pn) ? exports.get(pn).isEmpty() : false; } @@ -159,11 +152,6 @@ class Module extends Archive { return isExported(pn) || exports.containsKey(pn) && exports.get(pn).contains(target); } - private final static String JDK_UNSUPPORTED = "jdk.unsupported"; - - // temporary until jdk.unsupported module - private final static List unsupported = Arrays.asList("sun.misc", "sun.reflect"); - @Override public String toString() { return name(); @@ -171,21 +159,19 @@ class Module extends Archive { public final static class Builder { final String name; - final Map requires = new HashMap<>(); - final Map> exports = new HashMap<>(); - final Set packages = new HashSet<>(); - final boolean isJDK; + final ModuleDescriptor descriptor; + final boolean isSystem; ClassFileReader reader; - ModuleDescriptor descriptor; URI location; - public Builder(String name) { - this(name, false); + public Builder(ModuleDescriptor md) { + this(md, false); } - public Builder(String name, boolean isJDK) { - this.name = name; - this.isJDK = isJDK; + public Builder(ModuleDescriptor md, boolean isSystem) { + this.name = md.name(); + this.descriptor = md; + this.isSystem = isSystem; } public Builder location(URI location) { @@ -193,48 +179,30 @@ class Module extends Archive { return this; } - public Builder descriptor(ModuleDescriptor md) { - this.descriptor = md; - return this; - } - - public Builder require(String d, boolean reexport) { - requires.put(d, reexport); - return this; - } - - public Builder packages(Set pkgs) { - packages.addAll(pkgs); - return this; - } - - public Builder export(String p, Set ms) { - Objects.requireNonNull(p); - Objects.requireNonNull(ms); - exports.put(p, new HashSet<>(ms)); - return this; - } public Builder classes(ClassFileReader reader) { this.reader = reader; return this; } public Module build() { - if (descriptor.isAutomatic() && isJDK) { + if (descriptor.isAutomatic() && isSystem) { throw new InternalError("JDK module: " + name + " can't be automatic module"); } - return new Module(name, location, descriptor, requires, exports, packages, isJDK, reader); + Map> exports = new HashMap<>(); + + descriptor.exports().stream() + .forEach(exp -> exports.computeIfAbsent(exp.source(), _k -> new HashSet<>()) + .addAll(exp.targets())); + + return new Module(name, location, descriptor, exports, isSystem, reader); } } - final static Module UNNAMED_MODULE = new UnnamedModule(); private static class UnnamedModule extends Module { private UnnamedModule() { super("unnamed", null, null, Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptySet(), false, null); } @@ -260,10 +228,7 @@ class Module extends Archive { } private static class StrictModule extends Module { - private static final String SERVICES_PREFIX = "META-INF/services/"; - private final Map> provides; - private final Module module; - private final JarFile jarfile; + private final ModuleDescriptor md; /** * Converts the given automatic module to a strict module. @@ -272,114 +237,26 @@ class Module extends Archive { * declare service providers, if specified in META-INF/services configuration file */ private StrictModule(Module m, Map requires) { - super(m.name(), m.location, m.descriptor, requires, m.exports, m.packages, m.isJDK, m.reader()); - this.module = m; - try { - this.jarfile = new JarFile(m.path().toFile(), false); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - this.provides = providers(jarfile); + super(m.name(), m.location, m.descriptor, m.exports, m.isSystem, m.reader()); + + ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(m.name()); + requires.keySet().forEach(mn -> { + if (requires.get(mn).equals(Boolean.TRUE)) { + builder.requires(ModuleDescriptor.Requires.Modifier.PUBLIC, mn); + } else { + builder.requires(mn); + } + }); + m.descriptor.exports().forEach(e -> builder.exports(e)); + m.descriptor.uses().forEach(s -> builder.uses(s)); + m.descriptor.provides().values().forEach(p -> builder.provides(p)); + builder.conceals(m.descriptor.conceals()); + this.md = builder.build(); } @Override - public Map> provides() { - return provides; - } - - private Map> providers(JarFile jf) { - Map> provides = new HashMap<>(); - // map names of service configuration files to service names - Set serviceNames = jf.stream() - .map(e -> e.getName()) - .filter(e -> e.startsWith(SERVICES_PREFIX)) - .distinct() - .map(this::toServiceName) - .filter(Optional::isPresent) - .map(Optional::get) - .collect(Collectors.toSet()); - - // parse each service configuration file - for (String sn : serviceNames) { - JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn); - Set providerClasses = new HashSet<>(); - try (InputStream in = jf.getInputStream(entry)) { - BufferedReader reader - = new BufferedReader(new InputStreamReader(in, "UTF-8")); - String cn; - while ((cn = nextLine(reader)) != null) { - if (isJavaIdentifier(cn)) { - providerClasses.add(cn); - } - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } - if (!providerClasses.isEmpty()) - provides.put(sn, providerClasses); - } - - return provides; - } - - /** - * Returns a container with the service type corresponding to the name of - * a services configuration file. - * - * For example, if called with "META-INF/services/p.S" then this method - * returns a container with the value "p.S". - */ - private Optional toServiceName(String cf) { - assert cf.startsWith(SERVICES_PREFIX); - int index = cf.lastIndexOf("/") + 1; - if (index < cf.length()) { - String prefix = cf.substring(0, index); - if (prefix.equals(SERVICES_PREFIX)) { - String sn = cf.substring(index); - if (isJavaIdentifier(sn)) - return Optional.of(sn); - } - } - return Optional.empty(); - } - - /** - * Reads the next line from the given reader and trims it of comments and - * leading/trailing white space. - * - * Returns null if the reader is at EOF. - */ - private String nextLine(BufferedReader reader) throws IOException { - String ln = reader.readLine(); - if (ln != null) { - int ci = ln.indexOf('#'); - if (ci >= 0) - ln = ln.substring(0, ci); - ln = ln.trim(); - } - return ln; - } - - /** - * Returns {@code true} if the given identifier is a legal Java identifier. - */ - private static boolean isJavaIdentifier(String id) { - int n = id.length(); - if (n == 0) - return false; - if (!Character.isJavaIdentifierStart(id.codePointAt(0))) - return false; - int cp = id.codePointAt(0); - int i = Character.charCount(cp); - for (; i < n; i += Character.charCount(cp)) { - cp = id.codePointAt(i); - if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.') - return false; - } - if (cp == '.') - return false; - - return true; + public ModuleDescriptor descriptor() { + return md; } } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java index f419e5631df..d17424007b2 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java @@ -24,277 +24,364 @@ */ package com.sun.tools.jdeps; -import java.io.IOException; -import java.io.PrintStream; -import java.io.UncheckedIOException; - +import static com.sun.tools.jdeps.Graph.*; +import static com.sun.tools.jdeps.JdepsFilter.DEFAULT_FILTER; +import static com.sun.tools.jdeps.Module.*; import static java.lang.module.ModuleDescriptor.Requires.Modifier.*; +import static java.util.stream.Collectors.*; -import java.lang.module.Configuration; +import com.sun.tools.classfile.Dependency; +import com.sun.tools.jdeps.JdepsTask.BadArgs; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; import java.lang.module.ModuleDescriptor; -import java.lang.module.ModuleFinder; -import java.lang.module.ModuleReference; -import java.lang.module.ResolvedModule; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; import java.util.Comparator; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; +import java.util.Optional; import java.util.Set; -import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.sun.tools.jdeps.Module.*; -import static com.sun.tools.jdeps.ModulePaths.SystemModulePath.JAVA_BASE; - /** * Analyze module dependences and compare with module descriptor. * Also identify any qualified exports not used by the target module. */ -class ModuleAnalyzer { - private final ModulePaths modulePaths; +public class ModuleAnalyzer { + private static final String JAVA_BASE = "java.base"; + + private final JdepsConfiguration configuration; + private final PrintWriter log; + private final DependencyFinder dependencyFinder; - private final Module root; - private final Set modules; - private final Set requiresPublic = new HashSet<>(); - private final Set requires = new HashSet<>(); - private final Set exportTargets = new HashSet<>(); - private final JdepsFilter filter; - private Graph graph; - ModuleAnalyzer(ModulePaths modulePaths, DependencyFinder finder, - String moduleName) { - this.modulePaths = modulePaths; - this.dependencyFinder = finder; - this.root = modulePaths.getModules().get(moduleName); - this.modules = modulePaths.dependences(moduleName); + private final Map modules; - root.exports().values().stream() - .flatMap(Set::stream) - .map(target -> modulePaths.getModules().get(target)) - .forEach(this.exportTargets::add); - - this.filter = new JdepsFilter.Builder().filter(true, true).build(); + public ModuleAnalyzer(JdepsConfiguration config, + PrintWriter log) { + this(config, log, Collections.emptySet()); } + public ModuleAnalyzer(JdepsConfiguration config, + PrintWriter log, + Set names) { - /** - * Returns a graph of transitive closure of the given modules. - * - * This method does not add the implicit read edges and is intended to - * get all transitive closures in (reverse) topological sort. - */ - public static Graph graph(ModulePaths modulePaths, Module... modules) { - Graph.Builder gb = new Graph.Builder<>(); - for (Module module : modules) { - module.descriptor().requires().stream() - .map(ModuleDescriptor.Requires::name) - .map(mn -> modulePaths.getModules().get(mn)) - .forEach(m -> { - gb.addNode(m); - gb.addEdge(module, m); - }); + if (!config.initialArchives().isEmpty()) { + String list = config.initialArchives().stream() + .map(Archive::getPathName).collect(joining(" ")); + throw new JdepsTask.UncheckedBadArgs(new BadArgs("err.invalid.module.option", + list, "-check")); + } + + this.configuration = config; + this.log = log; + + this.dependencyFinder = new DependencyFinder(config, DEFAULT_FILTER); + if (names.isEmpty()) { + this.modules = configuration.rootModules().stream() + .collect(toMap(Function.identity(), ModuleDeps::new)); + } else { + this.modules = names.stream() + .map(configuration::findModule) + .flatMap(Optional::stream) + .collect(toMap(Function.identity(), ModuleDeps::new)); } - return gb.build(); } - /** - * Do the analysis - */ - public boolean run() { + public boolean run() throws IOException { try { - computeRequiresPublic(); - computeRequires(); - // apply transitive reduction and reports recommended requires. - analyzeDeps(); - // detect any qualiifed exports not used by the target module - checkQualifiedExports(); - } catch (IOException e) { - throw new UncheckedIOException(e); + // compute "requires public" dependences + modules.values().forEach(ModuleDeps::computeRequiresPublic); + + modules.values().forEach(md -> { + // compute "requires" dependences + md.computeRequires(); + // apply transitive reduction and reports recommended requires. + md.analyzeDeps(); + }); + } finally { + dependencyFinder.shutdown(); } return true; } - /** - * Compute 'requires public' dependences by analyzing API dependencies - */ - private void computeRequiresPublic() throws IOException { - JdepsFilter.Builder builder = new JdepsFilter.Builder(); - // only analyze exported API - root.descriptor.exports().stream() - .filter(exp -> !exp.isQualified()) - .map(ModuleDescriptor.Exports::source) - .forEach(builder::includePackage); + class ModuleDeps { + final Module root; + Set requiresPublic; + Set requires; + Map> unusedQualifiedExports; - JdepsFilter filter = builder.filter(true, true).build(); - - // analyze dependences for exported packages - dependencyFinder.findDependencies(filter, true /* api only */, 1); - Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter); - analyzer.run(modules); - - // record requires public - analyzer.requires(root) - .filter(m -> m != JAVA_BASE && m != root) - .map(Archive::getName) - .forEach(requiresPublic::add); - trace("requires public: %s%n", requiresPublic); - } - - private void computeRequires() throws IOException { - // add the exportTargets of the qualified exports to the root set - exportTargets.stream() - .peek(target -> trace("add root: %s%n", target)) - .forEach(dependencyFinder::addRoot); - - // analyze all classes - dependencyFinder.findDependencies(filter, false /* all classes */, 1); - Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter); - analyzer.run(modules); - - // record requires - analyzer.requires(root) - .filter(m -> m != JAVA_BASE && m != root) - .map(Archive::getName) - .forEach(requires::add); - - this.graph = buildGraph(analyzer, root); - if (traceOn) { - trace("dependences: %s%n", graph.nodes()); - graph.printGraph(System.out); + ModuleDeps(Module root) { + this.root = root; } - } - /** - * Apply transitive reduction on the resulting graph and reports - * recommended requires. - */ - private void analyzeDeps() { - String moduleName = root.name(); + /** + * Compute 'requires public' dependences by analyzing API dependencies + */ + private void computeRequiresPublic() { + // record requires public + this.requiresPublic = computeRequires(true) + .filter(m -> !m.name().equals(JAVA_BASE)) + .collect(toSet()); - Graph.Builder builder = new Graph.Builder<>(); - requiresPublic.stream() - .forEach(mn -> { - builder.addNode(mn); - builder.addEdge(moduleName, mn); - }); - // requires public graph - Graph rbg = builder.build().reduce(); + trace("requires public: %s%n", requiresPublic); + } - // convert the dependence graph from Module to name - Set nodes = this.graph.nodes().stream() + private void computeRequires() { + this.requires = computeRequires(false).collect(toSet()); + trace("requires: %s%n", requires); + } + + private Stream computeRequires(boolean apionly) { + // analyze all classes + + if (apionly) { + dependencyFinder.parseExportedAPIs(Stream.of(root)); + } else { + dependencyFinder.parse(Stream.of(root)); + } + + // find the modules of all the dependencies found + return dependencyFinder.getDependences(root) + .map(Archive::getModule); + } + + ModuleDescriptor descriptor() { + return descriptor(requiresPublic, requires); + } + + private ModuleDescriptor descriptor(Set requiresPublic, + Set requires) { + + ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(root.name()); + + if (!root.name().equals(JAVA_BASE)) + builder.requires(MANDATED, JAVA_BASE); + + requiresPublic.stream() + .filter(m -> !m.name().equals(JAVA_BASE)) .map(Module::name) - .collect(Collectors.toSet()); - Map> edges = new HashMap<>(); - this.graph.edges().keySet().stream() + .forEach(mn -> builder.requires(PUBLIC, mn)); + + requires.stream() + .filter(m -> !requiresPublic.contains(m)) + .filter(m -> !m.name().equals(JAVA_BASE)) + .map(Module::name) + .forEach(mn -> builder.requires(mn)); + + return builder.build(); + } + + ModuleDescriptor reduced() { + Graph.Builder bd = new Graph.Builder<>(); + requiresPublic.stream() .forEach(m -> { - String mn = m.name(); - Set es = edges.computeIfAbsent(mn, _k -> new HashSet()); - this.graph.edges().get(m).stream() - .map(Module::name) - .forEach(es::add); + bd.addNode(m); + bd.addEdge(root, m); }); - // transitive reduction - Graph newGraph = new Graph<>(nodes, edges).reduce(rbg); - if (traceOn) { - System.out.println("after transitive reduction"); - newGraph.printGraph(System.out); - }; + // requires public graph + Graph rbg = bd.build().reduce(); - Set reducedRequires = newGraph.adjacentNodes(moduleName); - if (matches(root.descriptor(), requires, requiresPublic) && - matches(root.descriptor(), reducedRequires, requiresPublic)) { - System.out.println("--- Analysis result: no change for " + root.name()); - } else { - System.out.println("--- Analysis result: suggested requires for " + root.name()); - System.out.format("module %s%n", root.name()); - requires.stream() + // transitive reduction + Graph newGraph = buildGraph(requires).reduce(rbg); + if (DEBUG) { + System.err.println("after transitive reduction: "); + newGraph.printGraph(log); + } + + return descriptor(requiresPublic, newGraph.adjacentNodes(root)); + } + + + /** + * Apply transitive reduction on the resulting graph and reports + * recommended requires. + */ + private void analyzeDeps() { + Graph.Builder builder = new Graph.Builder<>(); + requiresPublic.stream() + .forEach(m -> { + builder.addNode(m); + builder.addEdge(root, m); + }); + + // requires public graph + Graph rbg = buildGraph(requiresPublic).reduce(); + + // transitive reduction + Graph newGraph = buildGraph(requires).reduce(builder.build().reduce()); + if (DEBUG) { + System.err.println("after transitive reduction: "); + newGraph.printGraph(log); + } + + printModuleDescriptor(log, root); + + ModuleDescriptor analyzedDescriptor = descriptor(); + if (!matches(root.descriptor(), analyzedDescriptor)) { + log.format(" [Suggested module descriptor for %s]%n", root.name()); + analyzedDescriptor.requires() + .stream() + .sorted(Comparator.comparing(ModuleDescriptor.Requires::name)) + .forEach(req -> log.format(" requires %s;%n", req)); + } + + ModuleDescriptor reduced = reduced(); + if (!matches(root.descriptor(), reduced)) { + log.format(" [Transitive reduced graph for %s]%n", root.name()); + reduced.requires() + .stream() + .sorted(Comparator.comparing(ModuleDescriptor.Requires::name)) + .forEach(req -> log.format(" requires %s;%n", req)); + } + + checkQualifiedExports(); + log.println(); + } + + private void checkQualifiedExports() { + // detect any qualified exports not used by the target module + unusedQualifiedExports = unusedQualifiedExports(); + if (!unusedQualifiedExports.isEmpty()) + log.format(" [Unused qualified exports in %s]%n", root.name()); + + unusedQualifiedExports.keySet().stream() + .sorted() + .forEach(pn -> log.format(" exports %s to %s%n", pn, + unusedQualifiedExports.get(pn).stream() .sorted() - .forEach(dn -> System.out.format(" requires %s%s;%n", - requiresPublic.contains(dn) ? "public " : "", dn)); - if (!requires.equals(reducedRequires) && !reducedRequires.isEmpty()) { - System.out.format("%nmodule %s (reduced)%n", root.name()); - newGraph.adjacentNodes(moduleName) - .stream() - .sorted() - .forEach(dn -> System.out.format(" requires %s%s;%n", - requiresPublic.contains(dn) ? "public " : "", dn)); - } - System.out.println("\n--- Module descriptor"); - Graph mdGraph = graph(modulePaths, root); - mdGraph.reverse(m -> printModuleDescriptor(System.out, m.descriptor())); + .collect(joining(",")))); } - } - /** - * Detects any qualified exports not used by the target module. - */ - private void checkQualifiedExports() throws IOException { - Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter); - analyzer.run(dependencyFinder.roots()); + private void printModuleDescriptor(PrintWriter out, Module module) { + ModuleDescriptor descriptor = module.descriptor(); + out.format("%s (%s)%n", descriptor.name(), module.location()); - // build the qualified exports map - Map> qualifiedExports = - root.exports().entrySet().stream() - .filter(e -> !e.getValue().isEmpty()) - .map(Map.Entry::getKey) - .collect(Collectors.toMap(Function.identity(), _k -> new HashSet<>())); + if (descriptor.name().equals(JAVA_BASE)) + return; - // adds to the qualified exports map if a module references it - for (Module m : exportTargets) { - analyzer.dependences(m).stream() - .map(this::toPackageName) + out.println(" [Module descriptor]"); + descriptor.requires() + .stream() + .sorted(Comparator.comparing(ModuleDescriptor.Requires::name)) + .forEach(req -> out.format(" requires %s;%n", req)); + } + + + /** + * Returns a graph of modules required by the specified module. + * + * Requires public edges of the dependences are added to the graph. + */ + private Graph buildGraph(Set deps) { + Graph.Builder builder = new Graph.Builder<>(); + builder.addNode(root); + Set visited = new HashSet<>(); + visited.add(root); + Deque deque = new LinkedList<>(); + deps.stream() + .forEach(m -> { + deque.add(m); + builder.addEdge(root, m); + }); + + // read requires public from ModuleDescription + Module source; + while ((source = deque.poll()) != null) { + if (visited.contains(source)) + continue; + + visited.add(source); + builder.addNode(source); + Module from = source; + source.descriptor().requires().stream() + .filter(req -> req.modifiers().contains(PUBLIC)) + .map(ModuleDescriptor.Requires::name) + .map(configuration::findModule) + .flatMap(Optional::stream) + .forEach(m -> { + deque.add(m); + builder.addEdge(from, m); + }); + } + return builder.build(); + } + + /** + * Detects any qualified exports not used by the target module. + */ + private Map> unusedQualifiedExports() { + Map> unused = new HashMap<>(); + + // build the qualified exports map + Map> qualifiedExports = + root.exports().entrySet().stream() + .filter(e -> !e.getValue().isEmpty()) + .map(Map.Entry::getKey) + .collect(toMap(Function.identity(), _k -> new HashSet<>())); + + Set mods = new HashSet<>(); + root.exports().values() + .stream() + .flatMap(Set::stream) + .forEach(target -> configuration.findModule(target) + .ifPresentOrElse(mods::add, + () -> log.format("Warning: %s not found%n", target)) + ); + + // parse all target modules + dependencyFinder.parse(mods.stream()); + + // adds to the qualified exports map if a module references it + mods.stream().forEach(m -> + m.getDependencies() + .map(Dependency.Location::getPackageName) .filter(qualifiedExports::containsKey) - .forEach(pn -> qualifiedExports.get(pn).add(m.name())); - } + .forEach(pn -> qualifiedExports.get(pn).add(m.name()))); - // compare with the exports from ModuleDescriptor - Set staleQualifiedExports = - qualifiedExports.keySet().stream() - .filter(pn -> !qualifiedExports.get(pn).equals(root.exports().get(pn))) - .collect(Collectors.toSet()); + // compare with the exports from ModuleDescriptor + Set staleQualifiedExports = + qualifiedExports.keySet().stream() + .filter(pn -> !qualifiedExports.get(pn).equals(root.exports().get(pn))) + .collect(toSet()); - if (!staleQualifiedExports.isEmpty()) { - System.out.println("--- Unused qualified exports in " + root.name()); - for (String pn : staleQualifiedExports) { - Set unused = new HashSet<>(root.exports().get(pn)); - unused.removeAll(qualifiedExports.get(pn)); - System.out.format(" exports %s to %s%n", pn, - unused.stream().collect(Collectors.joining(","))); + if (!staleQualifiedExports.isEmpty()) { + for (String pn : staleQualifiedExports) { + Set targets = new HashSet<>(root.exports().get(pn)); + targets.removeAll(qualifiedExports.get(pn)); + unused.put(pn, targets); + } } + return unused; } } - private String toPackageName(String cn) { - int i = cn.lastIndexOf('.'); - return i > 0 ? cn.substring(0, i) : ""; - } + private boolean matches(ModuleDescriptor md, ModuleDescriptor other) { + // build requires public from ModuleDescriptor + Set reqPublic = md.requires().stream() + .filter(req -> req.modifiers().contains(PUBLIC)) + .collect(toSet()); + Set otherReqPublic = other.requires().stream() + .filter(req -> req.modifiers().contains(PUBLIC)) + .collect(toSet()); - private boolean matches(ModuleDescriptor md, Set requires, Set requiresPublic) { - Set reqPublic = md.requires().stream() - .filter(req -> req.modifiers().contains(PUBLIC)) - .map(ModuleDescriptor.Requires::name) - .collect(Collectors.toSet()); - if (!requiresPublic.equals(reqPublic)) { + if (!reqPublic.equals(otherReqPublic)) { trace("mismatch requires public: %s%n", reqPublic); return false; } - // java.base is not in requires - int javaBase = md.name().equals(JAVA_BASE.name()) ? 0 : 1; - if (requires.size()+javaBase != md.requires().size()) { - trace("mismatch requires: %d != %d%n", requires.size()+1, md.requires().size()); - return false; - } - Set unused = md.requires().stream() - .map(ModuleDescriptor.Requires::name) - .filter(req -> !requires.contains(req) && !req.equals(JAVA_BASE.name())) - .collect(Collectors.toSet()); + Set unused = md.requires().stream() + .filter(req -> !other.requires().contains(req)) + .collect(Collectors.toSet()); + if (!unused.isEmpty()) { trace("mismatch requires: %s%n", unused); return false; @@ -302,371 +389,50 @@ class ModuleAnalyzer { return true; } - private void printModuleDescriptor(PrintStream out, ModuleDescriptor descriptor) { - if (descriptor.name().equals("java.base")) - return; - - out.format("module %s%n", descriptor.name()); - descriptor.requires() - .stream() - .sorted(Comparator.comparing(ModuleDescriptor.Requires::name)) - .forEach(req -> out.format(" requires %s;%n", req)); - } - /** - * Returns a graph of modules required by the specified module. + * Generate dotfile from module descriptor * - * Requires public edges of the dependences are added to the graph. + * @param dir output directory */ - private Graph buildGraph(Analyzer analyzer, Module module) { - Graph.Builder builder = new Graph.Builder<>(); - builder.addNode(module); - Set visited = new HashSet<>(); - visited.add(module); - Deque deque = new LinkedList<>(); - analyzer.requires(module) - .map(Archive::getModule) - .filter(m -> m != JAVA_BASE) - .forEach(m -> { - deque.add(m); - builder.addEdge(module, m); - }); - - // read requires public from ModuleDescription - Module source; - while ((source = deque.poll()) != null) { - if (visited.contains(source)) - continue; - visited.add(source); - builder.addNode(source); - Module from = source; - source.descriptor().requires().stream() - .filter(req -> req.modifiers().contains(PUBLIC)) - .map(ModuleDescriptor.Requires::name) - .map(req -> modulePaths.getModules().get(req)) - .filter(m -> m != JAVA_BASE) - .forEach(m -> { - deque.add(m); - builder.addEdge(from, m); - }); + public boolean genDotFiles(Path dir) throws IOException { + Files.createDirectories(dir); + for (Module m : modules.keySet()) { + genDotFile(dir, m.name()); } - return builder.build(); + return true; } - static class Graph { - private final Set nodes; - private final Map> edges; - private Graph(Set nodes, Map> edges) { - this.nodes = nodes; - this.edges = edges; - } - - public Set nodes() { - return nodes; - } - - public Map> edges() { - return edges; - } - - public Set adjacentNodes(T u) { - return edges.get(u); - } - - /** - * Returns a new Graph after transitive reduction - */ - public Graph reduce() { - Graph.Builder builder = new Builder<>(); - nodes.stream() - .forEach(u -> { - builder.addNode(u); - edges.get(u).stream() - .filter(v -> !pathExists(u, v, false)) - .forEach(v -> builder.addEdge(u, v)); - }); - return builder.build(); - } - - /** - * Returns a new Graph after transitive reduction. All edges in - * the given g takes precedence over this graph. - * - * @throw IllegalArgumentException g must be a subgraph this graph - */ - public Graph reduce(Graph g) { - boolean subgraph = nodes.containsAll(g.nodes) && g.edges.keySet().stream() - .allMatch(u -> adjacentNodes(u).containsAll(g.adjacentNodes(u))); - if (!subgraph) { - throw new IllegalArgumentException(g + " is not a subgraph of " + this); - } - - Graph.Builder builder = new Builder<>(); - nodes.stream() - .forEach(u -> { - builder.addNode(u); - // filter the edge if there exists a path from u to v in the given g - // or there exists another path from u to v in this graph - edges.get(u).stream() - .filter(v -> !g.pathExists(u, v) && !pathExists(u, v, false)) - .forEach(v -> builder.addEdge(u, v)); - }); - - // add the overlapped edges from this graph and the given g - g.edges().keySet().stream() - .forEach(u -> g.adjacentNodes(u).stream() - .filter(v -> isAdjacent(u, v)) - .forEach(v -> builder.addEdge(u, v))); - return builder.build(); - } - - /** - * Returns nodes sorted in topological order. - */ - public Stream orderedNodes() { - TopoSorter sorter = new TopoSorter<>(this); - return sorter.result.stream(); - } - - /** - * Iterates the nodes sorted in topological order and performs the - * given action. - */ - public void ordered(Consumer action) { - TopoSorter sorter = new TopoSorter<>(this); - sorter.ordered(action); - } - - /** - * Iterates the nodes sorted in reverse topological order and - * performs the given action. - */ - public void reverse(Consumer action) { - TopoSorter sorter = new TopoSorter<>(this); - sorter.reverse(action); - } - - private boolean isAdjacent(T u, T v) { - return edges.containsKey(u) && edges.get(u).contains(v); - } - - private boolean pathExists(T u, T v) { - return pathExists(u, v, true); - } - - /** - * Returns true if there exists a path from u to v in this graph. - * If includeAdjacent is false, it returns true if there exists - * another path from u to v of distance > 1 - */ - private boolean pathExists(T u, T v, boolean includeAdjacent) { - if (!nodes.contains(u) || !nodes.contains(v)) { - return false; - } - if (includeAdjacent && isAdjacent(u, v)) { - return true; - } - Deque stack = new LinkedList<>(); - Set visited = new HashSet<>(); - stack.push(u); - while (!stack.isEmpty()) { - T node = stack.pop(); - if (node.equals(v)) { - return true; - } - if (!visited.contains(node)) { - visited.add(node); - edges.get(node).stream() - .filter(e -> includeAdjacent || !node.equals(u) || !e.equals(v)) - .forEach(e -> stack.push(e)); - } - } - assert !visited.contains(v); - return false; - } - - void printGraph(PrintStream out) { - out.println("graph for " + nodes); - nodes.stream() - .forEach(u -> adjacentNodes(u).stream() - .forEach(v -> out.format("%s -> %s%n", u, v))); - } - - @Override - public String toString() { - return nodes.toString(); - } - - static class Builder { - final Set nodes = new HashSet<>(); - final Map> edges = new HashMap<>(); - - public void addNode(T node) { - if (nodes.contains(node)) { - return; - } - nodes.add(node); - edges.computeIfAbsent(node, _e -> new HashSet<>()); - } - - public void addEdge(T u, T v) { - addNode(u); - addNode(v); - edges.get(u).add(v); - } - - public Graph build() { - return new Graph<>(nodes, edges); - } - - void print(PrintStream out) { - out.println(nodes); - nodes.stream() - .forEach(u -> edges.get(u).stream() - .forEach(v -> out.format("%s -> %s%n", u, v))); - } - } - } - - static class TopoSorter { - final Deque result = new LinkedList<>(); - final Deque nodes; - final Graph graph; - TopoSorter(Graph graph) { - this.graph = graph; - this.nodes = new LinkedList<>(graph.nodes); - sort(); - } - - public void ordered(Consumer action) { - result.iterator().forEachRemaining(action); - } - - public void reverse(Consumer action) { - result.descendingIterator().forEachRemaining(action); - } - - private void sort() { - Deque visited = new LinkedList<>(); - Deque done = new LinkedList<>(); - T node; - while ((node = nodes.poll()) != null) { - if (!visited.contains(node)) { - visit(node, visited, done); - } - } - } - - private void visit(T node, Deque visited, Deque done) { - if (visited.contains(node)) { - if (!done.contains(node)) { - throw new IllegalArgumentException("Cyclic detected: " + - node + " " + graph.edges().get(node)); - } - return; - } - visited.add(node); - graph.edges().get(node).stream() - .forEach(x -> visit(x, visited, done)); - done.add(node); - result.addLast(node); - } - } - - static class DotGraph { - static final String ORANGE = "#e76f00"; - static final String BLUE = "#437291"; - static final String GRAY = "#dddddd"; - - static final String REEXPORTS = ""; - static final String REQUIRES = "style=\"dashed\""; - static final String REQUIRES_BASE = "color=\"" + GRAY + "\""; - - static final Set javaModules = modules(name -> - (name.startsWith("java.") && !name.equals("java.smartcardio"))); - static final Set jdkModules = modules(name -> - (name.startsWith("java.") || - name.startsWith("jdk.") || - name.startsWith("javafx.")) && !javaModules.contains(name)); - - private static Set modules(Predicate predicate) { - return ModuleFinder.ofSystem().findAll() - .stream() - .map(ModuleReference::descriptor) - .map(ModuleDescriptor::name) - .filter(predicate) - .collect(Collectors.toSet()); - } - - static void printAttributes(PrintStream out) { - out.format(" size=\"25,25\";%n"); - out.format(" nodesep=.5;%n"); - out.format(" ranksep=1.5;%n"); - out.format(" pencolor=transparent;%n"); - out.format(" node [shape=plaintext, fontname=\"DejaVuSans\", fontsize=36, margin=\".2,.2\"];%n"); - out.format(" edge [penwidth=4, color=\"#999999\", arrowhead=open, arrowsize=2];%n"); - } - - static void printNodes(PrintStream out, Graph graph) { - out.format(" subgraph se {%n"); - graph.nodes().stream() - .filter(javaModules::contains) - .forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n", - mn, ORANGE, "java")); - out.format(" }%n"); - graph.nodes().stream() - .filter(jdkModules::contains) - .forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n", - mn, BLUE, "jdk")); - - graph.nodes().stream() - .filter(mn -> !javaModules.contains(mn) && !jdkModules.contains(mn)) - .forEach(mn -> out.format(" \"%s\";%n", mn)); - } - - static void printEdges(PrintStream out, Graph graph, - String node, Set requiresPublic) { - graph.adjacentNodes(node).forEach(dn -> { - String attr = dn.equals("java.base") ? REQUIRES_BASE - : (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES); - out.format(" \"%s\" -> \"%s\" [%s];%n", node, dn, attr); - }); - } - } - - public void genDotFile(Path dir) throws IOException { - String name = root.name(); - try (PrintStream out - = new PrintStream(Files.newOutputStream(dir.resolve(name + ".dot")))) { - Configuration cf = modulePaths.configuration(name); + private void genDotFile(Path dir, String name) throws IOException { + try (OutputStream os = Files.newOutputStream(dir.resolve(name + ".dot")); + PrintWriter out = new PrintWriter(os)) { + Set modules = configuration.resolve(Set.of(name)) + .collect(Collectors.toSet()); // transitive reduction - Graph graph = gengraph(cf); + Graph graph = gengraph(modules); out.format("digraph \"%s\" {%n", name); DotGraph.printAttributes(out); DotGraph.printNodes(out, graph); - cf.modules().stream() - .map(ResolvedModule::reference) - .map(ModuleReference::descriptor) - .sorted(Comparator.comparing(ModuleDescriptor::name)) - .forEach(md -> { - String mn = md.name(); - Set requiresPublic = md.requires().stream() + modules.stream() + .map(Module::descriptor) + .sorted(Comparator.comparing(ModuleDescriptor::name)) + .forEach(md -> { + String mn = md.name(); + Set requiresPublic = md.requires().stream() .filter(d -> d.modifiers().contains(PUBLIC)) .map(d -> d.name()) - .collect(Collectors.toSet()); + .collect(toSet()); - DotGraph.printEdges(out, graph, mn, requiresPublic); - }); + DotGraph.printEdges(out, graph, mn, requiresPublic); + }); out.println("}"); } } - /** * Returns a Graph of the given Configuration after transitive reduction. * @@ -675,12 +441,12 @@ class ModuleAnalyzer { * (e.g. U -> V) from being reduced by a path (U -> X -> Y -> V) * in which V would not be re-exported from U. */ - private Graph gengraph(Configuration cf) { + private Graph gengraph(Set modules) { // build a Graph containing only requires public edges // with transitive reduction. Graph.Builder rpgbuilder = new Graph.Builder<>(); - for (ResolvedModule resolvedModule : cf.modules()) { - ModuleDescriptor md = resolvedModule.reference().descriptor(); + for (Module module : modules) { + ModuleDescriptor md = module.descriptor(); String mn = md.name(); md.requires().stream() .filter(d -> d.modifiers().contains(PUBLIC)) @@ -692,12 +458,12 @@ class ModuleAnalyzer { // build the readability graph Graph.Builder builder = new Graph.Builder<>(); - for (ResolvedModule resolvedModule : cf.modules()) { - ModuleDescriptor md = resolvedModule.reference().descriptor(); + for (Module module : modules) { + ModuleDescriptor md = module.descriptor(); String mn = md.name(); builder.addNode(mn); - resolvedModule.reads().stream() - .map(ResolvedModule::name) + configuration.reads(module) + .map(Module::name) .forEach(d -> builder.addEdge(mn, d)); } @@ -705,4 +471,25 @@ class ModuleAnalyzer { return builder.build().reduce(rpg); } + // ---- for testing purpose + public ModuleDescriptor[] descriptors(String name) { + ModuleDeps moduleDeps = modules.keySet().stream() + .filter(m -> m.name().equals(name)) + .map(modules::get) + .findFirst().get(); + + ModuleDescriptor[] descriptors = new ModuleDescriptor[3]; + descriptors[0] = moduleDeps.root.descriptor(); + descriptors[1] = moduleDeps.descriptor(); + descriptors[2] = moduleDeps.reduced(); + return descriptors; + } + + public Map> unusedQualifiedExports(String name) { + ModuleDeps moduleDeps = modules.keySet().stream() + .filter(m -> m.name().equals(name)) + .map(modules::get) + .findFirst().get(); + return moduleDeps.unusedQualifiedExports; + } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java index 1afed6bfa77..ab493a61977 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java @@ -24,15 +24,25 @@ */ package com.sun.tools.jdeps; -import static com.sun.tools.jdeps.Analyzer.Type.CLASS; -import static com.sun.tools.jdeps.Analyzer.NOT_FOUND; -import static com.sun.tools.jdeps.Module.trace; +import static com.sun.tools.jdeps.JdepsTask.*; +import static com.sun.tools.jdeps.Analyzer.*; +import static com.sun.tools.jdeps.JdepsFilter.DEFAULT_FILTER; import java.io.IOException; import java.io.PrintWriter; +import java.io.UncheckedIOException; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleDescriptor.Exports; +import java.lang.module.ModuleDescriptor.Provides; +import java.lang.module.ModuleDescriptor.Requires; +import java.lang.module.ModuleFinder; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -40,168 +50,189 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; + public class ModuleInfoBuilder { - final ModulePaths modulePaths; + final JdepsConfiguration configuration; + final Path outputdir; + final DependencyFinder dependencyFinder; - final JdepsFilter filter; final Analyzer analyzer; - final Map strictModules = new HashMap<>(); - ModuleInfoBuilder(ModulePaths modulePaths, DependencyFinder finder) { - this.modulePaths = modulePaths; - this.dependencyFinder = finder; - this.filter = new JdepsFilter.Builder().filter(true, true).build(); - this.analyzer = new Analyzer(CLASS, filter); + + // an input JAR file (loaded as an automatic module for analysis) + // maps to an explicit module to generate module-info.java + final Map automaticToExplicitModule; + public ModuleInfoBuilder(JdepsConfiguration configuration, + List args, + Path outputdir) { + this.configuration = configuration; + this.outputdir = outputdir; + + this.dependencyFinder = new DependencyFinder(configuration, DEFAULT_FILTER); + this.analyzer = new Analyzer(configuration, Type.CLASS, DEFAULT_FILTER); + + // add targets to modulepath if it has module-info.class + List paths = args.stream() + .map(fn -> Paths.get(fn)) + .collect(Collectors.toList()); + + // automatic module to convert to explicit module + this.automaticToExplicitModule = ModuleFinder.of(paths.toArray(new Path[0])) + .findAll().stream() + .map(configuration::toModule) + .collect(Collectors.toMap(Function.identity(), Function.identity())); + + Optional om = automaticToExplicitModule.keySet().stream() + .filter(m -> !m.descriptor().isAutomatic()) + .findAny(); + if (om.isPresent()) { + throw new UncheckedBadArgs(new BadArgs("err.genmoduleinfo.not.jarfile", + om.get().getPathName())); + } + if (automaticToExplicitModule.isEmpty()) { + throw new UncheckedBadArgs(new BadArgs("err.invalid.path", args)); + } } - private Stream automaticModules() { - return modulePaths.getModules().values() - .stream() - .filter(Module::isAutomatic); + public boolean run() throws IOException { + try { + // pass 1: find API dependencies + Map> requiresPublic = computeRequiresPublic(); + + // pass 2: analyze all class dependences + dependencyFinder.parse(automaticModules().stream()); + + analyzer.run(automaticModules(), dependencyFinder.locationToArchive()); + + boolean missingDeps = false; + for (Module m : automaticModules()) { + Set apiDeps = requiresPublic.containsKey(m) + ? requiresPublic.get(m) + : Collections.emptySet(); + + Path file = outputdir.resolve(m.name()).resolve("module-info.java"); + + // computes requires and requires public + Module explicitModule = toExplicitModule(m, apiDeps); + if (explicitModule != null) { + automaticToExplicitModule.put(m, explicitModule); + + // generate module-info.java + System.out.format("writing to %s%n", file); + writeModuleInfo(file, explicitModule.descriptor()); + } else { + // find missing dependences + System.out.format("Missing dependence: %s not generated%n", file); + missingDeps = true; + } + } + + return !missingDeps; + } finally { + dependencyFinder.shutdown(); + } + } + + boolean notFound(Archive m) { + return m == NOT_FOUND || m == REMOVED_JDK_INTERNALS; + } + + private Module toExplicitModule(Module module, Set requiresPublic) + throws IOException + { + // done analysis + module.close(); + + if (analyzer.requires(module).anyMatch(this::notFound)) { + // missing dependencies + return null; + } + + Map requires = new HashMap<>(); + requiresPublic.stream() + .map(Archive::getModule) + .forEach(m -> requires.put(m.name(), Boolean.TRUE)); + + analyzer.requires(module) + .map(Archive::getModule) + .forEach(d -> requires.putIfAbsent(d.name(), Boolean.FALSE)); + + return module.toStrictModule(requires); + } + + /** + * Returns the stream of resulting modules + */ + Stream modules() { + return automaticToExplicitModule.values().stream(); + } + + /** + * Returns the stream of resulting ModuleDescriptors + */ + public Stream descriptors() { + return automaticToExplicitModule.entrySet().stream() + .map(Map.Entry::getValue) + .map(Module::descriptor); + } + + void visitMissingDeps(Analyzer.Visitor visitor) { + automaticModules().stream() + .filter(m -> analyzer.requires(m).anyMatch(this::notFound)) + .forEach(m -> { + analyzer.visitDependences(m, visitor, Analyzer.Type.VERBOSE); + }); + } + + void writeModuleInfo(Path file, ModuleDescriptor descriptor) { + try { + Files.createDirectories(file.getParent()); + try (PrintWriter pw = new PrintWriter(Files.newOutputStream(file))) { + printModuleInfo(pw, descriptor); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private void printModuleInfo(PrintWriter writer, ModuleDescriptor descriptor) { + writer.format("module %s {%n", descriptor.name()); + + Map modules = configuration.getModules(); + // first print the JDK modules + descriptor.requires().stream() + .filter(req -> !req.name().equals("java.base")) // implicit requires + .sorted(Comparator.comparing(Requires::name)) + .forEach(req -> writer.format(" requires %s;%n", req)); + + descriptor.exports().stream() + .peek(exp -> { + if (exp.targets().size() > 0) + throw new InternalError(descriptor.name() + " qualified exports: " + exp); + }) + .sorted(Comparator.comparing(Exports::source)) + .forEach(exp -> writer.format(" exports %s;%n", exp.source())); + + descriptor.provides().values().stream() + .sorted(Comparator.comparing(Provides::service)) + .forEach(p -> p.providers().stream() + .sorted() + .forEach(impl -> writer.format(" provides %s with %s;%n", p.service(), impl))); + + writer.println("}"); + } + + + private Set automaticModules() { + return automaticToExplicitModule.keySet(); } /** * Compute 'requires public' dependences by analyzing API dependencies */ - Map> computeRequiresPublic() throws IOException { - dependencyFinder.findDependencies(filter, true /* api only */, 1); - Analyzer pass1 = new Analyzer(Analyzer.Type.CLASS, filter); + private Map> computeRequiresPublic() throws IOException { + // parse the input modules + dependencyFinder.parseExportedAPIs(automaticModules().stream()); - pass1.run(dependencyFinder.archives()); - - return automaticModules().collect(Collectors.toMap(Function.identity(), - source -> pass1.requires(source) - .map(Archive::getModule) - .collect(Collectors.toSet()))); - } - - boolean run(Analyzer.Type verbose, boolean quiet) throws IOException { - // add all automatic modules to the root set - automaticModules().forEach(dependencyFinder::addRoot); - - // pass 1: find API dependencies - Map> requiresPublic = computeRequiresPublic(); - - // pass 2: analyze all class dependences - dependencyFinder.findDependencies(filter, false /* all classes */, 1); - analyzer.run(dependencyFinder.archives()); - - // computes requires and requires public - automaticModules().forEach(m -> { - Map requires; - if (requiresPublic.containsKey(m)) { - requires = requiresPublic.get(m) - .stream() - .collect(Collectors.toMap(Archive::getName, (v) -> Boolean.TRUE)); - } else { - requires = new HashMap<>(); - } - analyzer.requires(m) - .forEach(d -> requires.putIfAbsent(d.getName(), Boolean.FALSE)); - - trace("strict module %s requires %s%n", m.name(), requires); - strictModules.put(m, m.toStrictModule(requires)); - }); - - // find any missing dependences - Optional missingDeps = automaticModules() - .filter(this::missingDep) - .findAny(); - if (missingDeps.isPresent()) { - automaticModules() - .filter(this::missingDep) - .forEach(m -> { - System.err.format("Missing dependencies from %s%n", m.name()); - analyzer.visitDependences(m, - new Analyzer.Visitor() { - @Override - public void visitDependence(String origin, Archive originArchive, - String target, Archive targetArchive) { - if (targetArchive == NOT_FOUND) - System.err.format(" %-50s -> %-50s %s%n", - origin, target, targetArchive.getName()); - } - }, verbose); - System.err.println(); - }); - - System.err.println("ERROR: missing dependencies (check \"requires NOT_FOUND;\")"); - } - return missingDeps.isPresent() ? false : true; - } - - private boolean missingDep(Archive m) { - return analyzer.requires(m).filter(a -> a.equals(NOT_FOUND)) - .findAny().isPresent(); - } - - void build(Path dir) throws IOException { - ModuleInfoWriter writer = new ModuleInfoWriter(dir); - writer.generateOutput(strictModules.values(), analyzer); - } - - private class ModuleInfoWriter { - private final Path outputDir; - ModuleInfoWriter(Path dir) { - this.outputDir = dir; - } - - void generateOutput(Iterable modules, Analyzer analyzer) throws IOException { - // generate module-info.java file for each archive - for (Module m : modules) { - if (m.packages().contains("")) { - System.err.format("ERROR: %s contains unnamed package. " + - "module-info.java not generated%n", m.getPathName()); - continue; - } - - String mn = m.getName(); - Path srcFile = outputDir.resolve(mn).resolve("module-info.java"); - Files.createDirectories(srcFile.getParent()); - System.out.println("writing to " + srcFile); - try (PrintWriter pw = new PrintWriter(Files.newOutputStream(srcFile))) { - printModuleInfo(pw, m); - } - } - } - - private void printModuleInfo(PrintWriter writer, Module m) { - writer.format("module %s {%n", m.name()); - - Map modules = modulePaths.getModules(); - Map requires = m.requires(); - // first print the JDK modules - requires.keySet().stream() - .filter(mn -> !mn.equals("java.base")) // implicit requires - .filter(mn -> modules.containsKey(mn) && modules.get(mn).isJDK()) - .sorted() - .forEach(mn -> { - String modifier = requires.get(mn) ? "public " : ""; - writer.format(" requires %s%s;%n", modifier, mn); - }); - - // print requires non-JDK modules - requires.keySet().stream() - .filter(mn -> !modules.containsKey(mn) || !modules.get(mn).isJDK()) - .sorted() - .forEach(mn -> { - String modifier = requires.get(mn) ? "public " : ""; - writer.format(" requires %s%s;%n", modifier, mn); - }); - - m.packages().stream() - .sorted() - .forEach(pn -> writer.format(" exports %s;%n", pn)); - - m.provides().entrySet().stream() - .sorted(Map.Entry.comparingByKey()) - .forEach(e -> { - String service = e.getKey(); - e.getValue().stream() - .sorted() - .forEach(impl -> writer.format(" provides %s with %s;%n", service, impl)); - }); - - writer.println("}"); - } + return dependencyFinder.dependences(); } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java deleted file mode 100644 index 8e1cdb8b4b8..00000000000 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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 - * 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 com.sun.tools.jdeps; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.lang.module.Configuration; -import java.lang.module.ModuleDescriptor; -import java.lang.module.ModuleFinder; -import java.lang.module.ModuleReference; -import java.lang.module.ResolvedModule; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.ProviderNotFoundException; -import java.util.*; -import java.util.stream.Collectors; - -import static java.lang.module.ModuleDescriptor.Requires.Modifier.*; - -public class ModulePaths { - final ModuleFinder finder; - final Map modules = new LinkedHashMap<>(); - - public ModulePaths(String upgradeModulePath, String modulePath) { - this(upgradeModulePath, modulePath, Collections.emptyList()); - } - - public ModulePaths(String upgradeModulePath, String modulePath, List jars) { - ModuleFinder finder = ModuleFinder.ofSystem(); - if (upgradeModulePath != null) { - finder = ModuleFinder.compose(createModulePathFinder(upgradeModulePath), finder); - } - if (jars.size() > 0) { - finder = ModuleFinder.compose(finder, ModuleFinder.of(jars.toArray(new Path[0]))); - } - if (modulePath != null) { - finder = ModuleFinder.compose(finder, createModulePathFinder(modulePath)); - } - this.finder = finder; - - // add modules from modulepaths - finder.findAll().stream().forEach(mref -> - modules.computeIfAbsent(mref.descriptor().name(), mn -> toModule(mn, mref)) - ); - } - - /** - * Returns the list of Modules that can be found in the specified - * module paths. - */ - Map getModules() { - return modules; - } - - Set dependences(String... roots) { - Configuration cf = configuration(roots); - return cf.modules().stream() - .map(ResolvedModule::name) - .map(modules::get) - .collect(Collectors.toSet()); - } - - Configuration configuration(String... roots) { - return Configuration.empty().resolveRequires(finder, ModuleFinder.empty(), Set.of(roots)); - } - - private static ModuleFinder createModulePathFinder(String mpaths) { - if (mpaths == null) { - return null; - } else { - String[] dirs = mpaths.split(File.pathSeparator); - Path[] paths = new Path[dirs.length]; - int i = 0; - for (String dir : dirs) { - paths[i++] = Paths.get(dir); - } - return ModuleFinder.of(paths); - } - } - - private static Module toModule(String mn, ModuleReference mref) { - return SystemModulePath.find(mn) - .orElse(toModule(new Module.Builder(mn), mref)); - } - - private static Module toModule(Module.Builder builder, ModuleReference mref) { - ModuleDescriptor md = mref.descriptor(); - builder.descriptor(md); - for (ModuleDescriptor.Requires req : md.requires()) { - builder.require(req.name(), req.modifiers().contains(PUBLIC)); - } - for (ModuleDescriptor.Exports exp : md.exports()) { - builder.export(exp.source(), exp.targets()); - } - builder.packages(md.packages()); - - try { - URI location = mref.location() - .orElseThrow(FileNotFoundException::new); - builder.location(location); - builder.classes(getClassReader(location, md.name())); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - return builder.build(); - } - - static class SystemModulePath { - final static Module JAVA_BASE; - - private final static FileSystem fs; - private final static Path root; - private final static Map installed = new HashMap<>(); - static { - if (isJrtAvailable()) { - // jrt file system - fs = FileSystems.getFileSystem(URI.create("jrt:/")); - root = fs.getPath("/modules"); - } else { - // exploded image - String javahome = System.getProperty("java.home"); - fs = FileSystems.getDefault(); - root = Paths.get(javahome, "modules"); - } - - ModuleFinder.ofSystem().findAll().stream() - .forEach(mref -> - installed.computeIfAbsent(mref.descriptor().name(), - mn -> toModule(new Module.Builder(mn, true), mref)) - ); - JAVA_BASE = installed.get("java.base"); - - Profile.init(installed); - } - - private static boolean isJrtAvailable() { - try { - FileSystems.getFileSystem(URI.create("jrt:/")); - return true; - } catch (ProviderNotFoundException | FileSystemNotFoundException e) { - return false; - } - } - - public static Optional find(String mn) { - return installed.containsKey(mn) ? Optional.of(installed.get(mn)) - : Optional.empty(); - } - - public static boolean contains(Module m) { - return installed.containsValue(m); - } - - public static ClassFileReader getClassReader(String modulename) throws IOException { - Path mp = root.resolve(modulename); - if (Files.exists(mp) && Files.isDirectory(mp)) { - return ClassFileReader.newInstance(fs, mp); - } else { - throw new FileNotFoundException(mp.toString()); - } - } - } - - /** - * Returns a ModuleClassReader that only reads classes for the given modulename. - */ - public static ClassFileReader getClassReader(URI location, String modulename) - throws IOException { - if (location.getScheme().equals("jrt")) { - return SystemModulePath.getClassReader(modulename); - } else { - Path path = Paths.get(location); - return ClassFileReader.newInstance(path); - } - } -} diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java index c0790abc945..c150ca8d89b 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java @@ -26,9 +26,13 @@ package com.sun.tools.jdeps; import java.io.IOException; +import java.lang.module.ModuleDescriptor; +import java.util.Arrays; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Optional; import java.util.Set; /** @@ -44,17 +48,18 @@ enum Profile { // need a way to determine JRE modules SE_JRE("Java SE JRE", 4, "java.se", "jdk.charsets", "jdk.crypto.ec", "jdk.crypto.pkcs11", - "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat", + "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs"), FULL_JRE("Full JRE", 5, "java.se.ee", "jdk.charsets", "jdk.crypto.ec", "jdk.crypto.pkcs11", "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat", - "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs"); + "jdk.localedata", "jdk.scripting.nashorn", + "jdk.unsupported", "jdk.zipfs"); final String name; final int profile; final String[] mnames; - final Set modules = new HashSet<>(); + final Map modules = new HashMap<>(); Profile(String name, int profile, String... mnames) { this.name = name; @@ -75,12 +80,18 @@ enum Profile { return JDK.isEmpty() ? 0 : Profile.values().length; } + Optional findModule(String name) { + return modules.containsKey(name) + ? Optional.of(modules.get(name)) + : Optional.empty(); + } + /** * Returns the Profile for the given package name; null if not found. */ public static Profile getProfile(String pn) { for (Profile p : Profile.values()) { - for (Module m : p.modules) { + for (Module m : p.modules.values()) { if (m.packages().contains(pn)) { return p; } @@ -94,7 +105,7 @@ enum Profile { */ public static Profile getProfile(Module m) { for (Profile p : Profile.values()) { - if (p.modules.contains(m)) { + if (p.modules.containsValue(m)) { return p; } } @@ -102,34 +113,28 @@ enum Profile { } private final static Set JDK = new HashSet<>(); - static synchronized void init(Map installed) { - for (Profile p : Profile.values()) { - for (String mn : p.mnames) { - // this includes platform-dependent module that may not exist - Module m = installed.get(mn); - if (m != null) { - p.addModule(installed, m); - } - } - } + static synchronized void init(Map systemModules) { + Arrays.stream(Profile.values()).forEach(p -> + // this includes platform-dependent module that may not exist + Arrays.stream(p.mnames) + .filter(systemModules::containsKey) + .map(systemModules::get) + .forEach(m -> p.addModule(systemModules, m))); // JDK modules should include full JRE plus other jdk.* modules // Just include all installed modules. Assume jdeps is running // in JDK image - JDK.addAll(installed.values()); + JDK.addAll(systemModules.values()); } - private void addModule(Map installed, Module m) { - modules.add(m); - for (String n : m.requires().keySet()) { - Module d = installed.get(n); - if (d == null) { - throw new InternalError("module " + n + " required by " + - m.name() + " doesn't exist"); - } - modules.add(d); - } + private void addModule(Map systemModules, Module module) { + modules.put(module.name(), module); + module.descriptor().requires().stream() + .map(ModuleDescriptor.Requires::name) + .map(systemModules::get) + .forEach(m -> modules.put(m.name(), m)); } + // for debugging public static void main(String[] args) throws IOException { // find platform modules @@ -139,14 +144,6 @@ enum Profile { for (Profile p : Profile.values()) { String profileName = p.name; System.out.format("%2d: %-10s %s%n", p.profile, profileName, p.modules); - for (Module m: p.modules) { - System.out.format("module %s%n", m.name()); - System.out.format(" requires %s%n", m.requires()); - for (Map.Entry> e: m.exports().entrySet()) { - System.out.format(" exports %s %s%n", e.getKey(), - e.getValue().isEmpty() ? "" : "to " + e.getValue()); - } - } } System.out.println("All JDK modules:-"); JDK.stream().sorted(Comparator.comparing(Module::name)) diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties index b0fc19bee46..117baf1fc53 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties @@ -1,12 +1,10 @@ main.usage.summary=\ -Usage: {0} [-m | ]\n\ +Usage: {0} ]\n\ use -h, -? or -help for a list of possible options main.usage=\ -Usage: {0} [-m | ]\n\ -If -m is specified, the specified module will be analyzed\n\ -otherwise, can be a pathname to a .class file, a directory,\n\ -a JAR file, or a fully-qualified class name.\n\ +Usage: {0} ]\n\ + can be a pathname to a .class file, a directory, a JAR file.\n\ \n\ Possible options include: @@ -14,134 +12,156 @@ error.prefix=Error: warn.prefix=Warning: main.opt.h=\ -\ -h -? -help Print this usage message +\ -h -? -help Print this usage message main.opt.version=\ -\ -version Version information +\ -version Version information main.opt.v=\ -\ -v -verbose Print all class level dependencies\n\ -\ Equivalent to -verbose:class -filter:none.\n\ -\ -verbose:package Print package-level dependencies excluding\n\ -\ dependencies within the same package by default\n\ -\ -verbose:class Print class-level dependencies excluding\n\ -\ dependencies within the same package by default - -main.opt.f=\ -\ -f -filter Filter dependences matching the given pattern\n\ -\ If given multiple times, the last one will be used.\n\ -\ -filter:package Filter dependences within the same package (default)\n\ -\ -filter:module Filter dependences within the same module\n\ -\ -filter:archive Filter dependences within the same archive\n\ -\ -filter:none No -filter:package and -filter:archive filtering\n\ -\ Filtering specified via the -filter option still applies. +\ -v -verbose Print all class level dependencies\n\ +\ Equivalent to -verbose:class -filter:none.\n\ +\ -verbose:package Print package-level dependencies excluding\n\ +\ dependencies within the same package by default\n\ +\ -verbose:class Print class-level dependencies excluding\n\ +\ dependencies within the same package by default main.opt.s=\ -\ -s -summary Print dependency summary only.\n\ -\ If -s option is used with -m, the module descriptor of\n\ -\ the given module will be read to generate the graph. +\ -s -summary Print dependency summary only. -main.opt.p=\ -\ -p Finds dependences matching the given package name\n\ -\ -package (may be given multiple times). +main.opt.f=\ +\ -f -filter Filter dependences matching the given\n\ +\ pattern. If given multiple times, the last\n\ +\ one will be used.\n\ +\ -filter:package Filter dependences within the same package.\n\ +\ This is the default.\n\ +\ -filter:archive Filter dependences within the same archive.\n\ +\ -filter:module Filter dependences within the same module.\n\ +\ -filter:none No -filter:package and -filter:archive\n\ +\ filtering. Filtering specified via the\n\ +\ -filter option still applies.\n\ + +main.opt.p=\n\ +\Options to filter dependencies:\n\ +\ -p -package Finds dependences matching the given package\n\ +\ name (may be given multiple times). main.opt.e=\ -\ -e \n\ -\ -regex Finds dependences matching the given pattern. +\ -e -regex Finds dependences matching the given pattern. -main.opt.module=\ -\ -module Finds dependences matching the given module name\n\ -\ (may be given multiple times).\n\ -\ -package, -regex, -requires are mutual exclusive. +main.opt.requires=\ +\ -requires Finds dependences matching the given module\n\ +\ name (may be given multiple times).\n\ +\ -package, -regex, -requires are mutual exclusive. -main.opt.include=\ -\ -include Restrict analysis to classes matching pattern\n\ -\ This option filters the list of classes to\n\ -\ be analyzed. It can be used together with\n\ -\ -p and -e which apply pattern to the dependences +main.opt.include=\n\ + \Options to filter classes to be analyzed:\n\ +\ -include Restrict analysis to classes matching pattern\n\ +\ This option filters the list of classes to\n\ +\ be analyzed. It can be used together with\n\ +\ -p and -e which apply pattern to the dependences main.opt.P=\ -\ -P -profile Show profile containing a package - -main.opt.M=\ -\ -M Show module containing a package +\ -P -profile Show profile containing a package main.opt.cp=\ -\ -cp -classpath Specify where to find class files +\ -cp -classpath Specify where to find class files main.opt.mp=\ \ -mp ...\n\ -\ -modulepath ... Specify module path +\ -modulepath ... Specify module path main.opt.upgrademodulepath=\ \ -upgrademodulepath ... Specify upgrade module path +main.opt.system=\ +\ -system Specify an alternate system module path + +main.opt.addmods=\ +\ -addmods [,...]\n\ +\ Adds modules to the root set for analysis + main.opt.m=\ -\ -m Specify the name of the module and its transitive\n\ -\ dependences to be analyzed. +\ -m Specify the root module for analysis main.opt.R=\ -\ -R -recursive Recursively traverse all run-time dependencies.\n\ -\ The -R option implies -filter:none. If -p, -e, -f\n\ -\ option is specified, only the matching dependences\n\ -\ are analyzed. +\ -R -recursive Recursively traverse all run-time dependencies.\n\ +\ The -R option implies -filter:none. If -p,\n\ +\ -e, -foption is specified, only the matching\n\ +\ dependences are analyzed. + +main.opt.I=\ +\ -I -inverse Analyzes the dependences per other given options\n\ +\ and then find all artifacts that directly\n\ +\ and indirectly depend on the matching nodes.\n\ +\ This is equivalent to the inverse of\n\ +\ compile-time view analysis and print\n\ +\ dependency summary. This option must use\n\ +\ with -requires, -package or -regex option. main.opt.ct=\ -\ -ct -compile-time Compile-time view of transitive dependencies\n\ -\ i.e. compile-time view of -R option. If a dependence\n\ -\ is found from a directory, a JAR file or a module,\n\ -\ all class files in that containing archive are analyzed. +\ -ct -compile-time Compile-time view of transitive dependencies\n\ +\ i.e. compile-time view of -R option.\n\ +\ Analyzes the dependences per other given options\n\ +\ If a dependence is found from a directory,\n\ +\ a JAR file or a module, all classes in that \n\ +\ containing archive are analyzed. main.opt.apionly=\ -\ -apionly Restrict analysis to APIs i.e. dependences\n\ -\ from the signature of public and protected\n\ -\ members of public classes including field\n\ -\ type, method parameter types, returned type,\n\ -\ checked exception types etc +\ -apionly Restrict analysis to APIs i.e. dependences\n\ +\ from the signature of public and protected\n\ +\ members of public classes including field\n\ +\ type, method parameter types, returned type,\n\ +\ checked exception types etc. main.opt.genmoduleinfo=\ -\ -genmoduleinfo Generate module-info.java under the specified directory.\n\ -\ The specified JAR files will be analyzed.\n\ -\ This option cannot be used with -dotoutput or -cp. +\ -genmoduleinfo Generate module-info.java under the specified\n\ +\ directory. The specified JAR files will be\n\ +\ analyzed. This option cannot be used with\n\ +\ -dotoutput or -cp. main.opt.check=\ -\ -check Analyze the dependence of a given module specified via\n\ -\ -m option. It prints out the resulting module dependency\n\ -\ graph after transition reduction and also identifies any\n\ -\ unused qualified exports. +\ -check [,...\n\ +\ Analyze the dependence of the specified modules\n\ +\ It prints the module descriptor, the resulting\n\ +\ module dependences after analysis and the\n\ +\ graph after transition reduction. It also\n\ +\ identifies any unused qualified exports. main.opt.dotoutput=\ -\ -dotoutput Destination directory for DOT file output +\ -dotoutput Destination directory for DOT file output main.opt.jdkinternals=\ -\ -jdkinternals Finds class-level dependences on JDK internal APIs.\n\ -\ By default, it analyzes all classes on -classpath\n\ -\ and input files unless -include option is specified.\n\ -\ This option cannot be used with -p, -e and -s options.\n\ -\ WARNING: JDK internal APIs may not be accessible in\n\ -\ the next release. +\ -jdkinternals Finds class-level dependences on JDK internal\n\ +\ APIs. By default, it analyzes all classes\n\ +\ on -classpath and input files unless -include\n\ +\ option is specified. This option cannot be\n\ +\ used with -p, -e and -s options.\n\ +\ WARNING: JDK internal APIs are inaccessible. main.opt.depth=\ -\ -depth= Specify the depth of the transitive\n\ -\ dependency analysis +\ -depth= Specify the depth of the transitive\n\ +\ dependency analysis main.opt.q=\ -\ -q -quiet Do not show missing dependencies from -genmoduleinfo output. +\ -q -quiet Do not show missing dependencies from \n\ +\ -genmoduleinfo output. err.unknown.option=unknown option: {0} err.missing.arg=no value given for {0} err.invalid.arg.for.option=invalid argument for option: {0} err.option.after.class=option must be specified before classes: {0} -err.genmoduleinfo.not.jarfile={0} not valid for -genmoduleinfo option (must be JAR file) +err.genmoduleinfo.not.jarfile={0} not valid for -genmoduleinfo option (must be non-modular JAR file) err.profiles.msg=No profile information err.exception.message={0} err.invalid.path=invalid path: {0} -err.invalid.module.option=-m {0} is set but {1} is specified. +err.invalid.module.option=Cannot set {0} with {1} option. err.invalid.filters=Only one of -package (-p), -regex (-e), -requires option can be set err.module.not.found=module not found: {0} -err.root.module.not.set=-m is not set -warn.invalid.arg=Invalid classname or pathname not exist: {0} +err.root.module.not.set=root module set empty +err.invalid.inverse.option={0} cannot be used with -inverse option +err.inverse.filter.not.set={0} cannot be used with -inverse option +warn.invalid.arg=Path not exist: {0} warn.split.package=package {0} defined in {1} {2} warn.replace.useJDKInternals=\ JDK internal APIs are unsupported and private to JDK implementation that are\n\ diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties index 6dd8380024c..1644f11a9c0 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties @@ -1,6 +1,5 @@ -// No translation needed +# No translation needed com.sun.crypto.provider.SunJCE=Use java.security.Security.getProvider(provider-name) @since 1.3 -com.sun.image.codec=Use javax.imageio @since 1.4 com.sun.org.apache.xml.internal.security=Use java.xml.crypto @since 1.6 com.sun.org.apache.xml.internal.security.utils.Base64=Use java.util.Base64 @since 1.8 com.sun.org.apache.xml.internal.resolver=Use javax.xml.catalog @since 9 @@ -9,11 +8,16 @@ com.sun.net.ssl.internal.ssl.Provider=Use java.security.Security.getProvider(pro com.sun.rowset=Use javax.sql.rowset.RowSetProvider @since 1.7 com.sun.tools.javac.tree=Use com.sun.source @since 1.6 com.sun.tools.javac=Use javax.tools and javax.lang.model @since 1.6 -sun.awt.image.codec=Use javax.imageio @since 1.4 -sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8 -sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8 -sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9 -sun.misc.Service=Use java.util.ServiceLoader @since 1.6 +java.awt.peer=Should not use. See https://bugs.openjdk.java.net/browse/JDK-8037739 +java.awt.dnd.peer=Should not use. See https://bugs.openjdk.java.net/browse/JDK-8037739 +jdk.internal.ref.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9 +sun.awt.CausedFocusEvent=Use java.awt.event.FocusEvent::getCause @since 9 +sun.font.FontUtilities=See java.awt.Font.textRequiresLayout @since 9 +sun.reflect.Reflection=Use java.lang.StackWalker @since 9 +sun.reflect.ReflectionFactory=See http://openjdk.java.net/jeps/260 +sun.misc.Unsafe=See http://openjdk.java.net/jeps/260 +sun.misc.Signal=See http://openjdk.java.net/jeps/260 +sun.misc.SignalHandler=See http://openjdk.java.net/jeps/260 sun.security.action=Use java.security.PrivilegedAction @since 1.1 sun.security.krb5=Use com.sun.security.jgss sun.security.provider.PolicyFile=Use java.security.Policy.getInstance("JavaPolicy", new URIParameter(uri)) @since 1.6 @@ -21,5 +25,17 @@ sun.security.provider.Sun=Use java.security.Security.getProvider(provider-name) sun.security.util.SecurityConstants=Use appropriate java.security.Permission subclass @since 1.1 sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4 sun.tools.jar=Use java.util.jar or jar tool @since 1.2 -jdk.internal.ref.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9 +# Internal APIs removed in JDK 9 +com.apple.eawt=Use java.awt.desktop and JEP 272 @since 9 +com.apple.concurrent=Removed. See https://bugs.openjdk.java.net/browse/JDK-8148187 +com.sun.image.codec.jpeg=Use javax.imageio @since 1.4 +sun.awt.image.codec=Use javax.imageio @since 1.4 +sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8 +sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8 +sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9 +sun.misc.Service=Use java.util.ServiceLoader @since 1.6 +sun.misc=Removed. See http://openjdk.java.net/jeps/260 +sun.reflect=Removed. See http://openjdk.java.net/jeps/260 + + diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/debug/InternalDebugControl.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/debug/InternalDebugControl.java index 5a378eb8af3..4f759c7632c 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/debug/InternalDebugControl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/debug/InternalDebugControl.java @@ -23,24 +23,60 @@ package jdk.internal.jshell.debug; +import java.io.PrintStream; import java.util.HashMap; import java.util.Map; import jdk.jshell.JShell; /** - * Used to externally control output messages for debugging the implementation - * of the JShell API. This is NOT a supported interface, - * @author Robert Field +/** + * This class is used to externally control output messages for debugging the + * implementation of the JShell API. + *

    + * This is not part of the SPI, not API. */ public class InternalDebugControl { - public static final int DBG_GEN = 0b0000001; - public static final int DBG_FMGR = 0b0000010; + + /** + * This is a static only class; The constructor should never be called. + */ + private InternalDebugControl() { + } + + /** + * General debugging. + */ + public static final int DBG_GEN = 0b0000001; + + /** + * File manager debuging. + */ + public static final int DBG_FMGR = 0b0000010; + + /** + * Completion analysis debugging. + */ public static final int DBG_COMPA = 0b0000100; - public static final int DBG_DEP = 0b0001000; - public static final int DBG_EVNT = 0b0010000; + + /** + * Dependency debugging. + */ + public static final int DBG_DEP = 0b0001000; + + /** + * Event debugging. + */ + public static final int DBG_EVNT = 0b0010000; private static Map debugMap = null; + /** + * Sets which debug flags are enabled for a given JShell instance. The flags + * are or'ed bits as defined in {@code DBG_*}. + * + * @param state the JShell instance + * @param flags the or'ed debug bits + */ public static void setDebugFlags(JShell state, int flags) { if (debugMap == null) { debugMap = new HashMap<>(); @@ -48,7 +84,14 @@ public class InternalDebugControl { debugMap.put(state, flags); } - public static boolean debugEnabled(JShell state, int flag) { + /** + * Tests if any of the specified debug flags are enabled. + * + * @param state the JShell instance + * @param flag the {@code DBG_*} bits to check + * @return true if any of the flags are enabled + */ + public static boolean isDebugEnabled(JShell state, int flag) { if (debugMap == null) { return false; } @@ -58,4 +101,34 @@ public class InternalDebugControl { } return (flags & flag) != 0; } + + /** + * Displays debug info if the specified debug flags are enabled. + * + * @param state the current JShell instance + * @param err the {@code PrintStream} to report on + * @param flags {@code DBG_*} flag bits to check + * @param format format string for the output + * @param args args for the format string + */ + public static void debug(JShell state, PrintStream err, int flags, String format, Object... args) { + if (isDebugEnabled(state, flags)) { + err.printf(format, args); + } + } + + /** + * Displays a fatal exception as debug info. + * + * @param state the current JShell instance + * @param err the {@code PrintStream} to report on + * @param ex the fatal Exception + * @param where additional context + */ + public static void debug(JShell state, PrintStream err, Exception ex, String where) { + if (isDebugEnabled(state, 0xFFFFFFFF)) { + err.printf("Fatal error: %s: %s\n", where, ex.getMessage()); + ex.printStackTrace(err); + } + } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/ClassTracker.java similarity index 56% rename from langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java rename to langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/ClassTracker.java index 51af9abbc93..40053f166a9 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/ClassTracker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,35 +22,43 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package jdk.internal.jshell.jdi; -package jdk.jshell; - -import java.util.Arrays; import java.util.HashMap; import java.util.Objects; import com.sun.jdi.ReferenceType; +import java.util.List; /** - * Tracks the state of a class through compilation and loading in the remote - * environment. - * - * @author Robert Field + * Tracks the state of a class. */ class ClassTracker { - private final JShell state; + private final JDIEnv jdiEnv; private final HashMap map; - ClassTracker(JShell state) { - this.state = state; + ClassTracker(JDIEnv jdiEnv) { + this.jdiEnv = jdiEnv; this.map = new HashMap<>(); } + /** + * Associates a class name, class bytes, and ReferenceType. + */ class ClassInfo { + // The name of the class -- always set private final String className; + + // The corresponding compiled class bytes when a load or redefine + // is started. May not be the loaded bytes. May be null. private byte[] bytes; + + // The class bytes successfully loaded/redefined into the remote VM. private byte[] loadedBytes; + + // The corresponding JDI ReferenceType. Used by redefineClasses and + // acts as indicator of successful load (null if not loaded). private ReferenceType rt; private ClassInfo(String className) { @@ -61,33 +69,44 @@ class ClassTracker { return className; } + byte[] getLoadedBytes() { + return loadedBytes; + } + byte[] getBytes() { return bytes; } - void setBytes(byte[] bytes) { - this.bytes = bytes; + private void setBytes(byte[] potentialBytes) { + this.bytes = potentialBytes; } - void setLoaded() { + // The class has been successful loaded redefined. The class bytes + // sent are now actually loaded. + void markLoaded() { loadedBytes = bytes; } - boolean isLoaded() { - return Arrays.equals(loadedBytes, bytes); - } - + // Ask JDI for the ReferenceType, null if not loaded. ReferenceType getReferenceTypeOrNull() { if (rt == null) { - rt = state.executionControl().nameToRef(className); + rt = nameToRef(className); } return rt; } + private ReferenceType nameToRef(String name) { + List rtl = jdiEnv.vm().classesByName(name); + if (rtl.size() != 1) { + return null; + } + return rtl.get(0); + } + @Override public boolean equals(Object o) { - return o instanceof ClassInfo && - ((ClassInfo) o).className.equals(className); + return o instanceof ClassInfo + && ((ClassInfo) o).className.equals(className); } @Override @@ -96,13 +115,15 @@ class ClassTracker { } } + // Map a class name to the current compiled class bytes. ClassInfo classInfo(String className, byte[] bytes) { - ClassInfo ci = map.computeIfAbsent(className, k -> new ClassInfo(k)); + ClassInfo ci = get(className); ci.setBytes(bytes); return ci; } + // Lookup the ClassInfo by class name, create if it does not exist. ClassInfo get(String className) { - return map.get(className); + return map.computeIfAbsent(className, k -> new ClassInfo(k)); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIConnection.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIConnection.java similarity index 88% rename from langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIConnection.java rename to langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIConnection.java index 56cf4d95f9d..c50fd621854 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIConnection.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ */ -package jdk.jshell; +package jdk.internal.jshell.jdi; import com.sun.jdi.*; import com.sun.jdi.connect.*; @@ -40,7 +40,6 @@ import com.sun.jdi.connect.*; import java.util.*; import java.util.Map.Entry; import java.io.*; - import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; /** @@ -51,11 +50,11 @@ import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; class JDIConnection { private VirtualMachine vm; + private boolean active = true; private Process process = null; private int outputCompleteCount = 0; - private final JShell proc; - private final JDIEnv env; + private final JDIExecutionControl ec; private final Connector connector; private final Map connectorArgs; private final int traceFlags; @@ -103,9 +102,9 @@ class JDIConnection { return arguments; } - JDIConnection(JDIEnv env, String connectorName, Map argumentName2Value, int traceFlags, JShell proc) { - this.env = env; - this.proc = proc; + + JDIConnection(JDIExecutionControl ec, String connectorName, Map argumentName2Value, int traceFlags) { + this.ec = ec; this.connector = findConnector(connectorName); if (connector == null) { @@ -177,6 +176,11 @@ class JDIConnection { return process != null && process.isAlive(); } + // Beginning shutdown, ignore any random dying squeals + void beginShutdown() { + active = false; + } + public synchronized void disposeVM() { try { if (vm != null) { @@ -235,14 +239,19 @@ class JDIConnection { int i; try { while ((i = in.read()) != -1) { - pStream.print((char) i); + // directly copy input to output, but skip if asked to close + if (active) { + pStream.print((char) i); + } } } catch (IOException ex) { String s = ex.getMessage(); - if (!s.startsWith("Bad file number")) { + if (active && !s.startsWith("Bad file number")) { throw ex; } - // else we got a Bad file number IOException which just means + // else we are being shutdown (and don't want any spurious death + // throws to ripple) or + // we got a Bad file number IOException which just means // that the debuggee has gone away. We'll just treat it the // same as if we got an EOF. } @@ -260,8 +269,8 @@ class JDIConnection { try { dumpStream(inStream, pStream); } catch (IOException ex) { - proc.debug(ex, "Failed reading output"); - env.shutdown(); + ec.debug(ex, "Failed reading output"); + ec.jdiEnv.shutdown(); } finally { notifyOutputComplete(); } @@ -287,8 +296,8 @@ class JDIConnection { outStream.flush(); } } catch (IOException ex) { - proc.debug(ex, "Failed reading output"); - env.shutdown(); + ec.debug(ex, "Failed reading output"); + ec.jdiEnv.shutdown(); } } }; @@ -302,9 +311,9 @@ class JDIConnection { try { VirtualMachine new_vm = launcher.launch(connectorArgs); process = new_vm.process(); - displayRemoteOutput(process.getErrorStream(), proc.err); - displayRemoteOutput(process.getInputStream(), proc.out); - readRemoteInput(process.getOutputStream(), proc.in); + displayRemoteOutput(process.getErrorStream(), ec.execEnv.userErr()); + displayRemoteOutput(process.getInputStream(), ec.execEnv.userOut()); + readRemoteInput(process.getOutputStream(), ec.execEnv.userIn()); return new_vm; } catch (Exception ex) { reportLaunchFail(ex, "launch"); @@ -330,7 +339,7 @@ class JDIConnection { ListeningConnector listener = (ListeningConnector)connector; try { String retAddress = listener.startListening(connectorArgs); - proc.debug(DBG_GEN, "Listening at address: " + retAddress); + ec.debug(DBG_GEN, "Listening at address: " + retAddress); vm = listener.accept(connectorArgs); listener.stopListening(connectorArgs); return vm; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEnv.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIEnv.java similarity index 83% rename from langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEnv.java rename to langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIEnv.java index e280ade958a..16e6229c8f7 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEnv.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIEnv.java @@ -23,7 +23,7 @@ * questions. */ -package jdk.jshell; +package jdk.internal.jshell.jdi; import java.util.Map; @@ -37,14 +37,14 @@ import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; class JDIEnv { private JDIConnection connection; - private final JShell state; + private final JDIExecutionControl ec; - JDIEnv(JShell state) { - this.state = state; + JDIEnv(JDIExecutionControl ec) { + this.ec = ec; } void init(String connectorName, Map argumentName2Value, boolean openNow, int flags) { - connection = new JDIConnection(this, connectorName, argumentName2Value, flags, state); + connection = new JDIConnection(ec, connectorName, argumentName2Value, flags); if (!connection.isLaunch() || openNow) { connection.open(); } @@ -66,14 +66,14 @@ class JDIEnv { // Shutting down after the VM has gone away. This is // not an error, and we just ignore it. } catch (Throwable e) { - state.debug(DBG_GEN, null, "disposeVM threw: " + e); + ec.debug(DBG_GEN, null, "disposeVM threw: " + e); } } - if (state != null) { // If state has been set-up + if (ec.execEnv.state() != null) { // If state has been set-up try { - state.closeDown(); + ec.execEnv.closeDown(); } catch (Throwable e) { - state.debug(DBG_GEN, null, "state().closeDown() threw: " + e); + ec.debug(DBG_GEN, null, "state().closeDown() threw: " + e); } } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEventHandler.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIEventHandler.java similarity index 99% rename from langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEventHandler.java rename to langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIEventHandler.java index fc18b1e4e81..7c1bf9e1a55 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEventHandler.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIEventHandler.java @@ -23,7 +23,7 @@ * questions. */ -package jdk.jshell; +package jdk.internal.jshell.jdi; import com.sun.jdi.*; import com.sun.jdi.event.*; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIExecutionControl.java new file mode 100644 index 00000000000..d023ce81b34 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIExecutionControl.java @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2014, 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. + */ + +package jdk.internal.jshell.jdi; + +import static jdk.internal.jshell.remote.RemoteCodes.*; +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintStream; +import java.net.ServerSocket; +import java.net.Socket; +import com.sun.jdi.*; +import java.io.EOFException; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import static java.util.stream.Collectors.toList; +import jdk.jshell.JShellException; +import jdk.jshell.spi.ExecutionControl; +import jdk.jshell.spi.ExecutionEnv; +import jdk.internal.jshell.jdi.ClassTracker.ClassInfo; +import static java.util.stream.Collectors.toMap; +import jdk.internal.jshell.debug.InternalDebugControl; +import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; + +/** + * Controls the remote execution environment. + * Interfaces to the JShell-core by implementing ExecutionControl SPI. + * Interfaces to RemoteAgent over a socket and via JDI. + * Launches a remote process. + */ +public class JDIExecutionControl implements ExecutionControl { + + ExecutionEnv execEnv; + JDIEnv jdiEnv; + private ClassTracker tracker; + private JDIEventHandler handler; + private Socket socket; + private ObjectInputStream remoteIn; + private ObjectOutputStream remoteOut; + private String remoteVMOptions; + + /** + * Initializes the launching JDI execution engine. Initialize JDI and use it + * to launch the remote JVM. Set-up control and result communications socket + * to the remote execution environment. This socket also transports the + * input/output channels. + * + * @param execEnv the execution environment provided by the JShell-core + * @throws IOException + */ + @Override + public void start(ExecutionEnv execEnv) throws IOException { + this.execEnv = execEnv; + this.jdiEnv = new JDIEnv(this); + this.tracker = new ClassTracker(jdiEnv); + StringBuilder sb = new StringBuilder(); + execEnv.extraRemoteVMOptions().stream() + .forEach(s -> { + sb.append(" "); + sb.append(s); + }); + this.remoteVMOptions = sb.toString(); + try (ServerSocket listener = new ServerSocket(0)) { + // timeout after 60 seconds + listener.setSoTimeout(60000); + int port = listener.getLocalPort(); + jdiGo(port); + this.socket = listener.accept(); + // out before in -- match remote creation so we don't hang + this.remoteOut = new ObjectOutputStream(socket.getOutputStream()); + PipeInputStream commandIn = new PipeInputStream(); + new DemultiplexInput(socket.getInputStream(), commandIn, execEnv.userOut(), execEnv.userErr()).start(); + this.remoteIn = new ObjectInputStream(commandIn); + } + } + + /** + * Closes the execution engine. Send an exit command to the remote agent. + * Shuts down the JDI connection. Should this close the socket? + */ + @Override + public void close() { + try { + JDIConnection c = jdiEnv.connection(); + if (c != null) { + c.beginShutdown(); + } + if (remoteOut != null) { + remoteOut.writeInt(CMD_EXIT); + remoteOut.flush(); + } + if (c != null) { + c.disposeVM(); + } + } catch (IOException ex) { + debug(DBG_GEN, "Exception on JDI exit: %s\n", ex); + } + } + + /** + * Loads the list of classes specified. Sends a load command to the remote + * agent with pairs of classname/bytes. + * + * @param classes the names of the wrapper classes to loaded + * @return true if all classes loaded successfully + */ + @Override + public boolean load(Collection classes) { + try { + // Create corresponding ClassInfo instances to track the classes. + // Each ClassInfo has the current class bytes associated with it. + List infos = withBytes(classes); + // Send a load command to the remote agent. + remoteOut.writeInt(CMD_LOAD); + remoteOut.writeInt(classes.size()); + for (ClassInfo ci : infos) { + remoteOut.writeUTF(ci.getClassName()); + remoteOut.writeObject(ci.getBytes()); + } + remoteOut.flush(); + // Retrieve and report results from the remote agent. + boolean result = readAndReportResult(); + // For each class that now has a JDI ReferenceType, mark the bytes + // as loaded. + infos.stream() + .filter(ci -> ci.getReferenceTypeOrNull() != null) + .forEach(ci -> ci.markLoaded()); + return result; + } catch (IOException ex) { + debug(DBG_GEN, "IOException on remote load operation: %s\n", ex); + return false; + } + } + + /** + * Invoke the doit method on the specified class. + * + * @param classname name of the wrapper class whose doit should be invoked + * @return return the result value of the doit + * @throws JShellException if a user exception was thrown (EvalException) or + * an unresolved reference was encountered (UnresolvedReferenceException) + */ + @Override + public String invoke(String classname, String methodname) throws JShellException { + try { + synchronized (STOP_LOCK) { + userCodeRunning = true; + } + // Send the invoke command to the remote agent. + remoteOut.writeInt(CMD_INVOKE); + remoteOut.writeUTF(classname); + remoteOut.writeUTF(methodname); + remoteOut.flush(); + // Retrieve and report results from the remote agent. + if (readAndReportExecutionResult()) { + String result = remoteIn.readUTF(); + return result; + } + } catch (IOException | RuntimeException ex) { + if (!jdiEnv.connection().isRunning()) { + // The JDI connection is no longer live, shutdown. + jdiEnv.shutdown(); + } else { + debug(DBG_GEN, "Exception on remote invoke: %s\n", ex); + return "Execution failure: " + ex.getMessage(); + } + } finally { + synchronized (STOP_LOCK) { + userCodeRunning = false; + } + } + return ""; + } + + /** + * Retrieves the value of a JShell variable. + * + * @param classname name of the wrapper class holding the variable + * @param varname name of the variable + * @return the value as a String + */ + @Override + public String varValue(String classname, String varname) { + try { + // Send the variable-value command to the remote agent. + remoteOut.writeInt(CMD_VARVALUE); + remoteOut.writeUTF(classname); + remoteOut.writeUTF(varname); + remoteOut.flush(); + // Retrieve and report results from the remote agent. + if (readAndReportResult()) { + String result = remoteIn.readUTF(); + return result; + } + } catch (EOFException ex) { + jdiEnv.shutdown(); + } catch (IOException ex) { + debug(DBG_GEN, "Exception on remote var value: %s\n", ex); + return "Execution failure: " + ex.getMessage(); + } + return ""; + } + + /** + * Adds a path to the remote classpath. + * + * @param cp the additional path element + * @return true if succesful + */ + @Override + public boolean addToClasspath(String cp) { + try { + // Send the classpath addition command to the remote agent. + remoteOut.writeInt(CMD_CLASSPATH); + remoteOut.writeUTF(cp); + remoteOut.flush(); + // Retrieve and report results from the remote agent. + return readAndReportResult(); + } catch (IOException ex) { + throw new InternalError("Classpath addition failed: " + cp, ex); + } + } + + /** + * Redefine the specified classes. Where 'redefine' is, as in JDI and JVMTI, + * an in-place replacement of the classes (preserving class identity) -- + * that is, existing references to the class do not need to be recompiled. + * This implementation uses JDI redefineClasses. It will be unsuccessful if + * the signature of the class has changed (see the JDI spec). The + * JShell-core is designed to adapt to unsuccessful redefine. + * + * @param classes the names of the classes to redefine + * @return true if all the classes were redefined + */ + @Override + public boolean redefine(Collection classes) { + try { + // Create corresponding ClassInfo instances to track the classes. + // Each ClassInfo has the current class bytes associated with it. + List infos = withBytes(classes); + // Convert to the JDI ReferenceType to class bytes map form needed + // by JDI. + Map rmp = infos.stream() + .collect(toMap( + ci -> ci.getReferenceTypeOrNull(), + ci -> ci.getBytes())); + // Attempt redefine. Throws exceptions on failure. + jdiEnv.vm().redefineClasses(rmp); + // Successful: mark the bytes as loaded. + infos.stream() + .forEach(ci -> ci.markLoaded()); + return true; + } catch (UnsupportedOperationException ex) { + // A form of class transformation not supported by JDI + return false; + } catch (Exception ex) { + debug(DBG_GEN, "Exception on JDI redefine: %s\n", ex); + return false; + } + } + + /** + * Converts a collection of class names into ClassInfo instances associated + * with the most recently compiled class bytes. + * + * @param classes names of the classes + * @return a list of corresponding ClassInfo instances + */ + private List withBytes(Collection classes) { + return classes.stream() + .map(cn -> tracker.classInfo(cn, execEnv.getClassBytes(cn))) + .collect(toList()); + } + + /** + * Reports the status of the named class. UNKNOWN if not loaded. CURRENT if + * the most recent successfully loaded/redefined bytes match the current + * compiled bytes. + * + * @param classname the name of the class to test + * @return the status + */ + @Override + public ClassStatus getClassStatus(String classname) { + ClassInfo ci = tracker.get(classname); + if (ci.getReferenceTypeOrNull() == null) { + // If the class does not have a JDI ReferenceType it has not been loaded + return ClassStatus.UNKNOWN; + } + // Compare successfully loaded with last compiled bytes. + return (Arrays.equals(execEnv.getClassBytes(classname), ci.getLoadedBytes())) + ? ClassStatus.CURRENT + : ClassStatus.NOT_CURRENT; + } + + /** + * Reports results from a remote agent command that does not expect + * exceptions. + * + * @return true if successful + * @throws IOException if the connection has dropped + */ + private boolean readAndReportResult() throws IOException { + int ok = remoteIn.readInt(); + switch (ok) { + case RESULT_SUCCESS: + return true; + case RESULT_FAIL: { + String ex = remoteIn.readUTF(); + debug(DBG_GEN, "Exception on remote operation: %s\n", ex); + return false; + } + default: { + debug(DBG_GEN, "Bad remote result code: %s\n", ok); + return false; + } + } + } + + /** + * Reports results from a remote agent command that expects runtime + * exceptions. + * + * @return true if successful + * @throws IOException if the connection has dropped + * @throws EvalException if a user exception was encountered on invoke + * @throws UnresolvedReferenceException if an unresolved reference was + * encountered + */ + private boolean readAndReportExecutionResult() throws IOException, JShellException { + int ok = remoteIn.readInt(); + switch (ok) { + case RESULT_SUCCESS: + return true; + case RESULT_FAIL: { + // An internal error has occurred. + String ex = remoteIn.readUTF(); + return false; + } + case RESULT_EXCEPTION: { + // A user exception was encountered. + String exceptionClassName = remoteIn.readUTF(); + String message = remoteIn.readUTF(); + StackTraceElement[] elems = readStackTrace(); + throw execEnv.createEvalException(message, exceptionClassName, elems); + } + case RESULT_CORRALLED: { + // An unresolved reference was encountered. + int id = remoteIn.readInt(); + StackTraceElement[] elems = readStackTrace(); + throw execEnv.createUnresolvedReferenceException(id, elems); + } + case RESULT_KILLED: { + // Execution was aborted by the stop() + debug(DBG_GEN, "Killed."); + return false; + } + default: { + debug(DBG_GEN, "Bad remote result code: %s\n", ok); + return false; + } + } + } + + private StackTraceElement[] readStackTrace() throws IOException { + int elemCount = remoteIn.readInt(); + StackTraceElement[] elems = new StackTraceElement[elemCount]; + for (int i = 0; i < elemCount; ++i) { + String className = remoteIn.readUTF(); + String methodName = remoteIn.readUTF(); + String fileName = remoteIn.readUTF(); + int line = remoteIn.readInt(); + elems[i] = new StackTraceElement(className, methodName, fileName, line); + } + return elems; + } + + /** + * Launch the remote agent as a JDI connection. + * + * @param port the socket port for (non-JDI) commands + */ + private void jdiGo(int port) { + //MessageOutput.textResources = ResourceBundle.getBundle("impl.TTYResources", + // Locale.getDefault()); + + // Set-up for a fresh launch of a remote agent with any user-specified VM options. + String connectorName = "com.sun.jdi.CommandLineLaunch"; + Map argumentName2Value = new HashMap<>(); + argumentName2Value.put("main", "jdk.internal.jshell.remote.RemoteAgent " + port); + argumentName2Value.put("options", remoteVMOptions); + + boolean launchImmediately = true; + int traceFlags = 0;// VirtualMachine.TRACE_SENDS | VirtualMachine.TRACE_EVENTS; + + // Launch. + jdiEnv.init(connectorName, argumentName2Value, launchImmediately, traceFlags); + + if (jdiEnv.connection().isOpen() && jdiEnv.vm().canBeModified()) { + /* + * Connection opened on startup. Start event handler + * immediately, telling it (through arg 2) to stop on the + * VM start event. + */ + handler = new JDIEventHandler(jdiEnv); + } + } + + private final Object STOP_LOCK = new Object(); + private boolean userCodeRunning = false; + + /** + * Interrupt a running invoke. + */ + @Override + public void stop() { + synchronized (STOP_LOCK) { + if (!userCodeRunning) { + return; + } + + VirtualMachine vm = handler.env.vm(); + vm.suspend(); + try { + OUTER: + for (ThreadReference thread : vm.allThreads()) { + // could also tag the thread (e.g. using name), to find it easier + for (StackFrame frame : thread.frames()) { + String remoteAgentName = "jdk.internal.jshell.remote.RemoteAgent"; + if (remoteAgentName.equals(frame.location().declaringType().name()) + && "commandLoop".equals(frame.location().method().name())) { + ObjectReference thiz = frame.thisObject(); + if (((BooleanValue) thiz.getValue(thiz.referenceType().fieldByName("inClientCode"))).value()) { + thiz.setValue(thiz.referenceType().fieldByName("expectingStop"), vm.mirrorOf(true)); + ObjectReference stopInstance = (ObjectReference) thiz.getValue(thiz.referenceType().fieldByName("stopException")); + + vm.resume(); + debug(DBG_GEN, "Attempting to stop the client code...\n"); + thread.stop(stopInstance); + thiz.setValue(thiz.referenceType().fieldByName("expectingStop"), vm.mirrorOf(false)); + } + + break OUTER; + } + } + } + } catch (ClassNotLoadedException | IncompatibleThreadStateException | InvalidTypeException ex) { + debug(DBG_GEN, "Exception on remote stop: %s\n", ex); + } finally { + vm.resume(); + } + } + } + + void debug(int flags, String format, Object... args) { + InternalDebugControl.debug(execEnv.state(), execEnv.userErr(), flags, format, args); + } + + void debug(Exception ex, String where) { + InternalDebugControl.debug(execEnv.state(), execEnv.userErr(), ex, where); + } + + private final class DemultiplexInput extends Thread { + + private final DataInputStream delegate; + private final PipeInputStream command; + private final PrintStream out; + private final PrintStream err; + + public DemultiplexInput(InputStream input, + PipeInputStream command, + PrintStream out, + PrintStream err) { + super("output reader"); + this.delegate = new DataInputStream(input); + this.command = command; + this.out = out; + this.err = err; + } + + public void run() { + try { + while (true) { + int nameLen = delegate.read(); + if (nameLen == (-1)) + break; + byte[] name = new byte[nameLen]; + DemultiplexInput.this.delegate.readFully(name); + int dataLen = delegate.read(); + byte[] data = new byte[dataLen]; + DemultiplexInput.this.delegate.readFully(data); + switch (new String(name, "UTF-8")) { + case "err": + err.write(data); + break; + case "out": + out.write(data); + break; + case "command": + for (byte b : data) { + command.write(Byte.toUnsignedInt(b)); + } + break; + } + } + } catch (IOException ex) { + debug(ex, "Failed reading output"); + } finally { + command.close(); + } + } + + } + + public static final class PipeInputStream extends InputStream { + public static final int INITIAL_SIZE = 128; + + private int[] buffer = new int[INITIAL_SIZE]; + private int start; + private int end; + private boolean closed; + + @Override + public synchronized int read() { + while (start == end) { + if (closed) { + return -1; + } + try { + wait(); + } catch (InterruptedException ex) { + //ignore + } + } + try { + return buffer[start]; + } finally { + start = (start + 1) % buffer.length; + } + } + + public synchronized void write(int b) { + if (closed) + throw new IllegalStateException("Already closed."); + int newEnd = (end + 1) % buffer.length; + if (newEnd == start) { + //overflow: + int[] newBuffer = new int[buffer.length * 2]; + int rightPart = (end > start ? end : buffer.length) - start; + int leftPart = end > start ? 0 : start - 1; + System.arraycopy(buffer, start, newBuffer, 0, rightPart); + System.arraycopy(buffer, 0, newBuffer, rightPart, leftPart); + buffer = newBuffer; + start = 0; + end = rightPart + leftPart; + newEnd = end + 1; + } + buffer[end] = b; + end = newEnd; + notifyAll(); + } + + @Override + public synchronized void close() { + closed = true; + notifyAll(); + } + + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDINotConnectedException.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDINotConnectedException.java similarity index 97% rename from langtools/src/jdk.jshell/share/classes/jdk/jshell/JDINotConnectedException.java rename to langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDINotConnectedException.java index 2b9407c2114..ac22d094559 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDINotConnectedException.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDINotConnectedException.java @@ -23,7 +23,7 @@ * questions. */ -package jdk.jshell; +package jdk.internal.jshell.jdi; /** * Internal exception when Java Debug Interface VirtualMacine is not connected. diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java index 83d6419f86a..25c1d9be1b4 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java @@ -24,6 +24,7 @@ */ package jdk.internal.jshell.remote; +import jdk.jshell.spi.SPIResolutionException; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; @@ -111,10 +112,11 @@ class RemoteAgent { out.flush(); break; } + String methodName = in.readUTF(); Method doitMethod; try { - this.getClass().getModule().addExports(RemoteResolutionException.class.getPackage().getName(), klass.getModule()); - doitMethod = klass.getDeclaredMethod(DOIT_METHOD_NAME, new Class[0]); + this.getClass().getModule().addExports(SPIResolutionException.class.getPackage().getName(), klass.getModule()); + doitMethod = klass.getDeclaredMethod(methodName, new Class[0]); doitMethod.setAccessible(true); Object res; try { @@ -138,9 +140,9 @@ class RemoteAgent { } catch (InvocationTargetException ex) { Throwable cause = ex.getCause(); StackTraceElement[] elems = cause.getStackTrace(); - if (cause instanceof RemoteResolutionException) { + if (cause instanceof SPIResolutionException) { out.writeInt(RESULT_CORRALLED); - out.writeInt(((RemoteResolutionException) cause).id); + out.writeInt(((SPIResolutionException) cause).id()); } else { out.writeInt(RESULT_EXCEPTION); out.writeUTF(cause.getClass().getName()); @@ -254,27 +256,14 @@ class RemoteAgent { if (value == null) { return "null"; } else if (value instanceof String) { - return "\"" + expunge((String)value) + "\""; + return "\"" + (String)value + "\""; } else if (value instanceof Character) { return "'" + value + "'"; } else { - return expunge(value.toString()); + return value.toString(); } } - /** - * Expunge internal info from string - * @param s string to process - * @return string the display, JShell package and wrapper class names removed - */ - static String expunge(String s) { - StringBuilder sb = new StringBuilder(); - for (String comp : PREFIX_PATTERN.split(s)) { - sb.append(comp); - } - return sb.toString(); - } - private static final class MultiplexingOutputStream extends OutputStream { private static final int PACKET_SIZE = 127; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java index e8deae7e73c..ee71a632b02 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java @@ -25,8 +25,6 @@ package jdk.internal.jshell.remote; -import java.util.regex.Pattern; - /** * Communication constants shared between the main process and the remote * execution process @@ -46,13 +44,4 @@ public class RemoteCodes { public static final int RESULT_EXCEPTION = 102; public static final int RESULT_CORRALLED = 103; public static final int RESULT_KILLED = 104; - - // String constants - public static final String REPL_PACKAGE = "REPL"; - public static final String REPL_CLASS_PREFIX = "$JShell$"; - public static final String DOIT_METHOD_NAME = "do_it$"; - public static final Pattern PREFIX_PATTERN = Pattern.compile( - "(" + REPL_PACKAGE + "\\.)?" + - "(?" + Pattern.quote(REPL_CLASS_PREFIX) + - "\\w+" + ")" + "[\\$\\.]?"); } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java index a7105cf1dc8..8334d78a7f5 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java @@ -25,8 +25,13 @@ package jdk.internal.jshell.tool; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Stream; +import static java.util.stream.Collectors.toList; /** * Parse command arguments, derived from StreamTokenizer by @@ -49,13 +54,12 @@ class ArgTokenizer { private String sval; private boolean isQuoted = false; - ArgTokenizer(String arg) { - this("", arg); - } + private final Map options = new HashMap<>(); + private final List badOptions = new ArrayList<>(); ArgTokenizer(String prefix, String arg) { this.str = arg; - this.prefix = prefix; + this.prefix = prefix + " "; this.length = arg.length(); quoteChar('"'); quoteChar('\''); @@ -65,17 +69,47 @@ class ArgTokenizer { whitespaceChars(0xA0, 0xA0); } + /** + * Return the next non-option argument. Encountered options are stored. + * + * @return the token string, or null if there are no more tokens + */ String next() { - nextToken(); + while (true) { + nextToken(); + if (sval != null && !isQuoted() && sval.startsWith("-")) { + foundOption(sval); + } else { + break; + } + } return sval; } + private void foundOption(String opt) { + if (options.containsKey(opt)) { + options.put(opt, true); + return; + } + + List> matches = + options.entrySet() + .stream() + .filter(e -> e.getKey().startsWith(opt)) + .collect(toList()); + if (matches.size() == 1) { + matches.get(0).setValue(true); + } else { + badOptions.add(opt); + } + } + String[] next(String... strings) { return next(Arrays.stream(strings)); } String[] next(Stream stream) { - nextToken(); + next(); if (sval == null) { return null; } @@ -85,6 +119,68 @@ class ArgTokenizer { return matches; } + /** + * Set the allowed options. Must be called before any options would be read + * and before calling any of the option functionality below. + */ + void allowedOptions(String... opts) { + for (String opt : opts) { + options.put(opt, false); + } + } + + /** + * Has the specified option been encountered. + * + * @param opt the option to check + * @return true if the option has been encountered + */ + boolean hasOption(String opt) { + Boolean has = options.get(opt); + if (has == null) { + throw new InternalError("hasOption called before allowedOptions or on bad option"); + } + return has; + } + + /** + * Return the number of encountered options + * + * @return the option count + */ + int optionCount() { + return (int) options.entrySet().stream() + .filter(e -> e.getValue()) + .count(); + } + + /** + * Return the bad options encountered. Bad options are those that were not + * listed in the call to allowedOptions(). + * + * @return as space-separated list the bad options encountered, or the empty + * string if none. + */ + String badOptions() { + return String.join(" ", badOptions); + } + + /** + * Consume the remainder of the input. This is useful to sure all options + * have been encountered and to check to unexpected additional non-option + * input. + * + * @return the string-separated concatenation of all remaining non-option + * arguments. + */ + String remainder() { + List rem = new ArrayList<>(); + while (next() != null) { + rem.add(sval); + } + return String.join(" ", rem); + } + String val() { return sval; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java index 8b8c6ddf0b7..4f1cc573d71 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package jdk.internal.jshell.tool; -import jdk.jshell.SourceCodeAnalysis.CompletionInfo; import jdk.jshell.SourceCodeAnalysis.QualifiedNames; import jdk.jshell.SourceCodeAnalysis.Suggestion; @@ -36,6 +35,7 @@ import java.io.PrintStream; import java.io.UncheckedIOException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -44,6 +44,9 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; +import java.util.prefs.BackingStoreException; +import java.util.stream.Collectors; +import java.util.stream.Stream; import jdk.internal.jline.NoInterruptUnixTerminal; import jdk.internal.jline.Terminal; @@ -54,10 +57,13 @@ import jdk.internal.jline.console.ConsoleReader; import jdk.internal.jline.console.KeyMap; import jdk.internal.jline.console.UserInterruptException; import jdk.internal.jline.console.completer.Completer; +import jdk.internal.jline.extra.EditingHistory; import jdk.internal.jshell.tool.StopDetectingInputStream.State; class ConsoleIOContext extends IOContext { + private static final String HISTORY_LINE_PREFIX = "HISTORY_LINE_"; + final JShellTool repl; final StopDetectingInputStream input; final ConsoleReader in; @@ -80,12 +86,18 @@ class ConsoleIOContext extends IOContext { in = new ConsoleReader(cmdin, cmdout, term); in.setExpandEvents(false); in.setHandleUserInterrupt(true); - in.setHistory(history = new EditingHistory(repl.prefs) { - @Override protected CompletionInfo analyzeCompletion(String input) { - return repl.analysis.analyzeCompletion(input); + List persistenHistory = Stream.of(repl.prefs.keys()) + .filter(key -> key.startsWith(HISTORY_LINE_PREFIX)) + .sorted() + .map(key -> repl.prefs.get(key, null)) + .collect(Collectors.toList()); + in.setHistory(history = new EditingHistory(in, persistenHistory) { + @Override protected boolean isComplete(CharSequence input) { + return repl.analysis.analyzeCompletion(input.toString()).completeness.isComplete; } }); in.setBellEnabled(true); + in.setCopyPasteDetection(true); in.addCompleter(new Completer() { private String lastTest; private int lastCursor; @@ -150,8 +162,6 @@ class ConsoleIOContext extends IOContext { } }); bind(DOCUMENTATION_SHORTCUT, (ActionListener) evt -> documentation(repl)); - bind(CTRL_UP, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::previousSnippet)); - bind(CTRL_DOWN, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::nextSnippet)); for (FixComputer computer : FIX_COMPUTERS) { for (String shortcuts : SHORTCUT_FIXES) { bind(shortcuts + computer.shortcut, (ActionListener) evt -> fixes(computer)); @@ -181,7 +191,24 @@ class ConsoleIOContext extends IOContext { @Override public void close() throws IOException { - history.save(); + //save history: + try { + for (String key : repl.prefs.keys()) { + if (key.startsWith(HISTORY_LINE_PREFIX)) + repl.prefs.remove(key); + } + Collection savedHistory = history.save(); + if (!savedHistory.isEmpty()) { + int len = (int) Math.ceil(Math.log10(savedHistory.size()+1)); + String format = HISTORY_LINE_PREFIX + "%0" + len + "d"; + int index = 0; + for (String historyLine : savedHistory) { + repl.prefs.put(String.format(format, index++), historyLine); + } + } + } catch (BackingStoreException ex) { + throw new IllegalStateException(ex); + } in.shutdown(); try { in.getTerminal().restore(); @@ -190,30 +217,6 @@ class ConsoleIOContext extends IOContext { } } - private void moveHistoryToSnippet(Supplier action) { - if (!action.get()) { - try { - in.beep(); - } catch (IOException ex) { - throw new IllegalStateException(ex); - } - } else { - try { - //could use: - //in.resetPromptLine(in.getPrompt(), in.getHistory().current().toString(), -1); - //but that would mean more re-writing on the screen, (and prints an additional - //empty line), so using setBuffer directly: - Method setBuffer = in.getClass().getDeclaredMethod("setBuffer", String.class); - - setBuffer.setAccessible(true); - setBuffer.invoke(in, in.getHistory().current().toString()); - in.flush(); - } catch (ReflectiveOperationException | IOException ex) { - throw new IllegalStateException(ex); - } - } - } - private void bind(String shortcut, Object action) { KeyMap km = in.getKeys(); for (int i = 0; i < shortcut.length(); i++) { @@ -227,8 +230,6 @@ class ConsoleIOContext extends IOContext { } private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB - private static final String CTRL_UP = "\033\133\061\073\065\101"; //Ctrl-UP - private static final String CTRL_DOWN = "\033\133\061\073\065\102"; //Ctrl-DOWN private static final String[] SHORTCUT_FIXES = { "\033\015", //Alt-Enter (Linux) "\033\133\061\067\176", //F6/Alt-F1 (Mac) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java index 21ac481bd1e..eedceff6fb2 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java @@ -30,9 +30,11 @@ import java.util.Arrays; import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.util.stream.Collectors.joining; @@ -47,12 +49,24 @@ class Feedback { // Patern for substituted fields within a customized format string private static final Pattern FIELD_PATTERN = Pattern.compile("\\{(.*?)\\}"); - // Current mode - private Mode mode = new Mode("", false); // initial value placeholder during start-up + // Internal field name for truncation length + private static final String TRUNCATION_FIELD = ""; - // Mapping of mode names to mode modes + // For encoding to Properties String + private static final String RECORD_SEPARATOR = "\u241E"; + + // Current mode -- initial value is placeholder during start-up + private Mode mode = new Mode(""); + + // Retained current mode -- for checks + private Mode retainedCurrentMode = null; + + // Mapping of mode name to mode private final Map modeMap = new HashMap<>(); + // Mapping of mode names to encoded retained mode + private final Map retainedMap = new HashMap<>(); + // Mapping selector enum names to enums private final Map> selectorMap = new HashMap<>(); @@ -103,14 +117,35 @@ class Feedback { return new Setter(messageHandler, at).setFormat(); } - public boolean setNewMode(MessageHandler messageHandler, ArgTokenizer at) { - return new Setter(messageHandler, at).setNewMode(); + public boolean setTruncation(MessageHandler messageHandler, ArgTokenizer at) { + return new Setter(messageHandler, at).setTruncation(); + } + + public boolean setMode(MessageHandler messageHandler, ArgTokenizer at) { + return new Setter(messageHandler, at).setMode(); } public boolean setPrompt(MessageHandler messageHandler, ArgTokenizer at) { return new Setter(messageHandler, at).setPrompt(); } + public String retainFeedback(MessageHandler messageHandler, ArgTokenizer at) { + return new Setter(messageHandler, at).retainFeedback(); + } + + public String retainMode(MessageHandler messageHandler, ArgTokenizer at) { + return new Setter(messageHandler, at).retainMode(); + } + + public boolean restoreEncodedModes(MessageHandler messageHandler, String encoded) { + return new Setter(messageHandler, new ArgTokenizer("", "")).restoreEncodedModes(encoded); + } + + public void markModesReadOnly() { + modeMap.values().stream() + .forEach(m -> m.readOnly = true); + } + { for (FormatCase e : EnumSet.allOf(FormatCase.class)) selectorMap.put(e.name().toLowerCase(Locale.US), e); @@ -135,11 +170,13 @@ class Feedback { final String name; // Display command verification/information - final boolean commandFluff; + boolean commandFluff; // Event cases: class, method, expression, ... final Map> cases; + boolean readOnly = false; + String prompt = "\n-> "; String continuationPrompt = ">> "; @@ -158,10 +195,9 @@ class Feedback { * @param name * @param commandFluff True if should display command fluff messages */ - Mode(String name, boolean commandFluff) { + Mode(String name) { this.name = name; - this.commandFluff = commandFluff; - cases = new HashMap<>(); + this.cases = new HashMap<>(); add("name", new Setting(ALWAYS, "%1$s")); add("type", new Setting(ALWAYS, "%2$s")); add("value", new Setting(ALWAYS, "%3$s")); @@ -181,20 +217,79 @@ class Feedback { * Set up a copied mode. * * @param name - * @param commandFluff True if should display command fluff messages * @param m Mode to copy, or null for no fresh */ - Mode(String name, boolean commandFluff, Mode m) { + Mode(String name, Mode m) { this.name = name; - this.commandFluff = commandFluff; - cases = new HashMap<>(); - + this.commandFluff = m.commandFluff; + this.prompt = m.prompt; + this.continuationPrompt = m.continuationPrompt; + this.cases = new HashMap<>(); m.cases.entrySet().stream() .forEach(fes -> fes.getValue() .forEach(ing -> add(fes.getKey(), ing))); - this.prompt = m.prompt; - this.continuationPrompt = m.continuationPrompt; + } + + /** + * Set up a mode reconstituted from a preferences string. + * + * @param it the encoded Mode broken into String chunks, may contain + * subsequent encoded modes + */ + Mode(Iterator it) { + this.name = it.next(); + this.commandFluff = Boolean.parseBoolean(it.next()); + this.prompt = it.next(); + this.continuationPrompt = it.next(); + cases = new HashMap<>(); + String field; + while (!(field = it.next()).equals("***")) { + String open = it.next(); + assert open.equals("("); + List settings = new ArrayList<>(); + String bits; + while (!(bits = it.next()).equals(")")) { + String format = it.next(); + Setting ing = new Setting(Long.parseLong(bits), format); + settings.add(ing); + } + cases.put(field, settings); + } + } + + /** + * Set if this mode displays informative/confirmational messages on + * commands. + * + * @param fluff the value to set + */ + void setCommandFluff(boolean fluff) { + commandFluff = fluff; + } + + /** + * Encodes the mode into a String so it can be saved in Preferences. + * + * @return the string representation + */ + String encode() { + List el = new ArrayList<>(); + el.add(name); + el.add(String.valueOf(commandFluff)); + el.add(prompt); + el.add(continuationPrompt); + for (Entry> es : cases.entrySet()) { + el.add(es.getKey()); + el.add("("); + for (Setting ing : es.getValue()) { + el.add(String.valueOf(ing.enumBits)); + el.add(ing.format); + } + el.add(")"); + } + el.add("***"); + return String.join(RECORD_SEPARATOR, el); } private boolean add(String field, Setting ing) { @@ -251,13 +346,42 @@ class Feedback { return sb.toString(); } + // Compute the display output given full context and values String format(FormatCase fc, FormatAction fa, FormatWhen fw, FormatResolve fr, FormatUnresolved fu, FormatErrors fe, String name, String type, String value, String unresolved, List errorLines) { + // Convert the context into a bit representation used as selectors for store field formats long bits = bits(fc, fa, fw, fr, fu, fe); String fname = name==null? "" : name; String ftype = type==null? "" : type; - String fvalue = value==null? "" : value; + // Compute the representation of value + String fvalue; + if (value==null) { + fvalue = ""; + } else { + // Retrieve the truncation length + String truncField = format(TRUNCATION_FIELD, bits); + if (truncField.isEmpty()) { + // No truncation set, use whole value + fvalue = value; + } else { + // Convert truncation length to int + // this is safe since it has been tested before it is set + int trunc = Integer.parseUnsignedInt(truncField); + if (value.length() > trunc) { + if (trunc <= 5) { + // Very short truncations have no room for "..." + fvalue = value.substring(0, trunc); + } else { + // Normal truncation, make total length equal truncation length + fvalue = value.substring(0, trunc - 4) + " ..."; + } + } else { + // Within truncation length, use whole value + fvalue = value; + } + } + } String funresolved = unresolved==null? "" : unresolved; String errors = errorLines.stream() .map(el -> String.format( @@ -554,8 +678,12 @@ class Feedback { // For /set prompt "" "" boolean setPrompt() { Mode m = nextMode(); - String prompt = nextFormat(); - String continuationPrompt = nextFormat(); + if (valid && m.readOnly) { + errorat("jshell.err.not.valid.with.predefined.mode", m.name); + valid = false; + } + String prompt = valid ? nextFormat() : null; + String continuationPrompt = valid ? nextFormat() : null; if (valid) { m.setPrompts(prompt, continuationPrompt); } else { @@ -564,36 +692,71 @@ class Feedback { return valid; } - // For /set newmode [command|quiet []] - boolean setNewMode() { - String umode = at.next(); - if (umode == null) { - errorat("jshell.err.feedback.expected.new.feedback.mode"); - valid = false; - } - if (modeMap.containsKey(umode)) { - errorat("jshell.err.feedback.expected.mode.name", umode); - valid = false; - } - String[] fluffOpt = at.next("command", "quiet"); - boolean fluff = fluffOpt == null || fluffOpt.length != 1 || "command".equals(fluffOpt[0]); - if (fluffOpt != null && fluffOpt.length != 1) { - errorat("jshell.err.feedback.command.quiet"); - valid = false; - } + /** + * Set mode. Create, changed, or delete a feedback mode. For @{code /set + * mode [] [-command|-quiet|-delete]}. + * + * @return true if successful + */ + boolean setMode() { + at.allowedOptions("-command", "-quiet", "-delete"); + String umode = nextModeIdentifier(); Mode om = null; String omode = at.next(); - if (omode != null) { + if (valid && omode != null) { om = toMode(omode); } + checkOptionsAndRemainingInput(); + boolean commandOption = at.hasOption("-command"); + boolean quietOption = at.hasOption("-quiet"); + boolean deleteOption = at.hasOption("-delete"); + // Only one (or zero) of the options can be used + if (valid && at.optionCount() > 1) { + errorat("jshell.err.conflicting.options"); + valid = false; + } if (valid) { - Mode nm = (om != null) - ? new Mode(umode, fluff, om) - : new Mode(umode, fluff); - modeMap.put(umode, nm); - fluffmsg("jshell.msg.feedback.new.mode", nm.name); - } else { - fluffmsg("jshell.msg.see", "/help /set newmode"); + Mode m = modeMap.get(umode); + if (m != null && m.readOnly) { + // Cannot make changes to a the built-in modes + errorat("jshell.err.not.valid.with.predefined.mode", m.name); + valid = false; + } else if (deleteOption) { + if (m == null) { + // Cannot delete a mode that does not exist + errorat("jshell.err.mode.unknown", umode); + valid = false; + } else if (mode.name.equals(m.name)) { + // Cannot delete the current mode out from under us + errorat("jshell.err.cannot.delete.current.mode", umode); + valid = false; + } else { + // Remove the mode + modeMap.remove(umode); + } + } else { + if (om != null || m == null) { + // We are copying and existing mode and/or creating a + // brand-new mode -- in either case create from scratch + m = (om != null) + ? new Mode(umode, om) + : new Mode(umode); + modeMap.put(umode, m); + fluffmsg("jshell.msg.feedback.new.mode", m.name); + // Set the current mode by name, in case we just smashed + // the current mode + if (umode.equals(mode.name)) { + mode = modeMap.get(mode.name); + } + } + if (commandOption || quietOption || om == null) { + // set command fluff, if explicit, or wholly new + m.setCommandFluff(!quietOption); + } + } + } + if (!valid) { + fluffmsg("jshell.msg.see", "/help /set mode"); } return valid; } @@ -601,7 +764,7 @@ class Feedback { // For /set feedback boolean setFeedback() { Mode m = nextMode(); - if (valid && m != null) { + if (valid) { mode = m; fluffmsg("jshell.msg.feedback.mode", mode.name); } else { @@ -614,12 +777,149 @@ class Feedback { // For /set format "" ... boolean setFormat() { Mode m = nextMode(); - String field = at.next(); - if (field == null || at.isQuoted()) { - errorat("jshell.err.feedback.expected.field"); + if (valid && m.readOnly) { + errorat("jshell.err.not.valid.with.predefined.mode", m.name); valid = false; } - String format = valid? nextFormat() : null; + String field = valid + ? toIdentifier(at.next(), "jshell.err.missing.field", "jshell.err.field.name") + : null; + String format = valid ? nextFormat() : null; + return installFormat(m, field, format, "/help /set format"); + } + + // For /set truncation ... + boolean setTruncation() { + Mode m = nextMode(); + if (valid && m.readOnly) { + errorat("jshell.err.not.valid.with.predefined.mode", m.name); + valid = false; + } + String length = at.next(); + if (length == null) { + errorat("jshell.err.truncation.expected.length"); + valid = false; + } else { + try { + // Assure that integer format is correct + Integer.parseUnsignedInt(length); + } catch (NumberFormatException ex) { + errorat("jshell.err.truncation.length.not.integer", length); + valid = false; + } + } + // install length into an internal format field + return installFormat(m, TRUNCATION_FIELD, length, "/help /set truncation"); + } + + String retainFeedback() { + String umode = at.next(); + if (umode != null) { + toModeIdentifier(umode); + Mode m = valid ? toMode(umode) : null; + if (valid && !m.readOnly && !retainedMap.containsKey(m.name)) { + errorat("jshell.err.retained.feedback.mode.must.be.retained.or.predefined"); + valid = false; + } + if (valid) { + mode = m; + retainedCurrentMode = m; + fluffmsg("jshell.msg.feedback.mode", mode.name); + } else { + fluffmsg("jshell.msg.see", "/help /retain feedback"); + return null; + } + } + return mode.name; + } + + /** + * Retain (or delete from retention) a previously set mode. + * + * @return all retained modes encoded into a String + */ + String retainMode() { + at.allowedOptions("-delete"); + String umode = nextModeIdentifier(); + // -delete is the only valid option, fail for anything else + checkOptionsAndRemainingInput(); + boolean deleteOption = at.hasOption("-delete"); + // Lookup the mode + Mode m; + if (!valid) { + m = null; + // Skip this stuff, we have failed already + } else if (deleteOption) { + // If delete, allow for deleting, from retention, a mode that + // has been locally deleted but is retained. + // Also require the full name. + m = modeMap.get(umode); + if (m == null && !retainedMap.containsKey(umode)) { + errorat("jshell.err.mode.unknown", umode); + valid = false; + } + } else { + // For retain do normal lookup and checking + m = toMode(umode); + } + + // Built-in modes cannot be retained or deleted + if (valid && m != null && m.readOnly) { + errorat("jshell.err.not.valid.with.predefined.mode", umode); + valid = false; + } + if (valid) { + if (deleteOption) { + if (mode.name.equals(umode)) { + // Cannot delete the current mode out from under us + errorat("jshell.err.cannot.delete.current.mode", umode); + valid = false; + } else if (retainedCurrentMode != null && retainedCurrentMode.name.equals(umode)) { + // Cannot delete the retained mode or re-start has error + errorat("jshell.err.cannot.delete.retained.mode", umode); + valid = false; + } else { + // Delete the mode + modeMap.remove(umode); + retainedMap.remove(umode); + } + } else { + // Retain the current encoding + retainedMap.put(m.name, m.encode()); + } + } + if (valid) { + // Join all the retained encodings + return String.join(RECORD_SEPARATOR, retainedMap.values()); + } else { + fluffmsg("jshell.msg.see", "/help /retain mode"); + return null; + } + } + + boolean restoreEncodedModes(String allEncoded) { + try { + // Iterate over each record in each encoded mode + String[] ms = allEncoded.split(RECORD_SEPARATOR); + Iterator itr = Arrays.asList(ms).iterator(); + while (itr.hasNext()) { + // Reconstruct the encoded mode + Mode m = new Mode(itr); + modeMap.put(m.name, m); + // Continue to retain it a new retains occur + retainedMap.put(m.name, m.encode()); + } + return true; + } catch (Throwable exc) { + // Catastrophic corruption -- clear map + errorat("jshell.err.retained.mode.failure", exc); + retainedMap.clear(); + return false; + } + } + + // install the format of a field under parsed selectors + boolean installFormat(Mode m, String field, String format, String help) { String slRaw; List slList = new ArrayList<>(); while (valid && (slRaw = at.next()) != null) { @@ -629,8 +929,10 @@ class Feedback { } if (valid) { if (slList.isEmpty()) { + // No selectors specified, then always the format m.set(field, ALWAYS, format); } else { + // Set the format of the field for specified selector slList.stream() .forEach(sl -> m.set(field, sl.cases.getSet(), sl.actions.getSet(), sl.whens.getSet(), @@ -638,19 +940,73 @@ class Feedback { format)); } } else { - fluffmsg("jshell.msg.see", "/help /set format"); + fluffmsg("jshell.msg.see", help); } return valid; } + void checkOptionsAndRemainingInput() { + if (!valid) { + return; + } + String junk = at.remainder(); + if (!junk.isEmpty()) { + errorat("jshell.err.unexpected.at.end", junk); + valid = false; + } else { + String bad = at.badOptions(); + if (!bad.isEmpty()) { + errorat("jshell.err.unknown.option", bad); + valid = false; + } + } + } + + /** + * Check that the specified string is an identifier (Java identifier). + * If null display the missing error. If it is not an identifier, + * display the error. + * + * @param id the string to check, MUST be the most recently retrieved + * token from 'at'. + * @param missing the resource error to display if null + * @param err the resource error to display if not an identifier + * @return the identifier string, or null if null or not an identifier + */ + String toIdentifier(String id, String missing, String err) { + if (id == null) { + errorat(missing); + valid = false; + return null; + } + if (at.isQuoted() || + !id.codePoints().allMatch(cp -> Character.isJavaIdentifierPart(cp))) { + errorat(err, id); + valid = false; + return null; + } + return id; + } + + String toModeIdentifier(String id) { + return toIdentifier(id, "jshell.err.missing.mode", "jshell.err.mode.name"); + } + + String nextModeIdentifier() { + return toModeIdentifier(at.next()); + } + Mode nextMode() { - String umode = at.next(); + String umode = nextModeIdentifier(); return toMode(umode); } Mode toMode(String umode) { + if (!valid) { + return null; + } if (umode == null) { - errorat("jshell.err.feedback.expected.mode"); + errorat("jshell.err.missing.mode"); valid = false; return null; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index b6cd1a370f6..c7f3fec94c5 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -101,8 +101,13 @@ import jdk.internal.jshell.tool.Feedback.FormatResolve; import jdk.internal.jshell.tool.Feedback.FormatUnresolved; import jdk.internal.jshell.tool.Feedback.FormatWhen; import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; +import static java.util.stream.Collectors.toMap; +import static jdk.internal.jshell.debug.InternalDebugControl.DBG_COMPA; +import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP; +import static jdk.internal.jshell.debug.InternalDebugControl.DBG_EVNT; +import static jdk.internal.jshell.debug.InternalDebugControl.DBG_FMGR; +import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; /** * Command line REPL tool for Java using the JShell API. @@ -112,8 +117,6 @@ public class JShellTool implements MessageHandler { private static final String LINE_SEP = System.getProperty("line.separator"); private static final Pattern LINEBREAK = Pattern.compile("\\R"); - private static final Pattern HISTORY_ALL_START_FILENAME = Pattern.compile( - "((?(all|history|start))(\\z|\\p{javaWhitespace}+))?(?.*)"); private static final String RECORD_SEPARATOR = "\u241E"; private static final String RB_NAME_PREFIX = "jdk.internal.jshell.tool.resources"; private static final String VERSION_RB_NAME = RB_NAME_PREFIX + ".version"; @@ -166,7 +169,7 @@ public class JShellTool implements MessageHandler { private boolean regenerateOnDeath = true; private boolean live = false; private boolean feedbackInitialized = false; - private String initialMode = null; + private String commandLineFeedbackMode = null; private List remoteVMOptions = new ArrayList<>(); SourceCodeAnalysis analysis; @@ -176,14 +179,17 @@ public class JShellTool implements MessageHandler { private boolean debug = false; public boolean testPrompt = false; private String cmdlineClasspath = null; - private String cmdlineStartup = null; + private String startup = null; private String[] editor = null; // Commands and snippets which should be replayed private List replayableHistory; private List replayableHistoryPrevious; - static final String STARTUP_KEY = "STARTUP"; + static final String STARTUP_KEY = "STARTUP"; + static final String EDITOR_KEY = "EDITOR"; + static final String FEEDBACK_KEY = "FEEDBACK"; + static final String MODE_KEY = "MODE"; static final String REPLAY_RESTORE_KEY = "REPLAY_RESTORE"; static final String DEFAULT_STARTUP = @@ -367,7 +373,11 @@ public class JShellTool implements MessageHandler { */ @Override public void errormsg(String key, Object... args) { - cmdout.println(prefix(messageFormat(key, args), feedback.getErrorPre())); + if (isRunningInteractive()) { + cmdout.println(prefix(messageFormat(key, args), feedback.getErrorPre())); + } else { + startmsg(key, args); + } } /** @@ -454,6 +464,22 @@ public class JShellTool implements MessageHandler { } private void start(IOContext in, List loadList) { + // If startup hasn't been set by command line, set from retained/default + if (startup == null) { + startup = prefs.get(STARTUP_KEY, null); + if (startup == null) { + startup = DEFAULT_STARTUP; + } + } + + // Read retained editor setting (if any) + String editorString = prefs.get(EDITOR_KEY, ""); + if (editorString == null || editorString.isEmpty()) { + editor = null; + } else { + editor = editorString.split(RECORD_SEPARATOR); + } + resetState(); // Initialize // Read replay history from last jshell session into previous history @@ -519,37 +545,37 @@ public class JShellTool implements MessageHandler { return null; case "-feedback": if (ai.hasNext()) { - initialMode = ai.next(); + commandLineFeedbackMode = ai.next(); } else { startmsg("jshell.err.opt.feedback.arg"); return null; } break; case "-q": - initialMode = "concise"; + commandLineFeedbackMode = "concise"; break; case "-qq": - initialMode = "silent"; + commandLineFeedbackMode = "silent"; break; case "-v": - initialMode = "verbose"; + commandLineFeedbackMode = "verbose"; break; case "-startup": - if (cmdlineStartup != null) { - startmsg("jshell.err.opt.startup.conflict"); + if (startup != null) { + startmsg("jshell.err.opt.startup.one"); return null; } - cmdlineStartup = readFile(ai.hasNext()? ai.next() : null, "'-startup'"); - if (cmdlineStartup == null) { + startup = readFile(ai.hasNext()? ai.next() : null, "-startup"); + if (startup == null) { return null; } break; case "-nostartup": - if (cmdlineStartup != null && !cmdlineStartup.isEmpty()) { - startmsg("jshell.err.opt.startup.conflict"); + if (startup != null) { + startmsg("jshell.err.opt.startup.one"); return null; } - cmdlineStartup = ""; + startup = ""; break; default: if (arg.startsWith("-R")) { @@ -571,6 +597,27 @@ public class JShellTool implements MessageHandler { cmdout.print(getResourceString("help.usage")); } + /** + * Message handler to use during initial start-up. + */ + private class InitMessageHandler implements MessageHandler { + + @Override + public void fluff(String format, Object... args) { + //ignore + } + + @Override + public void fluffmsg(String messageKey, Object... args) { + //ignore + } + + @Override + public void errormsg(String messageKey, Object... args) { + startmsg(messageKey, args); + } + } + private void resetState() { closeState(); @@ -604,53 +651,62 @@ public class JShellTool implements MessageHandler { analysis = state.sourceCodeAnalysis(); live = true; if (!feedbackInitialized) { - startUpRun(getResourceString("startup.feedback")); + // One time per run feedback initialization feedbackInitialized = true; + initFeedback(); } if (cmdlineClasspath != null) { state.addToClasspath(cmdlineClasspath); } - String start; - if (cmdlineStartup == null) { - start = prefs.get(STARTUP_KEY, ""); - if (start.equals("")) { - start = DEFAULT_STARTUP; - prefs.put(STARTUP_KEY, DEFAULT_STARTUP); - } - } else { - start = cmdlineStartup; - } - startUpRun(start); - if (initialMode != null) { - MessageHandler mh = new MessageHandler() { - @Override - public void fluff(String format, Object... args) { - } - - @Override - public void fluffmsg(String messageKey, Object... args) { - } - - @Override - public void errormsg(String messageKey, Object... args) { - startmsg(messageKey, args); - } - }; - if (!feedback.setFeedback(mh, new ArgTokenizer("-feedback ", initialMode))) { - regenerateOnDeath = false; - } - initialMode = null; - } + startUpRun(startup); currentNameSpace = mainNamespace; } + + private boolean isRunningInteractive() { + return currentNameSpace != null && currentNameSpace == mainNamespace; + } + + //where -- one-time per run initialization of feedback modes + private void initFeedback() { + // No fluff, no prefix, for init failures + MessageHandler initmh = new InitMessageHandler(); + // Execute the feedback initialization code in the resource file + startUpRun(getResourceString("startup.feedback")); + // These predefined modes are read-only + feedback.markModesReadOnly(); + // Restore user defined modes retained on previous run with /retain mode + String encoded = prefs.get(MODE_KEY, null); + if (encoded != null && !encoded.isEmpty()) { + if (!feedback.restoreEncodedModes(initmh, encoded)) { + // Catastrophic corruption -- remove the retained modes + prefs.remove(MODE_KEY); + } + } + if (commandLineFeedbackMode != null) { + // The feedback mode to use was specified on the command line, use it + if (!feedback.setFeedback(initmh, new ArgTokenizer("-feedback", commandLineFeedbackMode))) { + regenerateOnDeath = false; + } + commandLineFeedbackMode = null; + } else { + String fb = prefs.get(FEEDBACK_KEY, null); + if (fb != null) { + // Restore the feedback mode to use that was retained + // on a previous run with /retain feedback + feedback.retainFeedback(initmh, new ArgTokenizer("/retain feedback", fb)); + } + } + } + //where private void startUpRun(String start) { try (IOContext suin = new FileScannerIOContext(new StringReader(start))) { run(suin); } catch (Exception ex) { hardmsg("jshell.err.startup.unexpected.exception", ex); + ex.printStackTrace(cmdout); } } @@ -674,7 +730,7 @@ public class JShellTool implements MessageHandler { String incomplete = ""; while (live) { String prompt; - if (currentNameSpace == mainNamespace) { + if (isRunningInteractive()) { prompt = testPrompt ? incomplete.isEmpty() ? "\u0005" //ENQ @@ -722,7 +778,7 @@ public class JShellTool implements MessageHandler { } private void addToReplayHistory(String s) { - if (currentNameSpace == mainNamespace) { + if (isRunningInteractive()) { replayableHistory.add(s); } } @@ -879,8 +935,8 @@ public class JShellTool implements MessageHandler { } private static final CompletionProvider EMPTY_COMPLETION_PROVIDER = new FixedCompletionProvider(); - private static final CompletionProvider KEYWORD_COMPLETION_PROVIDER = new FixedCompletionProvider("all ", "start ", "history "); - private static final CompletionProvider RELOAD_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider("restore", "quiet"); + private static final CompletionProvider KEYWORD_COMPLETION_PROVIDER = new FixedCompletionProvider("-all ", "-start ", "-history "); + private static final CompletionProvider RELOAD_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider("-restore", "-quiet"); private static final CompletionProvider FILE_COMPLETION_PROVIDER = fileCompletions(p -> true); private final Map commands = new LinkedHashMap<>(); private void registerCommand(Command cmd) { @@ -917,11 +973,10 @@ public class JShellTool implements MessageHandler { p.getFileName().toString().endsWith(".jar")); } - private CompletionProvider editCompletion() { + private CompletionProvider snippetCompletion(Supplier> snippetsSupplier) { return (prefix, cursor, anchor) -> { anchor[0] = 0; - return state.snippets() - .stream() + return snippetsSupplier.get() .stream() .flatMap(k -> (k instanceof DeclarationSnippet) ? Stream.of(String.valueOf(k.id()), ((DeclarationSnippet) k).name()) : Stream.of(String.valueOf(k.id()))) @@ -931,11 +986,11 @@ public class JShellTool implements MessageHandler { }; } - private CompletionProvider editKeywordCompletion() { + private CompletionProvider snippetKeywordCompletion(Supplier> snippetsSupplier) { return (code, cursor, anchor) -> { List result = new ArrayList<>(); result.addAll(KEYWORD_COMPLETION_PROVIDER.completionSuggestions(code, cursor, anchor)); - result.addAll(editCompletion().completionSuggestions(code, cursor, anchor)); + result.addAll(snippetCompletion(snippetsSupplier).completionSuggestions(code, cursor, anchor)); return result; }; } @@ -963,18 +1018,52 @@ public class JShellTool implements MessageHandler { }; } + // Snippet lists + + List allSnippets() { + return state.snippets(); + } + + List dropableSnippets() { + return state.snippets().stream() + .filter(sn -> state.status(sn).isActive && sn instanceof PersistentSnippet) + .map(sn -> (PersistentSnippet) sn) + .collect(toList()); + } + + List allVarSnippets() { + return state.snippets().stream() + .filter(sn -> sn.kind() == Snippet.Kind.VAR) + .map(sn -> (VarSnippet) sn) + .collect(toList()); + } + + List allMethodSnippets() { + return state.snippets().stream() + .filter(sn -> sn.kind() == Snippet.Kind.METHOD) + .map(sn -> (MethodSnippet) sn) + .collect(toList()); + } + + List allTypeSnippets() { + return state.snippets().stream() + .filter(sn -> sn.kind() == Snippet.Kind.TYPE_DECL) + .map(sn -> (TypeDeclSnippet) sn) + .collect(toList()); + } + // Table of commands -- with command forms, argument kinds, helpKey message, implementation, ... { registerCommand(new Command("/list", arg -> cmdList(arg), - editKeywordCompletion())); + snippetKeywordCompletion(this::allSnippets))); registerCommand(new Command("/edit", arg -> cmdEdit(arg), - editCompletion())); + snippetCompletion(this::allSnippets))); registerCommand(new Command("/drop", arg -> cmdDrop(arg), - editCompletion(), + snippetCompletion(this::dropableSnippets), CommandKind.REPLAY)); registerCommand(new Command("/save", arg -> cmdSave(arg), @@ -983,14 +1072,14 @@ public class JShellTool implements MessageHandler { arg -> cmdOpen(arg), FILE_COMPLETION_PROVIDER)); registerCommand(new Command("/vars", - arg -> cmdVars(), - EMPTY_COMPLETION_PROVIDER)); + arg -> cmdVars(arg), + snippetKeywordCompletion(this::allVarSnippets))); registerCommand(new Command("/methods", - arg -> cmdMethods(), - EMPTY_COMPLETION_PROVIDER)); - registerCommand(new Command("/classes", - arg -> cmdClasses(), - EMPTY_COMPLETION_PROVIDER)); + arg -> cmdMethods(arg), + snippetKeywordCompletion(this::allMethodSnippets))); + registerCommand(new Command("/types", + arg -> cmdTypes(arg), + snippetKeywordCompletion(this::allTypeSnippets))); registerCommand(new Command("/imports", arg -> cmdImports(), EMPTY_COMPLETION_PROVIDER)); @@ -1019,7 +1108,10 @@ public class JShellTool implements MessageHandler { EMPTY_COMPLETION_PROVIDER)); registerCommand(new Command("/set", arg -> cmdSet(arg), - new FixedCompletionProvider("format", "feedback", "prompt", "newmode", "start", "editor"))); + new FixedCompletionProvider(SET_SUBCOMMANDS))); + registerCommand(new Command("/retain", + arg -> cmdRetain(arg), + new FixedCompletionProvider(RETAIN_SUBCOMMANDS))); registerCommand(new Command("/?", "help.quest", arg -> cmdHelp(arg), @@ -1094,79 +1186,116 @@ public class JShellTool implements MessageHandler { // --- Command implementations --- private static final String[] SET_SUBCOMMANDS = new String[]{ - "format", "feedback", "newmode", "prompt", "editor", "start"}; + "format", "truncation", "feedback", "mode", "prompt", "editor", "start"}; + + private static final String[] RETAIN_SUBCOMMANDS = new String[]{ + "feedback", "mode", "editor", "start"}; final boolean cmdSet(String arg) { - ArgTokenizer at = new ArgTokenizer("/set ", arg.trim()); - String which = setSubCommand(at); + String cmd = "/set"; + ArgTokenizer at = new ArgTokenizer(cmd, arg.trim()); + String which = subCommand(cmd, at, SET_SUBCOMMANDS); if (which == null) { return false; } switch (which) { case "format": return feedback.setFormat(this, at); + case "truncation": + return feedback.setTruncation(this, at); case "feedback": return feedback.setFeedback(this, at); - case "newmode": - return feedback.setNewMode(this, at); + case "mode": + return feedback.setMode(this, at); case "prompt": return feedback.setPrompt(this, at); - case "editor": { - String prog = at.next(); - if (prog == null) { - errormsg("jshell.err.set.editor.arg"); - return false; - } else { - List ed = new ArrayList<>(); - ed.add(prog); - String n; - while ((n = at.next()) != null) { - ed.add(n); - } - editor = ed.toArray(new String[ed.size()]); - fluffmsg("jshell.msg.set.editor.set", prog); - return true; - } - } - case "start": { - String init = readFile(at.next(), "/set start"); - if (init == null) { - return false; - } else { - prefs.put(STARTUP_KEY, init); - return true; - } - } + case "editor": + return setEditor(at, true); + case "start": + return setStart(cmd, at, true); default: - errormsg("jshell.err.arg", "/set", at.val()); + errormsg("jshell.err.arg", cmd, at.val()); return false; } } - boolean printSetHelp(ArgTokenizer at) { - String which = setSubCommand(at); + final boolean cmdRetain(String arg) { + String cmd = "/retain"; + ArgTokenizer at = new ArgTokenizer(cmd, arg.trim()); + String which = subCommand(cmd, at, RETAIN_SUBCOMMANDS); if (which == null) { return false; } - hardrb("help.set." + which); + switch (which) { + case "feedback": { + String fb = feedback.retainFeedback(this, at); + if (fb != null) { + // If a feedback mode has been set now, or in the past, retain it + prefs.put(FEEDBACK_KEY, fb); + return true; + } + return false; + } + case "mode": + String retained = feedback.retainMode(this, at); + if (retained != null) { + // Retain this mode and all previously retained modes + prefs.put(MODE_KEY, retained); + return true; + } + return false; + case "editor": + if (!setEditor(at, false)) { + return false; + } + // retain editor setting + prefs.put(EDITOR_KEY, (editor == null) + ? "" + : String.join(RECORD_SEPARATOR, editor)); + return true; + case "start": { + if (!setStart(cmd, at, false)) { + return false; + } + // retain startup setting + prefs.put(STARTUP_KEY, startup); + return true; + } + default: + errormsg("jshell.err.arg", cmd, at.val()); + return false; + } + } + + // Print the help doc for the specified sub-command + boolean printSubCommandHelp(String cmd, ArgTokenizer at, String helpPrefix, String[] subs) { + String which = subCommand(cmd, at, subs); + if (which == null) { + return false; + } + hardrb(helpPrefix + which); return true; } - String setSubCommand(ArgTokenizer at) { - String[] matches = at.next(SET_SUBCOMMANDS); + // Find which, if any, sub-command matches + String subCommand(String cmd, ArgTokenizer at, String[] subs) { + String[] matches = at.next(subs); if (matches == null) { - errormsg("jshell.err.set.arg"); + // No sub-command was given + errormsg("jshell.err.sub.arg", cmd); return null; } if (matches.length == 0) { - errormsg("jshell.err.arg", "/set", at.val()); - fluffmsg("jshell.msg.use.one.of", Arrays.stream(SET_SUBCOMMANDS) + // There are no matching sub-commands + errormsg("jshell.err.arg", cmd, at.val()); + fluffmsg("jshell.msg.use.one.of", Arrays.stream(subs) .collect(Collectors.joining(", ")) ); return null; } if (matches.length > 1) { - errormsg("jshell.err.set.ambiguous", at.val()); + // More than one sub-command matches the initial characters provided + errormsg("jshell.err.sub.ambiguous", cmd, at.val()); fluffmsg("jshell.msg.use.one.of", Arrays.stream(matches) .collect(Collectors.joining(", ")) ); @@ -1175,6 +1304,63 @@ public class JShellTool implements MessageHandler { return matches[0]; } + // The sub-command: /set editor > + boolean setEditor(ArgTokenizer at, boolean argsRequired) { + at.allowedOptions("-default"); + String prog = at.next(); + List ed = new ArrayList<>(); + while (at.val() != null) { + ed.add(at.val()); + at.nextToken(); + } + if (!checkOptionsAndRemainingInput(at)) { + return false; + } + boolean defaultOption = at.hasOption("-default"); + if (prog != null) { + if (defaultOption) { + errormsg("jshell.err.default.option.or.program", at.whole()); + return false; + } + editor = ed.toArray(new String[ed.size()]); + fluffmsg("jshell.msg.set.editor.set", prog); + } else if (defaultOption) { + editor = null; + } else if (argsRequired) { + errormsg("jshell.err.set.editor.arg"); + return false; + } + return true; + } + + // The sub-command: /set start + boolean setStart(String cmd, ArgTokenizer at, boolean argsRequired) { + at.allowedOptions("-default", "-none"); + String fn = at.next(); + if (!checkOptionsAndRemainingInput(at)) { + return false; + } + int argCount = at.optionCount() + ((fn != null) ? 1 : 0); + if (argCount > 1 || argsRequired && argCount == 0) { + errormsg("jshell.err.option.or.filename", at.whole()); + return false; + } + if (fn != null) { + String init = readFile(fn, cmd + " start"); + if (init == null) { + return false; + } else { + startup = init; + return true; + } + } else if (at.hasOption("-default")) { + startup = DEFAULT_STARTUP; + } else if (at.hasOption("-none")) { + startup = ""; + } + return true; + } + boolean cmdClasspath(String arg) { if (arg.isEmpty()) { errormsg("jshell.err.classpath.arg"); @@ -1189,7 +1375,7 @@ public class JShellTool implements MessageHandler { boolean cmdDebug(String arg) { if (arg.isEmpty()) { debug = !debug; - InternalDebugControl.setDebugFlags(state, debug ? InternalDebugControl.DBG_GEN : 0); + InternalDebugControl.setDebugFlags(state, debug ? DBG_GEN : 0); fluff("Debugging %s", debug ? "on" : "off"); } else { int flags = 0; @@ -1205,23 +1391,23 @@ public class JShellTool implements MessageHandler { fluff("REPL tool debugging on"); break; case 'g': - flags |= InternalDebugControl.DBG_GEN; + flags |= DBG_GEN; fluff("General debugging on"); break; case 'f': - flags |= InternalDebugControl.DBG_FMGR; + flags |= DBG_FMGR; fluff("File manager debugging on"); break; case 'c': - flags |= InternalDebugControl.DBG_COMPA; + flags |= DBG_COMPA; fluff("Completion analysis debugging on"); break; case 'd': - flags |= InternalDebugControl.DBG_DEP; + flags |= DBG_DEP; fluff("Dependency debugging on"); break; case 'e': - flags |= InternalDebugControl.DBG_EVNT; + flags |= DBG_EVNT; fluff("Event debugging on"); break; default: @@ -1259,7 +1445,7 @@ public class JShellTool implements MessageHandler { } boolean cmdHelp(String arg) { - ArgTokenizer at = new ArgTokenizer(arg); + ArgTokenizer at = new ArgTokenizer("/help", arg); String subject = at.next(); if (subject != null) { Command[] matches = commands.values().stream() @@ -1267,9 +1453,16 @@ public class JShellTool implements MessageHandler { .toArray(size -> new Command[size]); at.mark(); String sub = at.next(); - if (sub != null && matches.length == 1 && matches[0].command.equals("/set")) { - at.rewind(); - return printSetHelp(at); + if (sub != null && matches.length == 1) { + String cmd = matches[0].command; + switch (cmd) { + case "/set": + at.rewind(); + return printSubCommandHelp(cmd, at, "help.set.", SET_SUBCOMMANDS); + case "/retain": + at.rewind(); + return printSubCommandHelp(cmd, at, "help.retain.", RETAIN_SUBCOMMANDS); + } } if (matches.length > 0) { for (Command c : matches) { @@ -1310,7 +1503,7 @@ public class JShellTool implements MessageHandler { /** * Avoid parameterized varargs possible heap pollution warning. */ - private interface SnippetPredicate extends Predicate { } + private interface SnippetPredicate extends Predicate { } /** * Apply filters to a stream until one that is non-empty is found. @@ -1320,10 +1513,11 @@ public class JShellTool implements MessageHandler { * @param filters Filters to attempt * @return The non-empty filtered Stream, or null */ - private static Stream nonEmptyStream(Supplier> supplier, - SnippetPredicate... filters) { - for (SnippetPredicate filt : filters) { - Iterator iterator = supplier.get().filter(filt).iterator(); + @SafeVarargs + private static Stream nonEmptyStream(Supplier> supplier, + SnippetPredicate... filters) { + for (SnippetPredicate filt : filters) { + Iterator iterator = supplier.get().filter(filt).iterator(); if (iterator.hasNext()) { return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); } @@ -1349,76 +1543,139 @@ public class JShellTool implements MessageHandler { } /** - * Convert a user argument to a Stream of snippets referenced by that argument - * (or lack of argument). + * Convert user arguments to a Stream of snippets referenced by those + * arguments (or lack of arguments). * - * @param arg The user's argument to the command, maybe be the empty string - * @return a Stream of referenced snippets or null if no matches to specific arg + * @param snippets the base list of possible snippets + * @param defFilter the filter to apply to the arguments if no argument + * @param rawargs the user's argument to the command, maybe be the empty + * string + * @return a Stream of referenced snippets or null if no matches are found */ - private Stream argToSnippets(String arg, boolean allowAll) { - List snippets = state.snippets(); - if (allowAll && arg.equals("all")) { + private Stream argsOptionsToSnippets(List snippets, + Predicate defFilter, String rawargs, String cmd) { + ArgTokenizer at = new ArgTokenizer(cmd, rawargs.trim()); + at.allowedOptions("-all", "-start"); + List args = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + args.add(s); + } + if (!checkOptionsAndRemainingInput(at)) { + return null; + } + if (at.optionCount() > 0 && args.size() > 0) { + errormsg("jshell.err.may.not.specify.options.and.snippets", at.whole()); + return null; + } + if (at.optionCount() > 1) { + errormsg("jshell.err.conflicting.options", at.whole()); + return null; + } + if (at.hasOption("-all")) { // all snippets including start-up, failed, and overwritten return snippets.stream(); - } else if (allowAll && arg.equals("start")) { + } + if (at.hasOption("-start")) { // start-up snippets return snippets.stream() .filter(this::inStartUp); - } else if (arg.isEmpty()) { + } + if (args.isEmpty()) { // Default is all active user snippets return snippets.stream() - .filter(this::mainActive); - } else { - Stream result = - nonEmptyStream( - () -> snippets.stream(), - // look for active user declarations matching the name - sn -> isActive(sn) && matchingDeclaration(sn, arg), - // else, look for any declarations matching the name - sn -> matchingDeclaration(sn, arg), - // else, look for an id of this name - sn -> sn.id().equals(arg) - ); - return result; + .filter(defFilter); } + return argsToSnippets(snippets, args); } - private boolean cmdDrop(String arg) { - if (arg.isEmpty()) { + /** + * Convert user arguments to a Stream of snippets referenced by those + * arguments. + * + * @param snippets the base list of possible snippets + * @param args the user's argument to the command, maybe be the empty list + * @return a Stream of referenced snippets or null if no matches to specific + * arg + */ + private Stream argsToSnippets(List snippets, + List args) { + Stream result = null; + for (String arg : args) { + // Find the best match + Stream st = layeredSnippetSearch(snippets, arg); + if (st == null) { + Stream est = layeredSnippetSearch(state.snippets(), arg); + if (est == null) { + errormsg("jshell.err.no.such.snippets", arg); + } else { + errormsg("jshell.err.the.snippet.cannot.be.used.with.this.command", + arg, est.findFirst().get().source()); + } + return null; + } + if (result == null) { + result = st; + } else { + result = Stream.concat(result, st); + } + } + return result; + } + + private Stream layeredSnippetSearch(List snippets, String arg) { + return nonEmptyStream( + // the stream supplier + () -> snippets.stream(), + // look for active user declarations matching the name + sn -> isActive(sn) && matchingDeclaration(sn, arg), + // else, look for any declarations matching the name + sn -> matchingDeclaration(sn, arg), + // else, look for an id of this name + sn -> sn.id().equals(arg) + ); + } + + private boolean cmdDrop(String rawargs) { + ArgTokenizer at = new ArgTokenizer("/drop", rawargs.trim()); + at.allowedOptions(); + List args = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + args.add(s); + } + if (!checkOptionsAndRemainingInput(at)) { + return false; + } + if (args.isEmpty()) { errormsg("jshell.err.drop.arg"); return false; } - Stream stream = argToSnippets(arg, false); + Stream stream = argsToSnippets(dropableSnippets(), args); if (stream == null) { - errormsg("jshell.err.def.or.id.not.found", arg); + // Snippet not found. Error already printed fluffmsg("jshell.msg.see.classes.etc"); return false; } - List snippets = stream - .filter(sn -> state.status(sn).isActive && sn instanceof PersistentSnippet) - .collect(toList()); - if (snippets.isEmpty()) { - errormsg("jshell.err.drop.not.active"); - return false; - } - if (snippets.size() > 1) { + List snippets = stream.collect(toList()); + if (snippets.size() > args.size()) { + // One of the args references more thean one snippet errormsg("jshell.err.drop.ambiguous"); fluffmsg("jshell.msg.use.one.of", snippets.stream() - .map(sn -> String.format("\n%4s : %s", sn.id(), sn.source().replace("\n", "\n "))) + .map(sn -> String.format("\n/drop %-5s : %s", sn.id(), sn.source().replace("\n", "\n "))) .collect(Collectors.joining(", ")) ); return false; } - PersistentSnippet psn = (PersistentSnippet) snippets.get(0); - state.drop(psn).forEach(this::handleEvent); + snippets.stream() + .forEach(sn -> state.drop(sn).forEach(this::handleEvent)); return true; } private boolean cmdEdit(String arg) { - Stream stream = argToSnippets(arg, true); + Stream stream = argsOptionsToSnippets(state.snippets(), + this::mainActive, arg, "/edit"); if (stream == null) { - errormsg("jshell.err.def.or.id.not.found", arg); - fluffmsg("jshell.msg.see.classes.etc"); return false; } Set srcSet = new LinkedHashSet<>(); @@ -1518,18 +1775,12 @@ public class JShellTool implements MessageHandler { } private boolean cmdList(String arg) { - if (arg.equals("history")) { + if (arg.length() >= 2 && "-history".startsWith(arg)) { return cmdHistory(); } - Stream stream = argToSnippets(arg, true); + Stream stream = argsOptionsToSnippets(state.snippets(), + this::mainActive, arg, "/list"); if (stream == null) { - errormsg("jshell.err.def.or.id.not.found", arg); - // Check if there are any definitions at all - if (argToSnippets("", false).iterator().hasNext()) { - fluffmsg("jshell.msg.try.list.without.args"); - } else { - hardmsg("jshell.msg.no.active"); - } return false; } @@ -1597,75 +1848,63 @@ public class JShellTool implements MessageHandler { return true; } - private boolean cmdReload(String arg) { - Iterable history = replayableHistory; - boolean echo = true; - if (arg.length() > 0) { - if ("restore".startsWith(arg)) { - if (replayableHistoryPrevious == null) { - errormsg("jshell.err.reload.no.previous"); - return false; - } - history = replayableHistoryPrevious; - } else if ("quiet".startsWith(arg)) { - echo = false; - } else { - errormsg("jshell.err.arg", "/reload", arg); + private boolean cmdReload(String rawargs) { + ArgTokenizer at = new ArgTokenizer("/reload", rawargs.trim()); + at.allowedOptions("-restore", "-quiet"); + if (!checkOptionsAndRemainingInput(at)) { + return false; + } + Iterable history; + if (at.hasOption("-restore")) { + if (replayableHistoryPrevious == null) { + errormsg("jshell.err.reload.no.previous"); return false; } + history = replayableHistoryPrevious; + fluffmsg("jshell.err.reload.restarting.previous.state"); + } else { + history = replayableHistory; + fluffmsg("jshell.err.reload.restarting.state"); } - fluffmsg(history == replayableHistoryPrevious - ? "jshell.err.reload.restarting.previous.state" - : "jshell.err.reload.restarting.state"); + boolean echo = !at.hasOption("-quiet"); resetState(); run(new ReloadIOContext(history, - echo? cmdout : null)); + echo ? cmdout : null)); return true; } - private boolean cmdSave(String arg_filename) { - Matcher mat = HISTORY_ALL_START_FILENAME.matcher(arg_filename); - if (!mat.find()) { - errormsg("jshell.err.arg", arg_filename); + private boolean cmdSave(String rawargs) { + ArgTokenizer at = new ArgTokenizer("/save", rawargs.trim()); + at.allowedOptions("-all", "-start", "-history"); + String filename = at.next(); + if (filename == null) { + errormsg("jshell.err.file.filename", "/save"); return false; } - boolean useHistory = false; - String saveAll = ""; - boolean saveStart = false; - String cmd = mat.group("cmd"); - if (cmd != null) switch (cmd) { - case "all": - saveAll = "all"; - break; - case "history": - useHistory = true; - break; - case "start": - saveStart = true; - break; + if (!checkOptionsAndRemainingInput(at)) { + return false; } - String filename = mat.group("filename"); - if (filename == null ||filename.isEmpty()) { - errormsg("jshell.err.file.filename", "/save"); + if (at.optionCount() > 1) { + errormsg("jshell.err.conflicting.options", at.whole()); return false; } try (BufferedWriter writer = Files.newBufferedWriter(toPathResolvingUserHome(filename), Charset.defaultCharset(), CREATE, TRUNCATE_EXISTING, WRITE)) { - if (useHistory) { + if (at.hasOption("-history")) { for (String s : input.currentSessionHistory()) { writer.write(s); writer.write("\n"); } - } else if (saveStart) { - writer.append(DEFAULT_STARTUP); + } else if (at.hasOption("-start")) { + writer.append(startup); } else { - Stream stream = argToSnippets(saveAll, true); - if (stream != null) { - for (Snippet sn : stream.collect(toList())) { - writer.write(sn.source()); - writer.write("\n"); - } + List sns = at.hasOption("-all") + ? state.snippets() + : state.snippets().stream().filter(this::mainActive).collect(toList()); + for (Snippet sn : sns) { + writer.write(sn.source()); + writer.write("\n"); } } } catch (FileNotFoundException e) { @@ -1678,25 +1917,42 @@ public class JShellTool implements MessageHandler { return true; } - private boolean cmdVars() { - for (VarSnippet vk : state.variables()) { + private boolean cmdVars(String arg) { + Stream stream = argsOptionsToSnippets(allVarSnippets(), + this::isActive, arg, "/vars"); + if (stream == null) { + return false; + } + stream.forEachOrdered(vk -> + { String val = state.status(vk) == Status.VALID ? state.varValue(vk) : "jshell.msg.vars.not.active"; hard(" %s %s = %s", vk.typeName(), vk.name(), val); - } + }); return true; } - private boolean cmdMethods() { - for (MethodSnippet mk : state.methods()) { - hard(" %s %s", mk.name(), mk.signature()); + private boolean cmdMethods(String arg) { + Stream stream = argsOptionsToSnippets(allMethodSnippets(), + this::isActive, arg, "/methods"); + if (stream == null) { + return false; } + stream.forEachOrdered(mk + -> hard(" %s %s", mk.name(), mk.signature()) + ); return true; } - private boolean cmdClasses() { - for (TypeDeclSnippet ck : state.types()) { + private boolean cmdTypes(String arg) { + Stream stream = argsOptionsToSnippets(allTypeSnippets(), + this::isActive, arg, "/types"); + if (stream == null) { + return false; + } + stream.forEachOrdered(ck + -> { String kind; switch (ck.subKind()) { case INTERFACE_SUBKIND: @@ -1717,7 +1973,7 @@ public class JShellTool implements MessageHandler { break; } hard(" %s %s", kind, ck.name()); - } + }); return true; } @@ -1743,6 +1999,21 @@ public class JShellTool implements MessageHandler { return true; } + boolean checkOptionsAndRemainingInput(ArgTokenizer at) { + String junk = at.remainder(); + if (!junk.isEmpty()) { + errormsg("jshell.err.unexpected.at.end", junk, at.whole()); + return false; + } else { + String bad = at.badOptions(); + if (!bad.isEmpty()) { + errormsg("jshell.err.unknown.option", bad, at.whole()); + return false; + } + } + return true; + } + private boolean rerunHistoryEntryById(String id) { Optional snippet = state.snippets().stream() .filter(s -> s.id().equals(id)) @@ -1876,7 +2147,7 @@ public class JShellTool implements MessageHandler { List disp = new ArrayList<>(); displayDiagnostics(source, d, disp); disp.stream() - .forEach(l -> hard(l)); + .forEach(l -> hard("%s", l)); } if (ste.status() != Status.REJECTED) { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties index 06784c86582..da44d078219 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties @@ -29,16 +29,15 @@ For an introduction type: /help intro\n jshell.err.opt.classpath.conflict = Conflicting -classpath option. jshell.err.opt.classpath.arg = Argument to -classpath missing. jshell.err.opt.feedback.arg = Argument to -feedback missing. Mode required. -jshell.err.opt.startup.conflict = Conflicting -startup or -nostartup option. +jshell.err.opt.startup.one = Only one -startup or -nostartup option may be used. jshell.err.opt.unknown = Unknown option: {0} jshell.msg.terminated =\ State engine terminated.\n\ -Restore definitions with: /reload restore +Restore definitions with: /reload -restore jshell.msg.use.one.of = Use one of: {0} -jshell.err.def.or.id.not.found = No definition or id found named: {0} -jshell.msg.see.classes.etc = See /classes, /methods, /vars, or /list +jshell.msg.see.classes.etc = See /types, /methods, /vars, or /list jshell.err.arg = Invalid ''{0}'' argument: {1} jshell.msg.see = See {0} for help. @@ -57,7 +56,7 @@ jshell.msg.set.editor.set = Editor set to: {0} jshell.err.cant.launch.editor = Cannot launch editor -- unexpected exception: {0} jshell.msg.try.set.editor = Try /set editor to use external editor. -jshell.msg.try.list.without.args = Try ''/list'' without arguments. +jshell.msg.try.command.without.args = Try ''{0}'' without arguments. jshell.msg.no.active = There are no active definitions. jshell.msg.resetting = Resetting... @@ -74,8 +73,8 @@ jshell.err.out.of.range = Out of range jshell.msg.error = Error: jshell.msg.warning = Warning: -jshell.err.set.arg = The ''/set'' command requires a sub-command and arguments. See: ''/help /set'' -jshell.err.set.ambiguous = Ambiguous sub-command argument to ''/set'': {0} +jshell.err.sub.arg = The ''{0}'' command requires a sub-command. See: ''/help {0}'' +jshell.err.sub.ambiguous = Ambiguous sub-command argument to ''{0}'': {1} jshell.err.classpath.arg = The /classpath command requires a path argument. jshell.msg.classpath = Path ''{0}'' added to classpath @@ -91,7 +90,6 @@ For example ''/help /list'' or ''/help intro''. Subjects:\n jshell.err.drop.arg =\ In the /drop argument, please specify an import, variable, method, or class to drop.\n\ Specify by id or name. Use /list to see ids. Use /reset to reset all state. -jshell.err.drop.not.active = The argument did not specify an active import, variable, method, or class to drop. jshell.err.drop.ambiguous = The argument references more than one import, variable, method, or class. jshell.err.failed = Failed. jshell.msg.native.method = Native Method @@ -100,11 +98,12 @@ jshell.msg.goodbye = Goodbye jshell.msg.help.for.help = Type /help for help. -jshell.err.feedback.expected.new.feedback.mode = Expected new feedback mode -- {0} -jshell.err.feedback.expected.mode.name = Expected a new feedback mode name. ''{0}'' is a known feedback mode -- {1} -jshell.err.feedback.command.quiet = Specify either ''command'' or ''quiet'' -- {0} -jshell.err.feedback.expected.field = Expected field name missing -- {0} -jshell.err.feedback.expected.mode = Expected a feedback mode -- {0} +jshell.err.mode.name = Expected a feedback mode name: {0} +jshell.err.missing.mode = Missing the feedback mode -- {0} +jshell.err.field.name = Expected a field name: {0} -- {1} +jshell.err.missing.field = Missing the field name -- {0} +jshell.err.mode.unknown = No feedback mode named: {0} -- {1} + jshell.err.feedback.does.not.match.mode = Does not match any current feedback mode: {0} -- {1} jshell.err.feedback.ambiguous.mode = Matches more then one current feedback mode: {0} -- {1} jshell.err.feedback.expected.format = Expected format missing -- {0} @@ -117,6 +116,25 @@ jshell.msg.feedback.new.mode = Created new feedback mode: {0} jshell.msg.feedback.mode = Feedback mode: {0} jshell.msg.feedback.mode.following = The feedback mode should be one of the following: +jshell.err.truncation.expected.length = Expected truncation length -- {0} +jshell.err.truncation.length.not.integer = Truncation length must be an integer: {0} -- {1} + +jshell.err.not.valid.with.predefined.mode = Not valid with a predefined mode: {0} -- {1} +jshell.err.retained.feedback.mode.must.be.retained.or.predefined = \ +''/retain feedback '' requires that is predefined or has been retained with ''/retain mode'' -- {0} + +jshell.err.unknown.option = Unknown option: {0} -- {1} +jshell.err.default.option.or.program = Specify -default option or program, not both -- {0} +jshell.err.option.or.filename = Specify either one option or a startup file name -- {0} +jshell.err.unexpected.at.end = Unexpected arguments at end of command: {0} -- {1} +jshell.err.conflicting.options = Conflicting options -- {0} +jshell.err.cannot.delete.current.mode = The current feedback mode ''{0}'' cannot be deleted, use ''/set feedback'' first -- {1} +jshell.err.cannot.delete.retained.mode = The retained feedback mode ''{0}'' cannot be deleted, use ''/retain feedback'' first -- {1} +jshell.err.may.not.specify.options.and.snippets = Options and snippets must not both be used: {0} +jshell.err.no.such.snippets = No such snippet: {0} +jshell.err.the.snippet.cannot.be.used.with.this.command = This command does not accept the snippet ''{0}'' : {1} +jshell.err.retained.mode.failure = Failure in retained modes (modes cleared) -- {0} {1} + jshell.console.see.more = jshell.console.do.nothing = Do nothing jshell.console.choice = Choice: \ @@ -148,15 +166,15 @@ where possible options include:\n\ \ -version Version information\n help.list.summary = list the source you have typed -help.list.args = [all|start|] +help.list.args = [|-all|-start] help.list =\ Show the source of snippets, prefaced with the snippet id.\n\ \n\ /list\n\t\ List the currently active snippets of code that you typed or read with /open\n\n\ -/list start\n\t\ +/list -start\n\t\ List the automatically evaluated start-up snippets\n\n\ -/list all\n\t\ +/list -all\n\t\ List all snippets including failed, overwritten, dropped, and start-up\n\n\ /list \n\t\ List snippets with the specified name (preference for active snippets)\n\n\ @@ -188,18 +206,18 @@ Drop a snippet -- making it inactive.\n\ Drop the snippet with the specified snippet id help.save.summary = Save snippet source to a file. -help.save.args = [all|history|start] +help.save.args = [-all|-history|-start] help.save =\ Save the specified snippets and/or commands to the specified file.\n\ \n\ /save \n\t\ Save the source of current active snippets to the file.\n\n\ -/save all \n\t\ +/save -all \n\t\ Save the source of all snippets to the file.\n\t\ Includes source including overwritten, failed, and start-up code.\n\n\ -/save history \n\t\ +/save -history \n\t\ Save the sequential history of all commands and snippets entered since jshell was launched.\n\n\ -/save start \n\t\ +/save -start \n\t\ Save the default start-up definitions to the file. help.open.summary = open a file as source input @@ -211,19 +229,52 @@ Open a file and read its contents as snippets and commands.\n\ Read the specified file as jshell input. help.vars.summary = list the declared variables and their values -help.vars.args = +help.vars.args = [|-all|-start] help.vars =\ -List the type, name, and value of the current active jshell variables. +List the type, name, and value of jshell variables.\n\ +\n\ +/vars\n\t\ + List the type, name, and value of the current active jshell variables\n\n\ +/vars \n\t\ + List jshell variables with the specified name (preference for active variables)\n\n\ +/vars \n\t\ + List the jshell variable with the specified snippet id\n\n\ +/vars -start\n\t\ + List the automatically added start-up jshell variables\n\n\ +/vars -all\n\t\ + List all jshell variables including failed, overwritten, dropped, and start-up help.methods.summary = list the declared methods and their signatures -help.methods.args = +help.methods.args = [|-all|-start] help.methods =\ -List the name, parameter types, and return type of the current active jshell methods. +List the name, parameter types, and return type of jshell methods.\n\ +\n\ +/methods\n\t\ + List the name, parameter types, and return type of the current active jshell methods\n\n\ +/methods \n\t\ + List jshell methods with the specified name (preference for active methods)\n\n\ +/methods \n\t\ + List the jshell method with the specified snippet id\n\n\ +/methods -start\n\t\ + List the automatically added start-up jshell methods\n\n\ +/methods -all\n\t\ + List all snippets including failed, overwritten, dropped, and start-up -help.classes.summary = list the declared classes -help.classes.args = -help.classes =\ -List the current active jshell classes, interfaces, and enums. +help.types.summary = list the declared types +help.types.args =[|-all|-start] +help.types =\ +List jshell classes, interfaces, and enums.\n\ +\n\ +/types\n\t\ + List the current active jshell classes, interfaces, and enums.\n\n\ +/types \n\t\ + List jshell types with the specified name (preference for active types)\n\n\ +/types \n\t\ + List the jshell type with the specified snippet id\n\n\ +/types -start\n\t\ + List the automatically added start-up jshell types\n\n\ +/types -all\n\t\ + List all jshell types including failed, overwritten, dropped, and start-up help.imports.summary = list the imported items help.imports.args = @@ -247,8 +298,8 @@ Reset the jshell tool code and execution state:\n\t\ Tool settings are maintained, as set with: /set ...\n\ Save any work before using this command -help.reload.summary = reset and replay relevant history -- current or previous (restore) -help.reload.args = [restore] [quiet] +help.reload.summary = reset and replay relevant history -- current or previous (-restore) +help.reload.args = [-restore] [-quiet] help.reload =\ Reset the jshell tool code and execution state then replay each\n\ jshell valid command and valid snippet in the order they were entered.\n\ @@ -257,13 +308,13 @@ jshell valid command and valid snippet in the order they were entered.\n\ Reset and replay the valid history since jshell was entered, or\n\t\ a /reset, or /reload command was executed -- whichever is most\n\t\ recent.\n\n\ -/reload restore\n\t\ +/reload -restore\n\t\ Reset and replay the valid history between the previous and most\n\t\ recent time that jshell was entered, or a /reset, or /reload\n\t\ command was executed. This can thus be used to restore a previous\n\t\ jshell tool sesson.\n\n\ -/reload [restore] quiet\n\t\ - With the 'quiet' argument the replay is not shown. Errors will display. +/reload [-restore] -quiet\n\t\ + With the '-quiet' argument the replay is not shown. Errors will display. help.classpath.summary = add a path to the classpath help.classpath.args = @@ -301,7 +352,7 @@ Display information about jshell.\n\ Display information about the specified help subject. Example: /help intro help.set.summary = set jshell configuration information -help.set.args = editor|start|feedback|newmode|prompt|format ... +help.set.args = editor|start|feedback|mode|prompt|truncation|format ... help.set =\ Set jshell configuration information, including:\n\ the external editor to use, the start-up definitions to use, a new feedback mode,\n\ @@ -314,15 +365,36 @@ the command prompt, the feedback mode to use, or the format of output.\n\ The contents of the specified become the default start-up snippets and commands.\n\n\ /set feedback \n\t\ Set the feedback mode describing displayed feedback for entered snippets and commands.\n\n\ -/set newmode [command|quiet []]\n\t\ - Create a user-defined feedback mode, optionally copying from an existing mode.\n\n\ +/set mode [] [-command|-quiet|-delete]\n\t\ + Create or update a user-defined feedback mode, optionally copying from an existing mode.\n\n\ /set prompt "" ""\n\t\ Set the displayed prompts for a given feedback mode.\n\n\ +/set truncation ...\n\t\ + Set the maximum length of a displayed value\n\ /set format "" ...\n\t\ Configure a feedback mode by setting the format of a field when the selector matchs.\n\n\ To get more information about one of these forms, use /help with the form specified.\n\ For example: /help /set format +help.retain.summary = retain jshell configuration information for subsequent sessions +help.retain.args = editor|start|feedback|mode +help.retain =\ +Retain jshell configuration information for future invocations of the jshell tool,\n\ +including: the external editor to use, the start-up definitions to use, the\n\ +configuration of a feedback mode, or the feedback mode to use.\n\ +\n\ +/retain editor [ ...]\n\t\ + Specify the command to launch for the /edit command.\n\t\ + The is an operating system dependent string.\n\n\ +/retain start []\n\t\ + The contents of the specified become the default start-up snippets and commands.\n\n\ +/retain feedback []\n\t\ + Set the feedback mode describing displayed feedback for entered snippets and commands.\n\n\ +/retain mode \n\t\ + Create a user-defined feedback mode, optionally copying from an existing mode.\n\n\ +To get more information about one of these forms, use /help with the form specified.\n\ +For example: /help /retain feedback + help.quest.summary = get information about jshell help.quest.args = [|] help.quest =\ @@ -391,7 +463,7 @@ Set the format for reporting a snippet event.\n\ \n\t\ /set format "" ...\n\ \n\ -Where is the name of a previously defined feedback mode -- see '/help /set newmode'.\n\ +Where is the name of a previously defined feedback mode -- see '/help /set mode'.\n\ Where is the name of context-specific format to define.\n\ Where is a quoted string which will be the value of the field if one of\n\ the selectors matches (or there are no selectors). When the format is used,\n\ @@ -462,6 +534,37 @@ Examples:\n\t\ /set format myformat display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update\n\n\ Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n +help.set.truncation = \ +Set the max length a displayed value.\n\ +\n\t\ +/set truncation ...\n\ +\n\ +Where is the name of a previously defined feedback mode -- see '/help /set mode'.\n\ +Where is an unsigned integer representing a maximum length.\n\ +Where is a quoted string which will be the value of the field if one of\n\ +Where is only needed if you wish to fine-tune value truncation length\n\ +by context, is the context in which the truncation is applied.\n\ +The structure of selector is a hyphen separated list of selector kind lists.\n\ +A selector kind list is a comma separated list of values of one selector kind.\n\ +A selector matches if each selector kind list matches; A selector kind list\n\ +matches if one of the values matches.\n\n\ +Below are the relevant selector kinds for truncation.\n\n\ +The case selector kind describes the kind of snippet. The values are:\n\t\ + vardecl -- variable declaration without init\n\t\ + varinit -- variable declaration with init\n\t\ + expression -- expression -- note: {name}==scratch-variable-name\n\t\ + varvalue -- variable value expression\n\t\ + assignment -- assign variable\n\t\ +The action selector kind describes what happened to the snippet. The values are:\n\t\ + added -- snippet has been added\n\t\ + modified -- an existing snippet has been modified\n\t\ + replaced -- an existing snippet has been replaced with a new snippet\n\ +Examples:\n\t\ +/set trunc mymode 80\n\t\ +/set truncation mymode 45 expression\n\t\ +/set truncation mymode 0 vardecl-modified,replaced\n\n\ +Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n + help.set.feedback = \ Set the feedback mode describing displayed feedback for entered snippets and commands.\n\ \n\t\ @@ -469,18 +572,18 @@ Set the feedback mode describing displayed feedback for entered snippets and com \n\ Where is the name of a previously defined feedback mode.\n\ You may use just enough letters to make it unique.\n\ -User-defined modes can be added, see '/help /set newmode'\n\ +User-defined modes can be added, see '/help /set mode'\n\ Currently defined feedback modes:\n -help.set.newmode = \ +help.set.mode = \ Create a user-defined feedback mode, optionally copying from an existing mode.\n\ \n\t\ -/set newmode [command|quiet []]\n\ +/set mode [] [-command|-quiet|-delete]\n\ \n\ Where is the name of a mode you wish to create.\n\ Where is the name of a previously defined feedback mode.\n\ If is present, its settings are copied to the new mode.\n\ -'command' vs 'quiet' determines if informative/verifying command feedback is displayed.\n\ +'-command' vs '-quiet' determines if informative/verifying command feedback is displayed.\n\ \n\ Once the new mode is created, use '/set format' and '/set prompt' to configure it.\n\ Use '/set feedback' to use the new mode.\n\ @@ -499,22 +602,82 @@ The continuation-prompt is used on the second and subsequent lines of a multi-li help.set.editor =\ Specify the command to launch for the /edit command.\n\ \n\t\ -/set editor ...\n\ +/set editor |-default\n\ \n\ The is an operating system dependent string.\n\ -The may include space-separated arguments (such as flags) -- ....\n\ -When /edit is used, the temporary file to edit will be appended as the last argument. +The may include space-separated arguments (such as flags)\n\ +When /edit is used, the temporary file to edit will be appended as the last argument.\n\ +If instead the -default option is specified, the built-in default editor will be used. help.set.start =\ Set the start-up configuration -- a sequence of snippets and commands read at start-up.\n\ \n\t\ -/set start \n\ +/set start |-default|-none\n\ \n\ -The contents of the specified become the default start-up snippets and commands --\n\ -which are run when the jshell tool is started or reset. +The contents of the specified become the start-up snippets and commands used\n\ +when the /reset or /reload commands are used in this session.\n\ +If instead the -default option is specified, the predefined start-up snippets\n\ +will be used.\n\ +If the -none option is used, the start-up will be empty -- no start-up snippets\n\ +or commands will be used.\n\ +This command is good for testing the start-up settings. To retain them for future\n\ +runs of the jshell tool use the command:\n\t\ +/retain start\n + +help.retain.feedback = \ +Retain which feedback mode to use for displayed feedback for entered snippets and commands.\n\ +This feedback mode will be used in this and future sessions of the jshell tool.\n\ +\n\t\ +/retain feedback []\n\ +\n\ +Where is the name of a previously defined feedback mode.\n\ +You may use just enough letters to make it unique.\n\ +If the is not specified, this command retains the current mode (as set\n\ +with the most recent /set feedback or /retain feedback command.)\n\ + +help.retain.mode = \ +Retain the existence and configuration of a user-defined feedback mode.\n\ +This mode will be available in this and future sessions of the jshell tool. +\n\t\ +/retain mode \n\ +\n\ +Where is the name of a mode you wish to retain.\n\ +The must previously have been created with /set mode and\n\ +configured as desired with /set prompt, /set format, and /set truncation.\n + +help.retain.editor =\ +Retain the command to launch for the /edit command. This command will be invoked when\n\ +the /edit command is used in this and future sessions of the jshell tool.\n\ +\n\t\ +/retain editor [|-default]\n\ +\n\ +If is specified, it is an operating system dependent string which\n\ +may include space-separated arguments (such as flags). When /edit is used, the\n\ +temporary file to edit will be appended as the last argument.\n\ +If instead the -default option is specified, the built-in default editor will be used.\n\ +If neither is specified, the editor set in the last /set editor or /retain editor\n\ +command will be used.\n\ +The editor will be retained and used in this and future runs of the jshell tool. + +help.retain.start =\ +Retain the start-up configuration -- a sequence of snippets and commands read\n\ +at start-up.\n\ +\n\t\ +/retain start [|-default|-none]\n\ +\n\ +If is specified, the contents of the specified become the\n\ +start-up snippets\n\ +and commands.\n\ +If instead the -default option is specified, the predefined start-up snippets\n\ +will be the start-up.\n\ +If the -none option is used, the start-up will be empty -- no start-up snippets\n\ +or commands will be used.\n\ +If none of these is specified, the start-up is the last specified in a\n\ +''/set start'' or ''/retain start'' command.\n\ +The start-up will be retained and used when the jshell tool is started or reset startup.feedback = \ -/set newmode verbose command \n\ +/set mode verbose -command \n\ \n\ /set prompt verbose '\\njshell> ' ' ...> ' \n\ \n\ @@ -564,12 +727,12 @@ startup.feedback = \ \n\ /set format verbose result '{name} ==> {value}{post}' added,modified,replaced-ok-primary \n\ \n\ -/set format verbose display '{result}{pre}created scratch variable {name} : {type}{post}' expression-primary \n\ +/set format verbose display '{result}{pre}created scratch variable {name} : {type}{post}' expression-added,modified,replaced-primary \n\ /set format verbose display '{result}{pre}value of {name} : {type}{post}' varvalue-primary \n\ /set format verbose display '{result}{pre}assigned to {name} : {type}{post}' assignment-primary \n\ /set format verbose display '{result}{pre}{action} variable {name} : {type}{resolve}{post}' varinit,vardecl \n\ /set format verbose display '{pre}{action} variable {name}{resolve}{post}' vardecl,varinit-notdefined \n\ -/set format verbose display '{pre}{action} variable {name}{post}' dropped-vardecl,varinit \n\ +/set format verbose display '{pre}{action} variable {name}{post}' dropped-vardecl,varinit,expression \n\ /set format verbose display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update \n\ \n\ /set format verbose display '{pre}{action} {typeKind} {name}{resolve}{post}' class,interface,enum,annotation \n\ @@ -578,11 +741,14 @@ startup.feedback = \ /set format verbose display '{pre}attempted to use {typeKind} {name}{resolve}{post}' used-class,interface,enum,annotation \n\ /set format verbose display '{pre}attempted to call method {name}({type}){resolve}{post}' used-method \n\ \n\ -/set newmode normal command verbose \n\ +/set truncation verbose 80\n\ +/set truncation verbose 1000 varvalue,expression\n\ +\n\ +/set mode normal -command verbose \n\ /set format normal display '' added,modified,replaced,overwrote,dropped-update \n\ /set format normal display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update \n\ /set format normal display '{result}' added,modified,replaced-expression,varvalue,assignment,varinit,vardecl-ok-primary \n\ -/set newmode concise quiet normal \n\ +/set mode concise -quiet normal \n\ \n\ /set prompt concise 'jshell> ' ' ...> ' \n\ \n\ @@ -590,7 +756,7 @@ startup.feedback = \ \n\ /set feedback normal \n\ \n\ -/set newmode silent quiet \n\ +/set mode silent -quiet \n\ /set prompt silent '-> ' '>> ' \n\ /set format silent pre '| ' \n\ /set format silent post '%n' \n\ diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java index ce9ee86658d..8cb482815de 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java @@ -49,6 +49,8 @@ import static com.sun.tools.javac.code.Flags.STATIC; import static com.sun.tools.javac.code.Flags.INTERFACE; import static com.sun.tools.javac.code.Flags.ENUM; import static com.sun.tools.javac.code.Flags.PUBLIC; +import com.sun.tools.javac.util.Name; +import jdk.jshell.spi.SPIResolutionException; /** * Produce a corralled version of the Wrap for a snippet. @@ -129,16 +131,22 @@ class Corraller extends Pretty { super.visitClassDef(tree); } + // Build a compiler tree for an exception throwing block, e.g.: + // { + // throw new jdk.jshell.spi.SPIResolutionException(9); + // } private JCBlock resolutionExceptionBlock() { if (resolutionExceptionBlock == null) { - JCExpression expClass - = make.Select(make.Select(make.Select(make.Select( - make.Ident(names.fromString("jdk")), - names.fromString("internal")), - names.fromString("jshell")), - names.fromString("remote")), - names.fromString("RemoteResolutionException") - ); + JCExpression expClass = null; + // Split the exception class name at dots + for (String id : SPIResolutionException.class.getName().split("\\.")) { + Name nm = names.fromString(id); + if (expClass == null) { + expClass = make.Ident(nm); + } else { + expClass = make.Select(expClass, nm); + } + } JCNewClass exp = make.NewClass(null, null, expClass, List.of(make.Literal(keyIndex)), null); resolutionExceptionBlock = make.Block(0L, List.of( diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index 1d8af24b28c..6e0a3ca8239 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java @@ -49,7 +49,6 @@ import java.io.StringWriter; import java.io.Writer; import java.util.LinkedHashSet; import java.util.Set; -import jdk.jshell.ClassTracker.ClassInfo; import jdk.jshell.Key.ErroneousKey; import jdk.jshell.Key.MethodKey; import jdk.jshell.Key.TypeDeclKey; @@ -64,9 +63,9 @@ import jdk.jshell.Snippet.Status; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; -import static jdk.jshell.Util.*; -import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; -import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; +import static jdk.jshell.Util.DOIT_METHOD_NAME; +import static jdk.jshell.Util.PREFIX_PATTERN; +import static jdk.jshell.Util.expunge; import static jdk.jshell.Snippet.SubKind.SINGLE_TYPE_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.SINGLE_STATIC_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.TYPE_IMPORT_ON_DEMAND_SUBKIND; @@ -456,7 +455,7 @@ class Eval { if (si.status().isDefined) { if (si.isExecutable()) { try { - value = state.executionControl().commandInvoke(si.classFullName()); + value = state.executionControl().invoke(si.classFullName(), DOIT_METHOD_NAME); value = si.subKind().hasValue() ? expunge(value) : ""; @@ -578,7 +577,7 @@ class Eval { // load all new classes load(legit.stream() - .flatMap(u -> u.classesToLoad(ct.classInfoList(u.snippet().outerWrap()))) + .flatMap(u -> u.classesToLoad(ct.classList(u.snippet().outerWrap()))) .collect(toSet())); // attempt to redefine the remaining classes List toReplace = legit.stream() @@ -613,9 +612,13 @@ class Eval { } } - private void load(Set cil) { - if (!cil.isEmpty()) { - state.executionControl().commandLoad(cil); + /** + * If there are classes to load, loads by calling the execution engine. + * @param classnames names of the classes to load. + */ + private void load(Collection classnames) { + if (!classnames.isEmpty()) { + state.executionControl().load(classnames); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java deleted file mode 100644 index f28323e178c..00000000000 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ - -package jdk.jshell; - -import static jdk.internal.jshell.remote.RemoteCodes.*; -import java.io.DataInputStream; -import java.io.InputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.PrintStream; -import java.net.ServerSocket; -import java.net.Socket; -import com.sun.jdi.*; -import java.io.EOFException; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import jdk.jshell.ClassTracker.ClassInfo; -import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; - -/** - * Controls the remote execution environment. - * - * @author Robert Field - */ -class ExecutionControl { - - private final JDIEnv env; - private final SnippetMaps maps; - private JDIEventHandler handler; - private Socket socket; - private ObjectInputStream in; - private ObjectOutputStream out; - private final JShell proc; - private final String remoteVMOptions; - - ExecutionControl(JDIEnv env, SnippetMaps maps, JShell proc, List extraRemoteVMOptions) { - this.env = env; - this.maps = maps; - this.proc = proc; - StringBuilder sb = new StringBuilder(); - extraRemoteVMOptions.stream() - .forEach(s -> { - sb.append(" "); - sb.append(s); - }); - this.remoteVMOptions = sb.toString(); - } - - void launch() throws IOException { - try (ServerSocket listener = new ServerSocket(0)) { - // timeout after 60 seconds - listener.setSoTimeout(60000); - int port = listener.getLocalPort(); - jdiGo(port); - socket = listener.accept(); - // out before in -- match remote creation so we don't hang - out = new ObjectOutputStream(socket.getOutputStream()); - PipeInputStream commandIn = new PipeInputStream(); - new DemultiplexInput(socket.getInputStream(), commandIn, proc.out, proc.err).start(); - in = new ObjectInputStream(commandIn); - } - } - - void commandExit() { - try { - if (out != null) { - out.writeInt(CMD_EXIT); - out.flush(); - } - JDIConnection c = env.connection(); - if (c != null) { - c.disposeVM(); - } - } catch (IOException ex) { - proc.debug(DBG_GEN, "Exception on JDI exit: %s\n", ex); - } - } - - - boolean commandLoad(Collection cil) { - try { - out.writeInt(CMD_LOAD); - out.writeInt(cil.size()); - for (ClassInfo ci : cil) { - out.writeUTF(ci.getClassName()); - out.writeObject(ci.getBytes()); - } - out.flush(); - return readAndReportResult(); - } catch (IOException ex) { - proc.debug(DBG_GEN, "IOException on remote load operation: %s\n", ex); - return false; - } - } - - String commandInvoke(String classname) throws JShellException { - try { - synchronized (STOP_LOCK) { - userCodeRunning = true; - } - out.writeInt(CMD_INVOKE); - out.writeUTF(classname); - out.flush(); - if (readAndReportExecutionResult()) { - String result = in.readUTF(); - return result; - } - } catch (IOException | RuntimeException ex) { - if (!env.connection().isRunning()) { - env.shutdown(); - } else { - proc.debug(DBG_GEN, "Exception on remote invoke: %s\n", ex); - return "Execution failure: " + ex.getMessage(); - } - } finally { - synchronized (STOP_LOCK) { - userCodeRunning = false; - } - } - return ""; - } - - String commandVarValue(String classname, String varname) { - try { - out.writeInt(CMD_VARVALUE); - out.writeUTF(classname); - out.writeUTF(varname); - out.flush(); - if (readAndReportResult()) { - String result = in.readUTF(); - return result; - } - } catch (EOFException ex) { - env.shutdown(); - } catch (IOException ex) { - proc.debug(DBG_GEN, "Exception on remote var value: %s\n", ex); - return "Execution failure: " + ex.getMessage(); - } - return ""; - } - - boolean commandAddToClasspath(String cp) { - try { - out.writeInt(CMD_CLASSPATH); - out.writeUTF(cp); - out.flush(); - return readAndReportResult(); - } catch (IOException ex) { - throw new InternalError("Classpath addition failed: " + cp, ex); - } - } - - boolean commandRedefine(Map mp) { - try { - env.vm().redefineClasses(mp); - return true; - } catch (UnsupportedOperationException ex) { - return false; - } catch (Exception ex) { - proc.debug(DBG_GEN, "Exception on JDI redefine: %s\n", ex); - return false; - } - } - - ReferenceType nameToRef(String name) { - List rtl = env.vm().classesByName(name); - if (rtl.size() != 1) { - return null; - } - return rtl.get(0); - } - - private boolean readAndReportResult() throws IOException { - int ok = in.readInt(); - switch (ok) { - case RESULT_SUCCESS: - return true; - case RESULT_FAIL: { - String ex = in.readUTF(); - proc.debug(DBG_GEN, "Exception on remote operation: %s\n", ex); - return false; - } - default: { - proc.debug(DBG_GEN, "Bad remote result code: %s\n", ok); - return false; - } - } - } - - private boolean readAndReportExecutionResult() throws IOException, JShellException { - int ok = in.readInt(); - switch (ok) { - case RESULT_SUCCESS: - return true; - case RESULT_FAIL: { - String ex = in.readUTF(); - proc.debug(DBG_GEN, "Exception on remote operation: %s\n", ex); - return false; - } - case RESULT_EXCEPTION: { - String exceptionClassName = in.readUTF(); - String message = in.readUTF(); - StackTraceElement[] elems = readStackTrace(); - EvalException ee = new EvalException(message, exceptionClassName, elems); - throw ee; - } - case RESULT_CORRALLED: { - int id = in.readInt(); - StackTraceElement[] elems = readStackTrace(); - Snippet si = maps.getSnippetDeadOrAlive(id); - throw new UnresolvedReferenceException((DeclarationSnippet) si, elems); - } - case RESULT_KILLED: { - proc.out.println("Killed."); - return false; - } - default: { - proc.debug(DBG_GEN, "Bad remote result code: %s\n", ok); - return false; - } - } - } - - private StackTraceElement[] readStackTrace() throws IOException { - int elemCount = in.readInt(); - StackTraceElement[] elems = new StackTraceElement[elemCount]; - for (int i = 0; i < elemCount; ++i) { - String className = in.readUTF(); - String methodName = in.readUTF(); - String fileName = in.readUTF(); - int line = in.readInt(); - elems[i] = new StackTraceElement(className, methodName, fileName, line); - } - return elems; - } - - private void jdiGo(int port) { - //MessageOutput.textResources = ResourceBundle.getBundle("impl.TTYResources", - // Locale.getDefault()); - - String connectorName = "com.sun.jdi.CommandLineLaunch"; - Map argumentName2Value = new HashMap<>(); - argumentName2Value.put("main", "jdk.internal.jshell.remote.RemoteAgent " + port); - argumentName2Value.put("options", remoteVMOptions); - - boolean launchImmediately = true; - int traceFlags = 0;// VirtualMachine.TRACE_SENDS | VirtualMachine.TRACE_EVENTS; - - env.init(connectorName, argumentName2Value, launchImmediately, traceFlags); - - if (env.connection().isOpen() && env.vm().canBeModified()) { - /* - * Connection opened on startup. Start event handler - * immediately, telling it (through arg 2) to stop on the - * VM start event. - */ - handler = new JDIEventHandler(env); - } - } - - private final Object STOP_LOCK = new Object(); - private boolean userCodeRunning = false; - - void commandStop() { - synchronized (STOP_LOCK) { - if (!userCodeRunning) - return ; - - VirtualMachine vm = handler.env.vm(); - vm.suspend(); - try { - OUTER: for (ThreadReference thread : vm.allThreads()) { - // could also tag the thread (e.g. using name), to find it easier - for (StackFrame frame : thread.frames()) { - String remoteAgentName = "jdk.internal.jshell.remote.RemoteAgent"; - if (remoteAgentName.equals(frame.location().declaringType().name()) && - "commandLoop".equals(frame.location().method().name())) { - ObjectReference thiz = frame.thisObject(); - if (((BooleanValue) thiz.getValue(thiz.referenceType().fieldByName("inClientCode"))).value()) { - thiz.setValue(thiz.referenceType().fieldByName("expectingStop"), vm.mirrorOf(true)); - ObjectReference stopInstance = (ObjectReference) thiz.getValue(thiz.referenceType().fieldByName("stopException")); - - vm.resume(); - proc.debug(DBG_GEN, "Attempting to stop the client code...\n"); - thread.stop(stopInstance); - thiz.setValue(thiz.referenceType().fieldByName("expectingStop"), vm.mirrorOf(false)); - } - - break OUTER; - } - } - } - } catch (ClassNotLoadedException | IncompatibleThreadStateException | InvalidTypeException ex) { - proc.debug(DBG_GEN, "Exception on remote stop: %s\n", ex); - } finally { - vm.resume(); - } - } - } - - private final class DemultiplexInput extends Thread { - - private final DataInputStream delegate; - private final PipeInputStream command; - private final PrintStream out; - private final PrintStream err; - - public DemultiplexInput(InputStream input, - PipeInputStream command, - PrintStream out, - PrintStream err) { - super("output reader"); - this.delegate = new DataInputStream(input); - this.command = command; - this.out = out; - this.err = err; - } - - public void run() { - try { - while (true) { - int nameLen = delegate.read(); - if (nameLen == (-1)) - break; - byte[] name = new byte[nameLen]; - DemultiplexInput.this.delegate.readFully(name); - int dataLen = delegate.read(); - byte[] data = new byte[dataLen]; - DemultiplexInput.this.delegate.readFully(data); - switch (new String(name, "UTF-8")) { - case "err": - err.write(data); - break; - case "out": - out.write(data); - break; - case "command": - for (byte b : data) { - command.write(Byte.toUnsignedInt(b)); - } - break; - } - } - } catch (IOException ex) { - proc.debug(ex, "Failed reading output"); - } finally { - command.close(); - } - } - - } - - public static final class PipeInputStream extends InputStream { - public static final int INITIAL_SIZE = 128; - - private int[] buffer = new int[INITIAL_SIZE]; - private int start; - private int end; - private boolean closed; - - @Override - public synchronized int read() { - while (start == end) { - if (closed) { - return -1; - } - try { - wait(); - } catch (InterruptedException ex) { - //ignore - } - } - try { - return buffer[start]; - } finally { - start = (start + 1) % buffer.length; - } - } - - public synchronized void write(int b) { - if (closed) - throw new IllegalStateException("Already closed."); - int newEnd = (end + 1) % buffer.length; - if (newEnd == start) { - //overflow: - int[] newBuffer = new int[buffer.length * 2]; - int rightPart = (end > start ? end : buffer.length) - start; - int leftPart = end > start ? 0 : start - 1; - System.arraycopy(buffer, start, newBuffer, 0, rightPart); - System.arraycopy(buffer, 0, newBuffer, rightPart, leftPart); - buffer = newBuffer; - start = 0; - end = rightPart + leftPart; - newEnd = end + 1; - } - buffer[end] = b; - end = newEnd; - notifyAll(); - } - - @Override - public synchronized void close() { - closed = true; - notifyAll(); - } - - } -} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java index d906b39d8c2..bf2ec5e22ae 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java @@ -101,6 +101,6 @@ public class ImportSnippet extends PersistentSnippet { @Override String importLine(JShell state) { - return source(); + return guts().wrapped(); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java index 8b95bbdc7ff..f2a1496873c 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java @@ -25,6 +25,7 @@ package jdk.jshell; +import jdk.jshell.spi.ExecutionControl; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.PrintStream; @@ -47,6 +48,8 @@ import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toList; import static jdk.jshell.Util.expunge; import jdk.jshell.Snippet.Status; +import jdk.internal.jshell.jdi.JDIExecutionControl; +import jdk.jshell.spi.ExecutionEnv; /** * The JShell evaluation state engine. This is the central class in the JShell @@ -71,7 +74,6 @@ import jdk.jshell.Snippet.Status; *

    * This class is not thread safe, except as noted, all access should be through * a single thread. - * @see jdk.jshell * @author Robert Field */ public class JShell implements AutoCloseable { @@ -86,16 +88,17 @@ public class JShell implements AutoCloseable { final Supplier tempVariableNameGenerator; final BiFunction idGenerator; final List extraRemoteVMOptions; + final ExecutionControl executionControl; private int nextKeyIndex = 1; final Eval eval; - final ClassTracker classTracker; + private final Map classnameToBytes = new HashMap<>(); private final Map> shutdownListeners = new HashMap<>(); private final Map> keyStatusListeners = new HashMap<>(); private boolean closed = false; - private ExecutionControl executionControl = null; + private boolean executionControlLaunched = false; private SourceCodeAnalysisImpl sourceCodeAnalysis = null; private static final String L10N_RB_NAME = "jdk.jshell.resources.l10n"; @@ -108,13 +111,15 @@ public class JShell implements AutoCloseable { this.tempVariableNameGenerator = b.tempVariableNameGenerator; this.idGenerator = b.idGenerator; this.extraRemoteVMOptions = b.extraRemoteVMOptions; + this.executionControl = b.executionControl==null + ? new JDIExecutionControl() + : b.executionControl; this.maps = new SnippetMaps(this); this.keyMap = new KeyMap(this); this.outerMap = new OuterWrapMap(this); this.taskFactory = new TaskFactory(this); this.eval = new Eval(this); - this.classTracker = new ClassTracker(this); } /** @@ -143,22 +148,23 @@ public class JShell implements AutoCloseable { Supplier tempVariableNameGenerator = null; BiFunction idGenerator = null; List extraRemoteVMOptions = new ArrayList<>(); + ExecutionControl executionControl; Builder() { } /** - * Input for the running evaluation (it's System.in). Note: - * applications that use System.in for snippet or other - * user input cannot use System.in as the input stream for + * Sets the input for the running evaluation (it's {@code System.in}). Note: + * applications that use {@code System.in} for snippet or other + * user input cannot use {@code System.in} as the input stream for * the remote process. *

    * The default, if this is not set, is to provide an empty input stream - * -- new ByteArrayInputStream(new byte[0]). + * -- {@code new ByteArrayInputStream(new byte[0])}. * - * @param in the InputStream to be channelled to - * System.in in the remote execution process. - * @return the Builder instance (for use in chained - * initialization). + * @param in the {@code InputStream} to be channelled to + * {@code System.in} in the remote execution process + * @return the {@code Builder} instance (for use in chained + * initialization) */ public Builder in(InputStream in) { this.in = in; @@ -166,16 +172,16 @@ public class JShell implements AutoCloseable { } /** - * Output for the running evaluation (it's System.out). + * Sets the output for the running evaluation (it's {@code System.out}). * The controlling process and - * the remote process can share System.out. + * the remote process can share {@code System.out}. *

    - * The default, if this is not set, is System.out. + * The default, if this is not set, is {@code System.out}. * - * @param out the PrintStream to be channelled to - * System.out in the remote execution process. - * @return the Builder instance (for use in chained - * initialization). + * @param out the {@code PrintStream} to be channelled to + * {@code System.out} in the remote execution process + * @return the {@code Builder} instance (for use in chained + * initialization) */ public Builder out(PrintStream out) { this.out = out; @@ -183,16 +189,16 @@ public class JShell implements AutoCloseable { } /** - * Error output for the running evaluation (it's - * System.err). The controlling process and the remote - * process can share System.err. + * Sets the error output for the running evaluation (it's + * {@code System.err}). The controlling process and the remote + * process can share {@code System.err}. *

    - * The default, if this is not set, is System.err. + * The default, if this is not set, is {@code System.err}. * - * @param err the PrintStream to be channelled to - * System.err in the remote execution process. - * @return the Builder instance (for use in chained - * initialization). + * @param err the {@code PrintStream} to be channelled to + * {@code System.err} in the remote execution process + * @return the {@code Builder} instance (for use in chained + * initialization) */ public Builder err(PrintStream err) { this.err = err; @@ -200,7 +206,7 @@ public class JShell implements AutoCloseable { } /** - * Set a generator of temp variable names for + * Sets a generator of temp variable names for * {@link jdk.jshell.VarSnippet} of * {@link jdk.jshell.Snippet.SubKind#TEMP_VAR_EXPRESSION_SUBKIND}. *

    @@ -221,9 +227,9 @@ public class JShell implements AutoCloseable { * prefixing dollar sign ("$"). * * @param generator the Supplier to generate the temporary - * variable name string or null. - * @return the Builder instance (for use in chained - * initialization). + * variable name string or null + * @return the {@code Builder} instance (for use in chained + * initialization) */ public Builder tempVariableNameGenerator(Supplier generator) { this.tempVariableNameGenerator = generator; @@ -231,7 +237,7 @@ public class JShell implements AutoCloseable { } /** - * Set the generator of identifying names for Snippets. + * Sets the generator of identifying names for Snippets. *

    * Do not use this method unless you have explicit need for it. *

    @@ -258,9 +264,9 @@ public class JShell implements AutoCloseable { * is null) is to generate the id as the integer converted to a string. * * @param generator the BiFunction to generate the id - * string or null. - * @return the Builder instance (for use in chained - * initialization). + * string or null + * @return the {@code Builder} instance (for use in chained + * initialization) */ public Builder idGenerator(BiFunction generator) { this.idGenerator = generator; @@ -268,11 +274,11 @@ public class JShell implements AutoCloseable { } /** - * Set additional VM options for launching the VM. + * Sets additional VM options for launching the VM. * - * @param options The options for the remote VM. - * @return the Builder instance (for use in chained - * initialization). + * @param options The options for the remote VM + * @return the {@code Builder} instance (for use in chained + * initialization) */ public Builder remoteVMOptions(String... options) { this.extraRemoteVMOptions.addAll(Arrays.asList(options)); @@ -280,11 +286,24 @@ public class JShell implements AutoCloseable { } /** - * Build a JShell state engine. This is the entry-point to all JShell + * Sets the custom engine for execution. Snippet execution will be + * provided by the specified {@link ExecutionControl} instance. + * + * @param execEngine the execution engine + * @return the {@code Builder} instance (for use in chained + * initialization) + */ + public Builder executionEngine(ExecutionControl execEngine) { + this.executionControl = execEngine; + return this; + } + + /** + * Builds a JShell state engine. This is the entry-point to all JShell * functionality. This creates a remote process for execution. It is * thus important to close the returned instance. * - * @return the state engine. + * @return the state engine */ public JShell build() { return new JShell(this); @@ -406,7 +425,7 @@ public class JShell implements AutoCloseable { */ public void addToClasspath(String path) { taskFactory.addToClasspath(path); // Compiler - executionControl().commandAddToClasspath(path); // Runtime + executionControl().addToClasspath(path); // Runtime if (sourceCodeAnalysis != null) { sourceCodeAnalysis.classpathChanged(); } @@ -427,7 +446,7 @@ public class JShell implements AutoCloseable { */ public void stop() { if (executionControl != null) - executionControl.commandStop(); + executionControl.stop(); } /** @@ -438,7 +457,7 @@ public class JShell implements AutoCloseable { public void close() { if (!closed) { closeDown(); - executionControl().commandExit(); + executionControl().close(); } } @@ -580,7 +599,7 @@ public class JShell implements AutoCloseable { throw new IllegalArgumentException( messageFormat("jshell.exc.var.not.valid", snippet, snippet.status())); } - String value = executionControl().commandVarValue(snippet.classFullName(), snippet.name()); + String value = executionControl().varValue(snippet.classFullName(), snippet.name()); return expunge(value); } @@ -633,35 +652,86 @@ public class JShell implements AutoCloseable { } } - // --- private / package-private implementation support --- + /** + * Provide the environment for a execution engine. + */ + class ExecutionEnvImpl implements ExecutionEnv { + @Override + public InputStream userIn() { + return in; + } + + @Override + public PrintStream userOut() { + return out; + } + + @Override + public PrintStream userErr() { + return err; + } + + @Override + public JShell state() { + return JShell.this; + } + + @Override + public List extraRemoteVMOptions() { + return extraRemoteVMOptions; + } + + @Override + public byte[] getClassBytes(String classname) { + return classnameToBytes.get(classname); + } + + @Override + public EvalException createEvalException(String message, String exceptionClass, StackTraceElement[] stackElements) { + return new EvalException(message, exceptionClass, stackElements); + } + + @Override + public UnresolvedReferenceException createUnresolvedReferenceException(int id, StackTraceElement[] stackElements) { + DeclarationSnippet sn = (DeclarationSnippet) maps.getSnippetDeadOrAlive(id); + return new UnresolvedReferenceException(sn, stackElements); + } + + @Override + public void closeDown() { + JShell.this.closeDown(); + } + } + + // --- private / package-private implementation support --- ExecutionControl executionControl() { - if (executionControl == null) { - this.executionControl = new ExecutionControl(new JDIEnv(this), maps, this, extraRemoteVMOptions); + if (!executionControlLaunched) { try { - executionControl.launch(); + executionControlLaunched = true; + executionControl.start(new ExecutionEnvImpl()); } catch (Throwable ex) { - throw new InternalError("Launching JDI execution engine threw: " + ex.getMessage(), ex); + throw new InternalError("Launching execution engine threw: " + ex.getMessage(), ex); } } return executionControl; } + void setClassnameToBytes(String classname, byte[] bytes) { + classnameToBytes.put(classname, bytes); + } + void debug(int flags, String format, Object... args) { - if (InternalDebugControl.debugEnabled(this, flags)) { - err.printf(format, args); - } + InternalDebugControl.debug(this, err, flags, format, args); } void debug(Exception ex, String where) { - if (InternalDebugControl.debugEnabled(this, 0xFFFFFFFF)) { - err.printf("Fatal error: %s: %s\n", where, ex.getMessage()); - ex.printStackTrace(err); - } + InternalDebugControl.debug(this, err, ex, where); } /** * Generate the next key index, indicating a unique snippet signature. + * * @return the next key index */ int nextKeyIndex() { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java index f61d8b487d4..8cb1ae848a1 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java @@ -28,9 +28,11 @@ package jdk.jshell; import java.util.Locale; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import jdk.internal.jshell.remote.RemoteCodes; -import static jdk.jshell.Util.*; -import static jdk.internal.jshell.remote.RemoteCodes.REPL_PACKAGE; +import static jdk.jshell.Util.PARSED_LOCALE; +import static jdk.jshell.Util.REPL_CLASS_PREFIX; +import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; +import static jdk.jshell.Util.REPL_PACKAGE; +import static jdk.jshell.Util.expunge; /** * @@ -163,7 +165,7 @@ class OuterWrap implements GeneralWrap { } for (String line : diag.getMessage(PARSED_LOCALE).split("\\r?\\n")) { if (line.trim().startsWith("location:")) { - if (!line.contains(RemoteCodes.REPL_CLASS_PREFIX)) { + if (!line.contains(REPL_CLASS_PREFIX)) { // Resolution error must occur within a REPL class or it is not resolvable return false; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java index 1576ebe7725..29f4351f691 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java @@ -35,8 +35,8 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.stream.Collectors; import jdk.jshell.Wrap.CompoundWrap; -import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; -import static jdk.internal.jshell.remote.RemoteCodes.REPL_CLASS_PREFIX; +import static jdk.jshell.Util.PREFIX_PATTERN; +import static jdk.jshell.Util.REPL_CLASS_PREFIX; import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; import static jdk.jshell.Util.asLetters; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java index 9d0a48505d8..7c2dc38d2f7 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java @@ -38,9 +38,9 @@ import java.util.regex.Matcher; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; -import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; +import static jdk.jshell.Util.PREFIX_PATTERN; +import static jdk.jshell.Util.REPL_PACKAGE; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP; -import static jdk.internal.jshell.remote.RemoteCodes.REPL_PACKAGE; /** * Maintain relationships between the significant entities: Snippets, diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index 50959ba539a..efbd2c700e7 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -104,7 +104,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; @@ -130,6 +129,7 @@ import javax.tools.StandardLocation; import javax.tools.ToolProvider; import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; +import static java.util.stream.Collectors.joining; /** * The concrete implementation of SourceCodeAnalysis. diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java index fe0a3b73f74..df6d856be8a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java @@ -60,8 +60,7 @@ import java.util.stream.Stream; import javax.lang.model.util.Elements; import javax.tools.FileObject; import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject; -import jdk.jshell.ClassTracker.ClassInfo; -import jdk.Version; +import java.lang.Runtime.Version; /** * The primary interface to the compiler API. Parsing, analysis, and @@ -278,13 +277,19 @@ class TaskFactory { return result; } - - List classInfoList(OuterWrap w) { + // Returns the list of classes generated during this compile. + // Stores the mapping between class name and current compiled bytes. + List classList(OuterWrap w) { List l = classObjs.get(w); - if (l == null) return Collections.emptyList(); - return l.stream() - .map(fo -> state.classTracker.classInfo(fo.getName(), fo.getBytes())) - .collect(Collectors.toList()); + if (l == null) { + return Collections.emptyList(); + } + List list = new ArrayList<>(); + for (OutputMemoryJavaFileObject fo : l) { + state.setClassnameToBytes(fo.getName(), fo.getBytes()); + list.add(fo.getName()); + } + return list; } private void listenForNewClassFile(OutputMemoryJavaFileObject jfo, JavaFileManager.Location location, diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java index 987dc6bc93e..bc1839eddf6 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java @@ -30,18 +30,14 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.stream.Stream; -import com.sun.jdi.ReferenceType; import jdk.jshell.Snippet.Kind; import jdk.jshell.Snippet.Status; import jdk.jshell.Snippet.SubKind; import jdk.jshell.TaskFactory.AnalyzeTask; -import jdk.jshell.ClassTracker.ClassInfo; import jdk.jshell.TaskFactory.CompileTask; import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_EVNT; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; @@ -79,7 +75,7 @@ final class Unit { private SnippetEvent replaceOldEvent; private List secondaryEvents; private boolean isAttemptingCorral; - private List toRedefine; + private List toRedefine; private boolean dependenciesNeeded; Unit(JShell state, Snippet si, Snippet causalSnippet, @@ -260,10 +256,6 @@ final class Unit { si, status); } - /** - * Must be called for each unit - * @return - */ boolean isDefined() { return status.isDefined; } @@ -273,21 +265,28 @@ final class Unit { * Requires loading of returned list. * @return the list of classes to load */ - Stream classesToLoad(List cil) { + Stream classesToLoad(List classnames) { toRedefine = new ArrayList<>(); - List toLoad = new ArrayList<>(); + List toLoad = new ArrayList<>(); if (status.isDefined && !isImport()) { - cil.stream().forEach(ci -> { - if (!ci.isLoaded()) { - if (ci.getReferenceTypeOrNull() == null) { - toLoad.add(ci); - ci.setLoaded(); + // Classes should only be loaded/redefined if the compile left them + // in a defined state. Imports do not have code and are not loaded. + for (String cn : classnames) { + switch (state.executionControl().getClassStatus(cn)) { + case UNKNOWN: + // If not loaded, add to the list of classes to load. + toLoad.add(cn); dependenciesNeeded = true; - } else { - toRedefine.add(ci); - } + break; + case NOT_CURRENT: + // If loaded but out of date, add to the list of classes to attempt redefine. + toRedefine.add(cn); + break; + case CURRENT: + // Loaded and current, so nothing to do + break; } - }); + } } return toLoad.stream(); } @@ -298,19 +297,9 @@ final class Unit { * @return true if all redefines succeeded (can be vacuously true) */ boolean doRedefines() { - if (toRedefine.isEmpty()) { - return true; - } - Map mp = toRedefine.stream() - .collect(toMap(ci -> ci.getReferenceTypeOrNull(), ci -> ci.getBytes())); - if (state.executionControl().commandRedefine(mp)) { - // success, mark as loaded - toRedefine.stream().forEach(ci -> ci.setLoaded()); - return true; - } else { - // failed to redefine - return false; - } + return toRedefine.isEmpty() + ? true + : state.executionControl().redefine(toRedefine); } void markForReplacement() { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java index 413c30baa13..3127753e2bf 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -29,20 +29,40 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; +import java.util.regex.Pattern; import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.lang.model.element.Name; -import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; -import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; -import static jdk.internal.jshell.remote.RemoteCodes.REPL_CLASS_PREFIX; /** - * Assorted shared utilities. - * @author Robert Field + * Assorted shared utilities and constants. */ class Util { - static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX+"DOESNOTMATTER"; + /** + * The package name of all wrapper classes. + */ + static final String REPL_PACKAGE = "REPL"; + + /** + * The prefix for all wrapper class names. + */ + static final String REPL_CLASS_PREFIX = "$JShell$"; + + /** + * The name of the invoke method. + */ + static final String DOIT_METHOD_NAME = "do_it$"; + + /** + * A pattern matching the full or simple class name of a wrapper class. + */ + static final Pattern PREFIX_PATTERN = Pattern.compile( + "(" + REPL_PACKAGE + "\\.)?" + + "(?" + Pattern.quote(REPL_CLASS_PREFIX) + + "\\w+" + ")" + "[\\$\\.]?"); + + static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX + "DOESNOTMATTER"; static final Locale PARSED_LOCALE = Locale.ROOT; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java index 873a0d1cce8..3b4e4cbfc35 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java @@ -27,7 +27,7 @@ package jdk.jshell; import java.util.Arrays; import static java.util.stream.Collectors.joining; -import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; +import static jdk.jshell.Util.DOIT_METHOD_NAME; /** * Wrapping of source into Java methods, fields, etc. All but outer layer diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionControl.java new file mode 100644 index 00000000000..d0af4baaf50 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionControl.java @@ -0,0 +1,154 @@ +/* + * 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.jshell.spi; + +import java.util.Collection; +import jdk.jshell.JShellException; + +/** + * This interface specifies the functionality that must provided to implement + * a pluggable JShell execution engine. + *

    + * The audience for this Service Provider Interface is engineers + * wishing to implement their own version of the execution engine in support + * of the JShell API. This is NOT a part of the JShell API. + *

    + * A Snippet is compiled into code wrapped in a 'wrapper class'. The execution + * engine is used by the core JShell implementation to load and, for + * executable Snippets, execute the Snippet. + *

    + * Methods defined in this interface should only be called by the core JShell + * implementation. + *

    + * To install an instance of ExecutionControl, it is passed to + * {@link jdk.jshell.JShell.Builder#executionEngine(jdk.jshell.spi.ExecutionControl) }. + */ +public interface ExecutionControl { + + /** + * Represents the current status of a class in the execution engine. + */ + public enum ClassStatus { + /** + * Class is not known to the execution engine (not loaded). + */ + UNKNOWN, + + /** + * Class is loaded, but the loaded/redefined bytes do not match those + * returned by {@link ExecutionEnv#getClassBytes(java.lang.String) }. + */ + NOT_CURRENT, + + /** + * Class is loaded and loaded/redefined bytes match those + * returned by {@link ExecutionEnv#getClassBytes(java.lang.String) }. + */ + CURRENT + }; + + /** + * Initializes the instance. No methods in this interface can be called + * before this. + * + * @param env the execution environment information provided by JShell + * @throws Exception if the instance is unable to initialize + */ + void start(ExecutionEnv env) throws Exception; + + /** + * Shuts down this execution engine. Implementation should free all + * resources held by this execution engine. + *

    + * No calls to methods on this interface should be made after close. + */ + void close(); + + /** + * Adds the path to the execution class path. + * + * @param path the path to add + * @return true if successful + */ + boolean addToClasspath(String path); + + /** + * Invokes an executable Snippet by calling a method on the specified + * wrapper class. The method must have no arguments and return String. + * + * @param classname the class whose method should be invoked + * @param methodname the name of method to invoke + * @return the result of the execution or null if no result + * @throws JShellException if a user exception if thrown, + * {@link jdk.jshell.EvalException EvalException} will be thrown; if an + * unresolved reference is encountered, + * {@link jdk.jshell.UnresolvedReferenceException UnresolvedReferenceException} + * will be thrown + */ + String invoke(String classname, String methodname) throws JShellException; + + /** + * Attempts to load new classes. Class bytes are retrieved from + * {@link ExecutionEnv#getClassBytes(java.lang.String) } + * + * @param classes list of class names to load + * @return true if load succeeded + */ + boolean load(Collection classes); + + /** + * Attempts to redefine previously loaded classes. Class bytes are retrieved + * from {@link ExecutionEnv#getClassBytes(java.lang.String) } + * + * @param classes list of class names to redefine + * @return true if redefine succeeded + */ + boolean redefine(Collection classes); + + /** + * Queries if the class is loaded and the class bytes are current. + * + * @param classname name of the wrapper class to query + * @return {@code UNKNOWN} if the class is not loaded; {@code CURRENT} if + * the loaded/redefined bytes are equal to the most recent bytes for this + * wrapper class; otherwise {@code NOT_CURRENT} + */ + ClassStatus getClassStatus(String classname); + + /** + * Interrupt a running invoke. + */ + void stop(); + + /** + * Returns the value of a variable. + * + * @param classname the name of the wrapper class of the variable + * @param varname the name of the variable + * @return the value of the variable + */ + String varValue(String classname, String varname); +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionEnv.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionEnv.java new file mode 100644 index 00000000000..3c07ba09da2 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionEnv.java @@ -0,0 +1,127 @@ +/* + * 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.jshell.spi; + +import java.io.InputStream; +import java.io.PrintStream; +import java.util.List; +import jdk.jshell.EvalException; +import jdk.jshell.JShell; +import jdk.jshell.UnresolvedReferenceException; + +/** + * Functionality made available to a pluggable JShell execution engine. It is + * provided to the execution engine by the core JShell implementation calling + * {@link ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }. + *

    + * This interface is designed to provide the access to core JShell functionality + * needed to implement ExecutionControl. + * + * @see ExecutionControl + */ +public interface ExecutionEnv { + + /** + * Returns the user's input stream. + * + * @return the user's input stream + */ + InputStream userIn(); + + /** + * Returns the user's output stream. + * + * @return the user's output stream + */ + PrintStream userOut(); + + /** + * Returns the user's error stream. + * + * @return the user's error stream + */ + PrintStream userErr(); + + /** + * @return the JShell instance + */ + JShell state(); + + /** + * Returns the additional VM options to be used when launching the remote + * JVM. This is advice to the execution engine. + *

    + * Note: an execution engine need not launch a remote JVM. + * + * @return the additional options with which to launch the remote JVM + */ + List extraRemoteVMOptions(); + + /** + * Retrieves the class file bytes for the specified wrapper class. + * + * @param className the name of the wrapper class + * @return the current class file bytes as a byte array + */ + byte[] getClassBytes(String className); + + /** + * Creates an {@code EvalException} corresponding to a user exception. An + * user exception thrown during + * {@link ExecutionControl#invoke(java.lang.String, java.lang.String) } + * should be converted to an {@code EvalException} using this method. + * + * @param message the exception message to use (from the user exception) + * @param exceptionClass the class name of the user exception + * @param stackElements the stack trace elements to install + * @return a user API EvalException for the user exception + */ + EvalException createEvalException(String message, String exceptionClass, + StackTraceElement[] stackElements); + + /** + * Creates an {@code UnresolvedReferenceException} for the Snippet identifed + * by the specified identifier. An {@link SPIResolutionException} thrown + * during {@link ExecutionControl#invoke(java.lang.String, java.lang.String) } + * should be converted to an {@code UnresolvedReferenceException} using + * this method. + *

    + * The identifier is an internal id, different from the id in the API. This + * internal id is returned by {@link SPIResolutionException#id()}. + * + * @param id the internal integer identifier + * @param stackElements the stack trace elements to install + * @return an {@code UnresolvedReferenceException} for the unresolved + * reference + */ + UnresolvedReferenceException createUnresolvedReferenceException(int id, + StackTraceElement[] stackElements); + + /** + * Reports that the execution engine has shutdown. + */ + void closeDown(); +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteResolutionException.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/SPIResolutionException.java similarity index 56% rename from langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteResolutionException.java rename to langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/SPIResolutionException.java index 8026979f2c3..07f7455d249 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteResolutionException.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/SPIResolutionException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,27 +23,47 @@ * questions. */ -package jdk.internal.jshell.remote; +package jdk.jshell.spi; /** - * The exception thrown on the remote side upon executing a + * The construction and throw of this exception is embedded in code generated by + * the JShell core implementation in such a way that, upon executing a * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED} - * user method. This exception is not seen by the end user nor through the API. - * @author Robert Field + * user method, this exception is thrown. + *

    + * This exception is seen by the execution engine, but not seen by + * the end user nor through the JShell API. + * + * @see ExecutionEnv#createUnresolvedReferenceException(int, + * java.lang.StackTraceElement[]) */ @SuppressWarnings("serial") // serialVersionUID intentionally omitted -public class RemoteResolutionException extends RuntimeException { +public class SPIResolutionException extends RuntimeException { - final int id; + private final int id; /** - * The throw of this exception is generated into the body of a + * Constructs an SPI layer exception indicating that a + * {@code DeclarationSnippet} with unresolved references has been + * encountered. The throw of this exception is generated into the body of a * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED} * method. + * * @param id An internal identifier of the specific method */ - public RemoteResolutionException(int id) { - super("RemoteResolutionException"); + public SPIResolutionException(int id) { + super("resolution exception"); this.id = id; } + + /** + * Retrieves the internal identifer of the unresolved identifer. + * + * @return the internal identifer + * @see ExecutionEnv#createUnresolvedReferenceException(int, + * java.lang.StackTraceElement[]) + */ + public int id() { + return id; + } } diff --git a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/package-info.java similarity index 63% rename from jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java rename to langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/package-info.java index b96e6ae6239..744e13b74e4 100644 --- a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/package-info.java @@ -23,24 +23,17 @@ * questions. */ -package jdk.internal.vm.agent.spi; - -import java.lang.reflect.Layer; -import java.util.HashMap; -import java.util.Map; -import java.util.ServiceLoader; - -public final class ToolProviderFinder { - private static final Map providers = init(); - - public static ToolProvider find(String name) { - return providers.get(name); - } - - private static Map init() { - Map providers = new HashMap<>(); - ServiceLoader.load(Layer.boot(), ToolProvider.class) - .forEach(p -> providers.putIfAbsent(p.getName(), p)); - return providers; - } -} +/** + * Provides support for alternate implementations of the JShell execution + * engine. The JShell core tracks and compiles Snippets then sends them + * (represented in a wrapper class) to the execution engine for loading, + * and in the case of executable Snippets, execution. The JShell + * implementation includes a default execution engine (currently a remote + * process which is JDI controlled). By implementing the + * {@link ExecutionControl} interface and installing it with + * {@link jdk.jshell.JShell.Builder#executionEngine(jdk.jshell.spi.ExecutionControl) } + * other execution engines can be used. + *

    + * This is not a part of the JShell API. + */ +package jdk.jshell.spi; diff --git a/langtools/src/jdk.jshell/share/classes/module-info.java b/langtools/src/jdk.jshell/share/classes/module-info.java index 93b16ba12b9..0959583f16f 100644 --- a/langtools/src/jdk.jshell/share/classes/module-info.java +++ b/langtools/src/jdk.jshell/share/classes/module-info.java @@ -32,4 +32,5 @@ module jdk.jshell { requires jdk.jdi; exports jdk.jshell; + exports jdk.jshell.spi; } diff --git a/langtools/test/ProblemList.txt b/langtools/test/ProblemList.txt index a7000de5e40..0d1f870629b 100644 --- a/langtools/test/ProblemList.txt +++ b/langtools/test/ProblemList.txt @@ -66,7 +66,6 @@ jdk/jshell/ToolBasicTest.java # javac tools/javac/Paths/AbsolutePathTest.java 8055768 generic-all ToolBox does not close opened files -tools/javac/Paths/MineField.sh 8149599 generic-all needs rewrite tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.java 8057679 generic-all clarify error messages trying to annotate scoping tools/javac/annotations/typeAnnotations/failures/CantAnnotateScoping.java 8057679 generic-all clarify error messages trying to annotate scoping tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass2.java 8057679 generic-all clarify error messages trying to annotate scoping @@ -95,6 +94,3 @@ tools/sjavac/IncCompileWithChanges.java # # jdeps -tools/jdeps/modules/GenModuleInfo.java 8152502,8153481 generic-all fails to clean up files, java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode -tools/jdeps/modules/ModuleTest.java 8153481 generic-all java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode - diff --git a/langtools/test/jdk/jshell/CommandCompletionTest.java b/langtools/test/jdk/jshell/CommandCompletionTest.java index 92a08fc5ca7..0a986a621c1 100644 --- a/langtools/test/jdk/jshell/CommandCompletionTest.java +++ b/langtools/test/jdk/jshell/CommandCompletionTest.java @@ -53,18 +53,18 @@ public class CommandCompletionTest extends ReplToolTesting { public void testCommand() { assertCompletion("/deb|", false); - assertCompletion("/c|", false, "/classes ", "/classpath "); + assertCompletion("/re|", false, "/reload ", "/reset ", "/retain "); assertCompletion("/h|", false, "/help ", "/history "); } public void testList() { test(false, new String[] {"-nostartup"}, a -> assertCompletion(a, "/l|", false, "/list "), - a -> assertCompletion(a, "/list |", false, "all ", "history ", "start "), - a -> assertCompletion(a, "/list h|", false, "history "), + a -> assertCompletion(a, "/list |", false, "-all ", "-history ", "-start "), + a -> assertCompletion(a, "/list -h|", false, "-history "), a -> assertCompletion(a, "/list q|", false), a -> assertVariable(a, "int", "xray"), - a -> assertCompletion(a, "/list |", false, "1", "all ", "history ", "start ", "xray"), + a -> assertCompletion(a, "/list |", false, "-all ", "-history ", "-start ", "1", "xray"), a -> assertCompletion(a, "/list x|", false, "xray") ); } @@ -108,7 +108,7 @@ public class CommandCompletionTest extends ReplToolTesting { Compiler compiler = new Compiler(); assertCompletion("/s|", false, "/save ", "/set "); List p1 = listFiles(Paths.get("")); - Collections.addAll(p1, "all ", "history ", "start "); + Collections.addAll(p1, "-all ", "-history ", "-start "); FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString())); Collections.sort(p1); assertCompletion("/save |", false, p1.toArray(new String[p1.size()])); @@ -116,7 +116,7 @@ public class CommandCompletionTest extends ReplToolTesting { List p2 = listFiles(classDir); assertCompletion("/save " + classDir + "/|", false, p2.toArray(new String[p2.size()])); - assertCompletion("/save all " + classDir + "/|", + assertCompletion("/save -all " + classDir + "/|", false, p2.toArray(new String[p2.size()])); } diff --git a/langtools/test/jdk/jshell/EditorPadTest.java b/langtools/test/jdk/jshell/EditorPadTest.java index 30eed668255..e907aa4625c 100644 --- a/langtools/test/jdk/jshell/EditorPadTest.java +++ b/langtools/test/jdk/jshell/EditorPadTest.java @@ -23,9 +23,10 @@ /* * @test + * @bug 8139872 * @summary Testing built-in editor. - * @ignore 8139872 - * @modules jdk.jshell/jdk.internal.jshell.tool + * @modules java.desktop/java.awt + * jdk.jshell/jdk.internal.jshell.tool * @build ReplToolTesting EditorTestBase * @run testng EditorPadTest */ @@ -35,6 +36,7 @@ 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; @@ -67,14 +69,24 @@ public class EditorPadTest extends EditorTestBase { private static JButton accept = null; private static JButton exit = null; + // Do not actually run if we are headless + @Override + public void testEditor(boolean defaultStartup, String[] args, ReplTest... tests) { + if (!GraphicsEnvironment.isHeadless()) { + test(defaultStartup, args, tests); + } + } + @BeforeClass public static void setUpEditorPadTest() { - try { - robot = new Robot(); - robot.setAutoWaitForIdle(true); - robot.setAutoDelay(DELAY); - } catch (AWTException e) { - throw new ExceptionInInitializerError(e); + if (!GraphicsEnvironment.isHeadless()) { + try { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(DELAY); + } catch (AWTException e) { + throw new ExceptionInInitializerError(e); + } } } @@ -123,7 +135,7 @@ public class EditorPadTest extends EditorTestBase { @Test public void testShuttingDown() { testEditor( - (a) -> assertEditOutput(a, "/e", "", this::shutdownEditor) + (a) -> assertEditOutput(a, "/ed", "", this::shutdownEditor) ); } diff --git a/langtools/test/jdk/jshell/EditorTestBase.java b/langtools/test/jdk/jshell/EditorTestBase.java index c2bd55a921c..12ff3c842a5 100644 --- a/langtools/test/jdk/jshell/EditorTestBase.java +++ b/langtools/test/jdk/jshell/EditorTestBase.java @@ -73,11 +73,9 @@ public abstract class EditorTestBase extends ReplToolTesting { for (String edit : new String[] {"/ed", "/edit"}) { test(new String[]{"-nostartup"}, a -> assertCommandOutputStartsWith(a, edit + " 1", - "| No definition or id found named: 1"), - a -> assertCommandOutputStartsWith(a, edit + " -1", - "| No definition or id found named: -1"), + "| No such snippet: 1"), a -> assertCommandOutputStartsWith(a, edit + " unknown", - "| No definition or id found named: unknown") + "| No such snippet: unknown") ); } } @@ -142,7 +140,7 @@ public abstract class EditorTestBase extends ReplToolTesting { exit(); loadClass(true, "enum A {}", "enum", "A"); }), - a -> assertCommandCheckOutput(a, "/classes", assertClasses()) + a -> assertCommandCheckOutput(a, "/types", assertClasses()) ); } @@ -161,7 +159,7 @@ public abstract class EditorTestBase extends ReplToolTesting { exit(); loadClass(true, "enum A {}", "enum", "A"); }), - a -> assertCommandCheckOutput(a, "/classes", assertClasses()) + a -> assertCommandCheckOutput(a, "/types", assertClasses()) ); } diff --git a/langtools/test/jdk/jshell/ExecutionControlTest.java b/langtools/test/jdk/jshell/ExecutionControlTest.java new file mode 100644 index 00000000000..215038478e3 --- /dev/null +++ b/langtools/test/jdk/jshell/ExecutionControlTest.java @@ -0,0 +1,150 @@ +/* + * 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 8156101 + * @summary Tests for ExecutionControl SPI + * @build KullaTesting LocalExecutionControl + * @run testng ExecutionControlTest + */ + + +import javax.tools.Diagnostic; + +import jdk.jshell.VarSnippet; +import org.testng.annotations.Test; + +import static jdk.jshell.Snippet.Status.VALID; +import static jdk.jshell.Snippet.SubKind.*; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.BeforeMethod; + +@Test +public class ExecutionControlTest extends KullaTesting { + + @BeforeMethod + @Override + public void setUp() { + setUp(new LocalExecutionControl()); + } + + public void verifyLocal() throws ClassNotFoundException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { + System.setProperty("LOCAL_CHECK", "TBD"); + assertEquals(System.getProperty("LOCAL_CHECK"), "TBD"); + assertEval("System.setProperty(\"LOCAL_CHECK\", \"local\")"); + assertEquals(System.getProperty("LOCAL_CHECK"), "local"); + } + + public void classesDeclaration() { + assertEval("interface A { }"); + assertEval("class B implements A { }"); + assertEval("interface C extends A { }"); + assertEval("enum D implements C { }"); + assertEval("@interface E { }"); + assertClasses( + clazz(KullaTesting.ClassType.INTERFACE, "A"), + clazz(KullaTesting.ClassType.CLASS, "B"), + clazz(KullaTesting.ClassType.INTERFACE, "C"), + clazz(KullaTesting.ClassType.ENUM, "D"), + clazz(KullaTesting.ClassType.ANNOTATION, "E")); + assertActiveKeys(); + } + + @Test + public void interfaceTest() { + String interfaceSource + = "interface A {\n" + + " default int defaultMethod() { return 1; }\n" + + " static int staticMethod() { return 2; }\n" + + " int method();\n" + + " class Inner1 {}\n" + + " static class Inner2 {}\n" + + "}"; + assertEval(interfaceSource); + assertEval("A.staticMethod();", "2"); + String classSource + = "class B implements A {\n" + + " public int method() { return 3; }\n" + + "}"; + assertEval(classSource); + assertEval("B b = new B();"); + assertEval("b.defaultMethod();", "1"); + assertDeclareFail("B.staticMethod();", + new ExpectedDiagnostic("compiler.err.cant.resolve.location.args", 0, 14, 1, -1, -1, Diagnostic.Kind.ERROR)); + assertEval("b.method();", "3"); + assertEval("new A.Inner1();"); + assertEval("new A.Inner2();"); + assertEval("new B.Inner1();"); + assertEval("new B.Inner2();"); + } + + public void variables() { + VarSnippet snx = varKey(assertEval("int x = 10;")); + VarSnippet sny = varKey(assertEval("String y = \"hi\";")); + VarSnippet snz = varKey(assertEval("long z;")); + assertVariables(variable("int", "x"), variable("String", "y"), variable("long", "z")); + assertVarValue(snx, "10"); + assertVarValue(sny, "\"hi\""); + assertVarValue(snz, "0"); + assertActiveKeys(); + } + + public void methodOverload() { + assertEval("int m() { return 1; }"); + assertEval("int m(int x) { return 2; }"); + assertEval("int m(String s) { return 3; }"); + assertEval("int m(int x, int y) { return 4; }"); + assertEval("int m(int x, String z) { return 5; }"); + assertEval("int m(int x, String z, long g) { return 6; }"); + assertMethods( + method("()int", "m"), + method("(int)int", "m"), + method("(String)int", "m"), + method("(int,int)int", "m"), + method("(int,String)int", "m"), + method("(int,String,long)int", "m") + ); + assertEval("m();", "1"); + assertEval("m(3);", "2"); + assertEval("m(\"hi\");", "3"); + assertEval("m(7, 8);", "4"); + assertEval("m(7, \"eight\");", "5"); + assertEval("m(7, \"eight\", 9L);", "6"); + assertActiveKeys(); + } + + public void testExprSanity() { + assertEval("int x = 3;", "3"); + assertEval("int y = 4;", "4"); + assertEval("x + y;", "7"); + assertActiveKeys(); + } + + public void testImportOnDemand() { + assertImportKeyMatch("import java.util.*;", "java.util.*", TYPE_IMPORT_ON_DEMAND_SUBKIND, added(VALID)); + assertEval("List list = new ArrayList<>();"); + assertEval("list.add(45);"); + assertEval("list.size();", "1"); + } +} diff --git a/langtools/test/jdk/jshell/HistoryTest.java b/langtools/test/jdk/jshell/HistoryTest.java index 0fa42b1f817..3513e778c22 100644 --- a/langtools/test/jdk/jshell/HistoryTest.java +++ b/langtools/test/jdk/jshell/HistoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,152 +24,64 @@ /* * @test * @summary Test Completion - * @modules jdk.jshell/jdk.internal.jshell.tool - * jdk.internal.le/jdk.internal.jline.console.history + * @modules jdk.internal.le/jdk.internal.jline.extra + * jdk.jshell/jdk.internal.jshell.tool * @build HistoryTest * @run testng HistoryTest */ -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.prefs.AbstractPreferences; -import java.util.prefs.BackingStoreException; -import jdk.internal.jline.console.history.MemoryHistory; - -import jdk.jshell.JShell; -import jdk.jshell.SourceCodeAnalysis; -import jdk.jshell.SourceCodeAnalysis.CompletionInfo; +import java.lang.reflect.Field; +import jdk.internal.jline.extra.EditingHistory; import org.testng.annotations.Test; -import jdk.internal.jshell.tool.EditingHistory; - import static org.testng.Assert.*; @Test -public class HistoryTest { +public class HistoryTest extends ReplToolTesting { public void testHistory() { - JShell eval = JShell.builder() - .in(new ByteArrayInputStream(new byte[0])) - .out(new PrintStream(new ByteArrayOutputStream())) - .err(new PrintStream(new ByteArrayOutputStream())) - .build(); - SourceCodeAnalysis analysis = eval.sourceCodeAnalysis(); - MemoryPreferences prefs = new MemoryPreferences(null, ""); - EditingHistory history = new EditingHistory(prefs) { - @Override protected CompletionInfo analyzeCompletion(String input) { - return analysis.analyzeCompletion(input); - } - }; - history.add("void test() {"); - history.add(" System.err.println(1);"); - history.add("}"); - history.add("/exit"); - - previousAndAssert(history, "/exit"); - - history.previous(); history.previous(); history.previous(); - - history.add("void test() { /*changed*/"); - - previousAndAssert(history, "}"); - previousAndAssert(history, " System.err.println(1);"); - previousAndAssert(history, "void test() {"); - - assertFalse(history.previous()); - - nextAndAssert(history, " System.err.println(1);"); - nextAndAssert(history, "}"); - nextAndAssert(history, ""); - - history.add(" System.err.println(2);"); - history.add("} /*changed*/"); - - assertEquals(history.size(), 7); - - history.save(); - - history = new EditingHistory(prefs) { - @Override protected CompletionInfo analyzeCompletion(String input) { - return analysis.analyzeCompletion(input); - } - }; - - previousSnippetAndAssert(history, "void test() { /*changed*/"); - previousSnippetAndAssert(history, "/exit"); - previousSnippetAndAssert(history, "void test() {"); - - assertFalse(history.previousSnippet()); - - nextSnippetAndAssert(history, "/exit"); - nextSnippetAndAssert(history, "void test() { /*changed*/"); - nextSnippetAndAssert(history, ""); - - assertFalse(history.nextSnippet()); - - history.add("{"); - history.add("}"); - - history.save(); - - history = new EditingHistory(prefs) { - @Override protected CompletionInfo analyzeCompletion(String input) { - return analysis.analyzeCompletion(input); - } - }; - - previousSnippetAndAssert(history, "{"); - previousSnippetAndAssert(history, "void test() { /*changed*/"); - previousSnippetAndAssert(history, "/exit"); - previousSnippetAndAssert(history, "void test() {"); - - while (history.next()); - - history.add("/*current1*/"); - history.add("/*current2*/"); - history.add("/*current3*/"); - - assertEquals(history.currentSessionEntries(), Arrays.asList("/*current1*/", "/*current2*/", "/*current3*/")); - - history.remove(0); - - assertEquals(history.currentSessionEntries(), Arrays.asList("/*current1*/", "/*current2*/", "/*current3*/")); - - while (history.size() > 2) - history.remove(0); - - assertEquals(history.currentSessionEntries(), Arrays.asList("/*current2*/", "/*current3*/")); - - for (int i = 0; i < MemoryHistory.DEFAULT_MAX_SIZE * 2; i++) { - history.add("/exit"); - } - - history.add("void test() { /*after full*/"); - history.add(" System.err.println(1);"); - history.add("}"); - - previousSnippetAndAssert(history, "void test() { /*after full*/"); + test( + a -> {if (!a) setCommandInput("void test() {\n");}, + a -> {if (!a) setCommandInput(" System.err.println(1);\n");}, + a -> {if (!a) setCommandInput(" System.err.println(1);\n");}, + a -> {assertCommand(a, "} //test", "| created method test()");}, + a -> { + if (!a) { + try { + previousAndAssert(getHistory(), "} //test"); + previousSnippetAndAssert(getHistory(), "void test() {"); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + assertCommand(a, "int dummy;", "dummy ==> 0"); + }); + test( + a -> {if (!a) setCommandInput("void test2() {\n");}, + a -> {assertCommand(a, "} //test2", "| created method test2()");}, + a -> { + if (!a) { + try { + previousAndAssert(getHistory(), "} //test2"); + previousSnippetAndAssert(getHistory(), "void test2() {"); + previousSnippetAndAssert(getHistory(), "/debug 0"); //added by test framework + previousSnippetAndAssert(getHistory(), "/exit"); + previousSnippetAndAssert(getHistory(), "int dummy;"); + previousSnippetAndAssert(getHistory(), "void test() {"); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + assertCommand(a, "int dummy;", "dummy ==> 0"); + }); } - public void testSaveOneHistory() { - JShell eval = JShell.builder() - .in(new ByteArrayInputStream(new byte[0])) - .out(new PrintStream(new ByteArrayOutputStream())) - .err(new PrintStream(new ByteArrayOutputStream())) - .build(); - SourceCodeAnalysis analysis = eval.sourceCodeAnalysis(); - MemoryPreferences prefs = new MemoryPreferences(null, ""); - EditingHistory history = new EditingHistory(prefs) { - @Override protected CompletionInfo analyzeCompletion(String input) { - return analysis.analyzeCompletion(input); - } - }; - - history.add("first"); - history.save(); + private EditingHistory getHistory() throws Exception { + Field input = repl.getClass().getDeclaredField("input"); + input.setAccessible(true); + Object console = input.get(repl); + Field history = console.getClass().getDeclaredField("history"); + history.setAccessible(true); + return (EditingHistory) history.get(console); } private void previousAndAssert(EditingHistory history, String expected) { @@ -177,71 +89,9 @@ public class HistoryTest { assertEquals(history.current().toString(), expected); } - private void nextAndAssert(EditingHistory history, String expected) { - assertTrue(history.next()); - assertEquals(history.current().toString(), expected); - } - private void previousSnippetAndAssert(EditingHistory history, String expected) { assertTrue(history.previousSnippet()); assertEquals(history.current().toString(), expected); } - private void nextSnippetAndAssert(EditingHistory history, String expected) { - assertTrue(history.nextSnippet()); - assertEquals(history.current().toString(), expected); - } - - private static final class MemoryPreferences extends AbstractPreferences { - - private final Map key2Value = new HashMap<>(); - private final Map key2SubNode = new HashMap<>(); - - public MemoryPreferences(AbstractPreferences parent, String name) { - super(parent, name); - } - - @Override - protected void putSpi(String key, String value) { - key2Value.put(key, value); - } - - @Override - protected String getSpi(String key) { - return key2Value.get(key); - } - - @Override - protected void removeSpi(String key) { - key2Value.remove(key); - } - - @Override - protected void removeNodeSpi() throws BackingStoreException { - ((MemoryPreferences) parent()).key2SubNode.remove(name()); - } - - @Override - protected String[] keysSpi() throws BackingStoreException { - return key2Value.keySet().toArray(new String[key2Value.size()]); - } - - @Override - protected String[] childrenNamesSpi() throws BackingStoreException { - return key2SubNode.keySet().toArray(new String[key2SubNode.size()]); - } - - @Override - protected AbstractPreferences childSpi(String name) { - return key2SubNode.computeIfAbsent(name, n -> new MemoryPreferences(this, n)); - } - - @Override - protected void syncSpi() throws BackingStoreException {} - - @Override - protected void flushSpi() throws BackingStoreException {} - - } - } diff --git a/langtools/test/jdk/jshell/ImportTest.java b/langtools/test/jdk/jshell/ImportTest.java index 66e1a5f44ea..d5b03c47f41 100644 --- a/langtools/test/jdk/jshell/ImportTest.java +++ b/langtools/test/jdk/jshell/ImportTest.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8141415 * @summary Test imports * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -162,4 +163,9 @@ public class ImportTest extends KullaTesting { assertEval("field;", "\"A\""); assertEval("method();", "\"A\""); } + + public void testImportWithComment() { + assertImportKeyMatch("import java.util.List;//comment", "List", SINGLE_TYPE_IMPORT_SUBKIND, added(VALID)); + assertEval("List l = null;"); + } } diff --git a/langtools/test/jdk/jshell/KullaTesting.java b/langtools/test/jdk/jshell/KullaTesting.java index 7c4224a27db..76f4892ad52 100644 --- a/langtools/test/jdk/jshell/KullaTesting.java +++ b/langtools/test/jdk/jshell/KullaTesting.java @@ -72,6 +72,7 @@ import jdk.jshell.Diag; import static jdk.jshell.Snippet.Status.*; import static org.testng.Assert.*; import static jdk.jshell.Snippet.SubKind.METHOD_SUBKIND; +import jdk.jshell.spi.ExecutionControl; public class KullaTesting { @@ -166,6 +167,21 @@ public class KullaTesting { classpath = new ArrayList<>(); } + public void setUp(ExecutionControl ec) { + inStream = new TestingInputStream(); + outStream = new ByteArrayOutputStream(); + errStream = new ByteArrayOutputStream(); + state = JShell.builder() + .executionEngine(ec) + .in(inStream) + .out(new PrintStream(outStream)) + .err(new PrintStream(errStream)) + .build(); + allSnippets = new LinkedHashSet<>(); + idToSnippet = new LinkedHashMap<>(); + classpath = new ArrayList<>(); + } + @AfterMethod public void tearDown() { if (state != null) state.close(); diff --git a/langtools/test/jdk/jshell/LocalExecutionControl.java b/langtools/test/jdk/jshell/LocalExecutionControl.java new file mode 100644 index 00000000000..e68d039fba3 --- /dev/null +++ b/langtools/test/jdk/jshell/LocalExecutionControl.java @@ -0,0 +1,313 @@ +/* + * 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. + */ + +import jdk.jshell.spi.ExecutionControl; +import jdk.jshell.spi.ExecutionEnv; +import jdk.jshell.spi.SPIResolutionException; +import jdk.jshell.EvalException; +import jdk.jshell.UnresolvedReferenceException; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.CodeSource; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicReference; + +/** + * An implementation of ExecutionControl which executes in the same JVM as the + * JShell core. + * + * @author Grigory Ptashko + */ +class LocalExecutionControl implements ExecutionControl { + private class REPLClassLoader extends URLClassLoader { + REPLClassLoader() { + super(new URL[0]); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + debug("findClass %s\n", name); + byte[] b = execEnv.getClassBytes(name); + if (b == null) { + return super.findClass(name); + } + return super.defineClass(name, b, 0, b.length, (CodeSource)null); + } + + @Override + public void addURL(URL url) { + super.addURL(url); + } + } + + private ExecutionEnv execEnv; + private final Object STOP_LOCK = new Object(); + private boolean userCodeRunning = false; + private REPLClassLoader loader = new REPLClassLoader(); + private final Map> klasses = new TreeMap<>(); + private final Map classBytes = new HashMap<>(); + private ThreadGroup execThreadGroup; + + @Override + public void start(ExecutionEnv execEnv) throws Exception { + this.execEnv = execEnv; + + debug("Process-local code snippets execution control started"); + } + + @Override + public void close() { + } + + @Override + public boolean load(Collection classes) { + try { + loadLocal(classes); + + return true; + } catch (ClassNotFoundException | ClassCastException ex) { + debug(ex, "Exception on load operation"); + } + + return false; + } + + @Override + public String invoke(String classname, String methodname) throws EvalException, UnresolvedReferenceException { + try { + synchronized (STOP_LOCK) { + userCodeRunning = true; + } + + // Invoke executable entry point in loaded code + Class klass = klasses.get(classname); + if (klass == null) { + debug("Invoke failure: no such class loaded %s\n", classname); + + return ""; + } + + Method doitMethod; + try { + this.getClass().getModule().addReads(klass.getModule()); + this.getClass().getModule().addExports(SPIResolutionException.class.getPackage() + .getName(), klass.getModule()); + doitMethod = klass.getDeclaredMethod(methodname, new Class[0]); + doitMethod.setAccessible(true); + + execThreadGroup = new ThreadGroup("JShell process local execution"); + + AtomicReference iteEx = new AtomicReference<>(); + AtomicReference iaeEx = new AtomicReference<>(); + AtomicReference nmeEx = new AtomicReference<>(); + AtomicReference stopped = new AtomicReference<>(false); + + Thread.setDefaultUncaughtExceptionHandler((t, e) -> { + if (e instanceof InvocationTargetException) { + if (e.getCause() instanceof ThreadDeath) { + stopped.set(true); + } else { + iteEx.set((InvocationTargetException)e); + } + } else if (e instanceof IllegalAccessException) { + iaeEx.set((IllegalAccessException)e); + } else if (e instanceof NoSuchMethodException) { + nmeEx.set((NoSuchMethodException)e); + } else if (e instanceof ThreadDeath) { + stopped.set(true); + } + }); + + final Object[] res = new Object[1]; + Thread snippetThread = new Thread(execThreadGroup, () -> { + try { + res[0] = doitMethod.invoke(null, new Object[0]); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof ThreadDeath) { + stopped.set(true); + } else { + iteEx.set(e); + } + } catch (IllegalAccessException e) { + iaeEx.set(e); + } catch (ThreadDeath e) { + stopped.set(true); + } + }); + + snippetThread.start(); + Thread[] threadList = new Thread[execThreadGroup.activeCount()]; + execThreadGroup.enumerate(threadList); + for (Thread thread : threadList) { + if (thread != null) + thread.join(); + } + + if (stopped.get()) { + debug("Killed."); + + return ""; + } + + if (iteEx.get() != null) { + throw iteEx.get(); + } else if (nmeEx.get() != null) { + throw nmeEx.get(); + } else if (iaeEx.get() != null) { + throw iaeEx.get(); + } + + return valueString(res[0]); + } catch (InvocationTargetException ex) { + Throwable cause = ex.getCause(); + StackTraceElement[] elems = cause.getStackTrace(); + if (cause instanceof SPIResolutionException) { + int id = ((SPIResolutionException)cause).id(); + + throw execEnv.createUnresolvedReferenceException(id, elems); + } else { + throw execEnv.createEvalException(cause.getMessage() == null ? + "" : cause.getMessage(), cause.getClass().getName(), elems); + } + } catch (NoSuchMethodException | IllegalAccessException | InterruptedException ex) { + debug(ex, "Invoke failure"); + } + } finally { + synchronized (STOP_LOCK) { + userCodeRunning = false; + } + } + + return ""; + } + + @Override + @SuppressWarnings("deprecation") + public void stop() { + synchronized (STOP_LOCK) { + if (!userCodeRunning) + return; + + if (execThreadGroup == null) { + debug("Process-local code snippets thread group is null. Aborting stop."); + + return; + } + + execThreadGroup.stop(); + } + } + + @Override + public String varValue(String classname, String varname) { + Class klass = klasses.get(classname); + if (klass == null) { + debug("Var value failure: no such class loaded %s\n", classname); + + return ""; + } + try { + this.getClass().getModule().addReads(klass.getModule()); + Field var = klass.getDeclaredField(varname); + var.setAccessible(true); + Object res = var.get(null); + + return valueString(res); + } catch (Exception ex) { + debug("Var value failure: no such field %s.%s\n", classname, varname); + } + + return ""; + } + + @Override + public boolean addToClasspath(String cp) { + // Append to the claspath + for (String path : cp.split(File.pathSeparator)) { + try { + loader.addURL(new File(path).toURI().toURL()); + } catch (MalformedURLException e) { + throw new InternalError("Classpath addition failed: " + cp, e); + } + } + + return true; + } + + @Override + public boolean redefine(Collection classes) { + return false; + } + + @Override + public ClassStatus getClassStatus(String classname) { + if (!classBytes.containsKey(classname)) { + return ClassStatus.UNKNOWN; + } else if (!Arrays.equals(classBytes.get(classname), execEnv.getClassBytes(classname))) { + return ClassStatus.NOT_CURRENT; + } else { + return ClassStatus.CURRENT; + } + } + + private void loadLocal(Collection classes) throws ClassNotFoundException { + for (String className : classes) { + Class klass = loader.loadClass(className); + klasses.put(className, klass); + classBytes.put(className, execEnv.getClassBytes(className)); + klass.getDeclaredMethods(); + } + } + + private void debug(String format, Object... args) { + //debug(execEnv.state(), execEnv.userErr(), flags, format, args); + } + + private void debug(Exception ex, String where) { + //debug(execEnv.state(), execEnv.userErr(), ex, where); + } + + private static String valueString(Object value) { + if (value == null) { + return "null"; + } else if (value instanceof String) { + return "\"" + (String)value + "\""; + } else if (value instanceof Character) { + return "'" + value + "'"; + } else { + return value.toString(); + } + } +} diff --git a/langtools/test/jdk/jshell/ReplToolTesting.java b/langtools/test/jdk/jshell/ReplToolTesting.java index a2be490511c..503bfc82e4c 100644 --- a/langtools/test/jdk/jshell/ReplToolTesting.java +++ b/langtools/test/jdk/jshell/ReplToolTesting.java @@ -70,6 +70,9 @@ public class ReplToolTesting { new MethodInfo("void printf(String format, Object... args) { System.out.printf(format, args); }", "(String,Object...)void", "printf")) .collect(toList()); + final static List START_UP_CMD_METHOD = Stream.of( + "| printf (String,Object...)void") + .collect(toList()); final static List START_UP = Collections.unmodifiableList( Stream.concat(START_UP_IMPORTS.stream(), START_UP_METHODS.stream()) .map(s -> s.getSource()) diff --git a/langtools/test/jdk/jshell/StartOptionTest.java b/langtools/test/jdk/jshell/StartOptionTest.java index 071b1523b9d..e3326597934 100644 --- a/langtools/test/jdk/jshell/StartOptionTest.java +++ b/langtools/test/jdk/jshell/StartOptionTest.java @@ -22,7 +22,7 @@ */ /* - * @test 8151754 + * @test 8151754 8080883 * @summary Testing start-up options. * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -34,7 +34,6 @@ */ import java.io.ByteArrayOutputStream; -import java.io.OutputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.nio.file.Path; @@ -48,97 +47,93 @@ import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; @Test public class StartOptionTest { - private ByteArrayOutputStream out; - private ByteArrayOutputStream err; + private ByteArrayOutputStream cmdout; + private ByteArrayOutputStream cmderr; + private ByteArrayOutputStream console; + private ByteArrayOutputStream userout; + private ByteArrayOutputStream usererr; private JShellTool getShellTool() { - class NoOutputAllowedStream extends OutputStream { - private final String label; - NoOutputAllowedStream(String label) { - this.label = label; - } - @Override - public void write(int b) { fail("Unexpected output to: " + label); } - } return new JShellTool( new TestingInputStream(), - new PrintStream(out), - new PrintStream(err), - new PrintStream(new NoOutputAllowedStream("console")), + new PrintStream(cmdout), + new PrintStream(cmderr), + new PrintStream(console), new TestingInputStream(), - new PrintStream(new NoOutputAllowedStream("userout")), - new PrintStream(new NoOutputAllowedStream("usererr")), + new PrintStream(userout), + new PrintStream(usererr), new ReplToolTesting.MemoryPreferences(), Locale.ROOT); } - private String getOutput() { - byte[] bytes = out.toByteArray(); - out.reset(); - return new String(bytes, StandardCharsets.UTF_8); - } - - private String getError() { - byte[] bytes = err.toByteArray(); - err.reset(); - return new String(bytes, StandardCharsets.UTF_8); + private void check(ByteArrayOutputStream str, Consumer checkOut, String label) { + byte[] bytes = str.toByteArray(); + str.reset(); + String out = new String(bytes, StandardCharsets.UTF_8); + if (checkOut != null) { + checkOut.accept(out); + } else { + assertEquals("", out, label + ": Expected empty -- "); + } } private void start(Consumer checkOutput, Consumer checkError, String... args) throws Exception { JShellTool tool = getShellTool(); tool.start(args); - if (checkOutput != null) { - checkOutput.accept(getOutput()); - } else { - assertEquals("", getOutput(), "Output: "); - } - if (checkError != null) { - checkError.accept(getError()); - } else { - assertEquals("", getError(), "Error: "); - } + check(cmdout, checkOutput, "cmdout"); + check(cmderr, checkError, "cmderr"); + check(console, null, "console"); + check(userout, null, "userout"); + check(usererr, null, "usererr"); } private void start(String expectedOutput, String expectedError, String... args) throws Exception { - start(s -> assertEquals(s.trim(), expectedOutput, "Output: "), s -> assertEquals(s.trim(), expectedError, "Error: "), args); + start(s -> assertEquals(s.trim(), expectedOutput, "cmdout: "), s -> assertEquals(s.trim(), expectedError, "cmderr: "), args); } @BeforeMethod public void setUp() { - out = new ByteArrayOutputStream(); - err = new ByteArrayOutputStream(); + cmdout = new ByteArrayOutputStream(); + cmderr = new ByteArrayOutputStream(); + console = new ByteArrayOutputStream(); + userout = new ByteArrayOutputStream(); + usererr = new ByteArrayOutputStream(); } @Test public void testUsage() throws Exception { start(s -> { - assertTrue(s.split("\n").length >= 7, s); - assertTrue(s.startsWith("Usage: jshell "), s); + assertTrue(s.split("\n").length >= 7, "Not enough usage lines: " + s); + assertTrue(s.startsWith("Usage: jshell "), "Unexpect usage start: " + s); }, null, "-help"); } @Test public void testUnknown() throws Exception { start(s -> { - assertTrue(s.split("\n").length >= 7, s); - assertTrue(s.startsWith("Usage: jshell "), s); + assertTrue(s.split("\n").length >= 7, "Not enough usage lines (unknown): " + s); + assertTrue(s.startsWith("Usage: jshell "), "Unexpect usage start (unknown): " + s); }, s -> assertEquals(s.trim(), "Unknown option: -unknown"), "-unknown"); } - @Test(enabled = false) // TODO 8080883 public void testStartup() throws Exception { Compiler compiler = new Compiler(); Path p = compiler.getPath("file.txt"); compiler.writeToFile(p); start("", "'-startup' requires a filename argument.", "-startup"); - start("", "Conflicting -startup or -nostartup option.", "-startup", p.toString(), "-startup", p.toString()); - start("", "Conflicting -startup or -nostartup option.", "-nostartup", "-startup", p.toString()); - start("", "Conflicting -startup or -nostartup option.", "-startup", p.toString(), "-nostartup"); + start("", "Only one -startup or -nostartup option may be used.", "-startup", p.toString(), "-startup", p.toString()); + start("", "Only one -startup or -nostartup option may be used.", "-nostartup", "-startup", p.toString()); + start("", "Only one -startup or -nostartup option may be used.", "-startup", p.toString(), "-nostartup"); + start("", "Only one -startup or -nostartup option may be used.", "-nostartup", "-nostartup"); + start("", "Only one -startup or -nostartup option may be used.", "-nostartup", "-startup"); + } + + public void testStartupUnknown() throws Exception { + start("", "File 'UNKNOWN' for '-startup' is not found.", "-startup", "UNKNOWN"); } @Test @@ -157,12 +152,15 @@ public class StartOptionTest { @Test public void testVersion() throws Exception { - start(s -> assertTrue(s.startsWith("jshell")), null, "-version"); + start(s -> assertTrue(s.startsWith("jshell"), "unexpected version: " + s), null, "-version"); } @AfterMethod public void tearDown() { - out = null; - err = null; + cmdout = null; + cmderr = null; + console = null; + userout = null; + usererr = null; } } diff --git a/langtools/test/jdk/jshell/ToolBasicTest.java b/langtools/test/jdk/jshell/ToolBasicTest.java index 9d162d39c31..5789a575207 100644 --- a/langtools/test/jdk/jshell/ToolBasicTest.java +++ b/langtools/test/jdk/jshell/ToolBasicTest.java @@ -23,21 +23,18 @@ /* * @test - * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 + * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 * @summary Tests for Basic tests for REPL tool - * @requires os.family != "solaris" * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.jdeps/com.sun.tools.javap * jdk.jshell/jdk.internal.jshell.tool * @library /tools/lib - * @ignore 8139873 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask * @build KullaTesting TestingInputStream Compiler * @run testng/timeout=600 ToolBasicTest */ -import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -68,7 +65,7 @@ public class ToolBasicTest extends ReplToolTesting { public void elideStartUpFromList() { test( - (a) -> assertCommandOutputContains(a, "123", "type int"), + (a) -> assertCommandOutputContains(a, "123", "==> 123"), (a) -> assertCommandCheckOutput(a, "/list", (s) -> { int cnt; try (Scanner scanner = new Scanner(s)) { @@ -89,7 +86,7 @@ public class ToolBasicTest extends ReplToolTesting { Compiler compiler = new Compiler(); Path path = compiler.getPath("myfile"); test( - (a) -> assertCommandOutputContains(a, "123", "type int"), + (a) -> assertCommandOutputContains(a, "123", "==> 123"), (a) -> assertCommand(a, "/save " + path.toString(), "") ); try (Stream lines = Files.lines(path)) { @@ -118,9 +115,9 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertCommand(a, "class A {" + s, ""), interrupt, (a) -> assertCommand(a, "class A {}\u0003", ""), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertClass(a, "interface A {}", "interface", "A"), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertCommand(a, "import java.util.stream." + s, ""), interrupt, (a) -> assertCommand(a, "import java.util.stream.\u0003", ""), @@ -187,12 +184,11 @@ public class ToolBasicTest extends ReplToolTesting { public void testStop() { test( - (a) -> assertStop(a, "while (true) {}", "Killed."), - (a) -> assertStop(a, "while (true) { try { Thread.sleep(100); } catch (InterruptedException ex) { } }", "Killed.") + (a) -> assertStop(a, "while (true) {}", ""), + (a) -> assertStop(a, "while (true) { try { Thread.sleep(100); } catch (InterruptedException ex) { } }", "") ); } - @Test(enabled = false) // TODO 8130450 public void testRerun() { test(false, new String[] {"-nostartup"}, (a) -> assertCommand(a, "/0", "| No such command or snippet id: /0\n| Type /help for help."), @@ -209,6 +205,7 @@ public class ToolBasicTest extends ReplToolTesting { for (String s : codes) { tests.add((a) -> assertCommand(a, s, null)); } + // Test /1 through /5 -- assure references are correct for (int i = 0; i < codes.length; ++i) { final int finalI = i; Consumer check = (s) -> { @@ -218,6 +215,7 @@ public class ToolBasicTest extends ReplToolTesting { }; tests.add((a) -> assertCommandCheckOutput(a, "/" + (finalI + 1), check)); } + // Test /-1 ... note that the snippets added by history must be stepped over for (int i = 0; i < codes.length; ++i) { final int finalI = i; Consumer check = (s) -> { @@ -225,9 +223,9 @@ public class ToolBasicTest extends ReplToolTesting { assertEquals(ss[0], codes[codes.length - finalI - 1]); assertTrue(ss.length > 1, s); }; - tests.add((a) -> assertCommandCheckOutput(a, "/-" + (finalI + 1), check)); + tests.add((a) -> assertCommandCheckOutput(a, "/-" + (2 * finalI + 1), check)); } - tests.add((a) -> assertCommandCheckOutput(a, "/!", assertStartsWith("void g() { h(); }"))); + tests.add((a) -> assertCommandCheckOutput(a, "/!", assertStartsWith("int a = 0;"))); test(false, new String[]{"-nostartup"}, tests.toArray(new ReplTest[tests.size()])); } @@ -308,8 +306,9 @@ public class ToolBasicTest extends ReplToolTesting { test(new String[]{"-nostartup"}, (a) -> assertCommandCheckOutput(a, "printf(\"\")", assertStartsWith("| Error:\n| cannot find symbol")) ); - test((a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", "")); - test(Locale.ROOT, false, new String[]{"-startup", "UNKNOWN"}, "| File 'UNKNOWN' for start-up is not found."); + test( + (a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", "") + ); } finally { removeStartup(); } @@ -325,8 +324,8 @@ public class ToolBasicTest extends ReplToolTesting { ); Path unknown = compiler.getPath("UNKNOWN.jar"); test(Locale.ROOT, true, new String[]{unknown.toString()}, - "| File " + unknown - + " is not found: " + unresolvableMessage(unknown)); + "| File '" + unknown + + "' for 'jshell' is not found."); } public void testReset() { @@ -338,13 +337,13 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertMethod(a, "void f() { }", "()void", "f"), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertClass(a, "class A { }", "class", "A"), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()), (a) -> assertReset(a, "/reset"), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()) ); } @@ -369,7 +368,7 @@ public class ToolBasicTest extends ReplToolTesting { loadClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"); loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*"); - assertCommandCheckOutput(a, "/classes", assertClasses()); + assertCommandCheckOutput(a, "/types", assertClasses()); }, (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), @@ -403,13 +402,13 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertCommand(a, "int a;", null), (a) -> assertCommand(a, "()", null, null, null, "", ""), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), - (a) -> assertCommandCheckOutput(a, "/list all", (out) -> + (a) -> assertCommandCheckOutput(a, "/list -all", (out) -> output.addAll(Stream.of(out.split("\n")) .filter(str -> !str.isEmpty()) .map(str -> str.substring(str.indexOf(':') + 2)) .filter(str -> !str.startsWith("/")) .collect(Collectors.toList()))), - (a) -> assertCommand(a, "/save all " + path.toString(), "") + (a) -> assertCommand(a, "/save -all " + path.toString(), "") ); assertEquals(Files.readAllLines(path), output); } @@ -422,13 +421,13 @@ public class ToolBasicTest extends ReplToolTesting { output.addAll(Stream.of(out.split("\n")) .filter(str -> !str.isEmpty()) .collect(Collectors.toList()))), - (a) -> assertCommand(a, "/save history " + path.toString(), "") + (a) -> assertCommand(a, "/save -history " + path.toString(), "") ); - output.add("/save history " + path.toString()); + output.add("/save -history " + path.toString()); assertEquals(Files.readAllLines(path), output); } - public void testStartSet() throws BackingStoreException { + public void testStartRetain() throws BackingStoreException { try { Compiler compiler = new Compiler(); Path startUpFile = compiler.getPath("startUp.txt"); @@ -438,12 +437,12 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertMethod(a, "void f() {}", "()V", "f"), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertCommand(a, "/save " + startUpFile.toString(), null), - (a) -> assertCommand(a, "/set start " + startUpFile.toString(), null) + (a) -> assertCommand(a, "/retain start " + startUpFile.toString(), null) ); Path unknown = compiler.getPath("UNKNOWN"); test( - (a) -> assertCommandOutputStartsWith(a, "/set start " + unknown.toString(), - "| File '" + unknown + "' for '/set start' is not found.") + (a) -> assertCommandOutputStartsWith(a, "/retain start " + unknown.toString(), + "| File '" + unknown + "' for '/retain start' is not found.") ); test(false, new String[0], (a) -> { @@ -451,7 +450,7 @@ public class ToolBasicTest extends ReplToolTesting { loadVariable(a, "double", "b", "10.0", "10.0"); loadMethod(a, "void f() {}", "()void", "f"); loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*"); - assertCommandCheckOutput(a, "/classes", assertClasses()); + assertCommandCheckOutput(a, "/types", assertClasses()); }, (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), @@ -472,7 +471,7 @@ public class ToolBasicTest extends ReplToolTesting { public void testStartSave() throws IOException { Compiler compiler = new Compiler(); Path startSave = compiler.getPath("startSave.txt"); - test(a -> assertCommand(a, "/save start " + startSave.toString(), null)); + test(a -> assertCommand(a, "/save -start " + startSave.toString(), null)); List lines = Files.lines(startSave) .filter(s -> !s.isEmpty()) .collect(Collectors.toList()); @@ -561,12 +560,16 @@ public class ToolBasicTest extends ReplToolTesting { ); } - private String unresolvableMessage(Path p) { + public void testHeadlessEditPad() { + String prevHeadless = System.getProperty("java.awt.headless"); try { - new FileInputStream(p.toFile()); - throw new AssertionError("Expected exception did not occur."); - } catch (IOException ex) { - return ex.getMessage(); + System.setProperty("java.awt.headless", "true"); + test( + (a) -> assertCommandOutputStartsWith(a, "/edit printf", "| Cannot launch editor -- unexpected exception:") + ); + } finally { + System.setProperty("java.awt.headless", prevHeadless==null? "false" : prevHeadless); } } + } diff --git a/langtools/test/jdk/jshell/ToolCommandOptionTest.java b/langtools/test/jdk/jshell/ToolCommandOptionTest.java new file mode 100644 index 00000000000..030d016a89e --- /dev/null +++ b/langtools/test/jdk/jshell/ToolCommandOptionTest.java @@ -0,0 +1,357 @@ +/* + * 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 8157395 8157393 8157517 + * @summary Tests of jshell comand options, and undoing operations + * @modules jdk.jshell/jdk.internal.jshell.tool + * @build ToolCommandOptionTest ReplToolTesting + * @run testng ToolCommandOptionTest + */ +import org.testng.annotations.Test; +import static org.testng.Assert.assertFalse; + +@Test +public class ToolCommandOptionTest extends ReplToolTesting { + + public void listTest() { + test( + (a) -> assertCommand(a, "int x;", + "x ==> 0"), + (a) -> assertCommand(a, "/li", + "1 : int x;"), + (a) -> assertCommandOutputStartsWith(a, "/lis -st", + "\n s1 : import"), + (a) -> assertCommandOutputStartsWith(a, "/list -all", + "\n s1 : import"), + (a) -> assertCommandOutputContains(a, "/list -all", + "1 : int x;"), + (a) -> assertCommandOutputContains(a, "/list -history", + "int x;"), + (a) -> assertCommandOutputContains(a, "/li -h", + "/lis -st"), + (a) -> assertCommand(a, "/list -furball", + "| Unknown option: -furball -- /list -furball"), + (a) -> assertCommand(a, "/list x", + "1 : int x;"), + (a) -> assertCommand(a, "/li x -start", + "| Options and snippets must not both be used: /list x -start"), + (a) -> assertCommand(a, "/l -st -al", + "| Conflicting options -- /list -st -al") + ); + } + + public void typesTest() { + test( + (a) -> assertCommand(a, "int x", + "x ==> 0"), + (a) -> assertCommand(a, "/types x", + "| This command does not accept the snippet 'x' : int x;"), + (a) -> assertCommand(a, "class C {}", + "| created class C"), + (a) -> assertCommand(a, "/ty", + "| class C"), + (a) -> assertCommand(a, "/ty -st", + ""), + (a) -> assertCommand(a, "/types -all", + "| class C"), + (a) -> assertCommand(a, "/types -furball", + "| Unknown option: -furball -- /types -furball"), + (a) -> assertCommand(a, "/types C", + "| class C"), + (a) -> assertCommand(a, "/types C -start", + "| Options and snippets must not both be used: /types C -start"), + (a) -> assertCommand(a, "/ty -st -al", + "| Conflicting options -- /types -st -al") + ); + } + + public void dropTest() { + test(false, new String[]{"-nostartup"}, + (a) -> assertCommand(a, "int x = 5;", + "x ==> 5"), + (a) -> assertCommand(a, "x", + "x ==> 5"), + (a) -> assertCommand(a, "long y;", + "y ==> 0"), + (a) -> assertCommand(a, "/drop -furball", + "| Unknown option: -furball -- /drop -furball"), + (a) -> assertCommand(a, "/drop -all", + "| Unknown option: -all -- /drop -all"), + (a) -> assertCommandOutputStartsWith(a, "/drop z", + "| No such snippet: z"), + (a) -> assertCommandOutputStartsWith(a, "/drop 2", + "| This command does not accept the snippet '2' : x"), + (a) -> assertCommand(a, "/dr x y", + "| dropped variable x\n" + + "| dropped variable y"), + (a) -> assertCommand(a, "/list", + "2 : x") + ); + } + + public void setEditorTest() { + test( + (a) -> assertCommand(a, "/set editor -furball", + "| Unknown option: -furball -- /set editor -furball"), + (a) -> assertCommand(a, "/set editor -furball prog", + "| Unknown option: -furball -- /set editor -furball prog"), + (a) -> assertCommand(a, "/set editor -furball -mattress", + "| Unknown option: -furball -mattress -- /set editor -furball -mattress"), + (a) -> assertCommand(a, "/set editor -default prog", + "| Specify -default option or program, not both -- /set editor -default prog"), + (a) -> assertCommand(a, "/set editor prog", + "| Editor set to: prog"), + (a) -> assertCommand(a, "/set editor prog -default", + "| Editor set to: prog"), + (a) -> assertCommand(a, "/se ed prog -furball", + "| Editor set to: prog"), + (a) -> assertCommand(a, "/set editor prog arg1 -furball arg3 -default arg4", + "| Editor set to: prog"), + (a) -> assertCommand(a, "/set editor -default", + ""), + (a) -> assertCommand(a, "/se edi -def", + ""), + (a) -> assertCommand(a, "/set editor", + "| The '/set editor' command requires a path argument") + ); + } + + public void retainEditorTest() { + test( + (a) -> assertCommand(a, "/retain editor -furball", + "| Unknown option: -furball -- /retain editor -furball"), + (a) -> assertCommand(a, "/retain editor -furball prog", + "| Unknown option: -furball -- /retain editor -furball prog"), + (a) -> assertCommand(a, "/retain editor -furball -mattress", + "| Unknown option: -furball -mattress -- /retain editor -furball -mattress"), + (a) -> assertCommand(a, "/retain editor -default prog", + "| Specify -default option or program, not both -- /retain editor -default prog"), + (a) -> assertCommand(a, "/retain editor prog", + "| Editor set to: prog"), + (a) -> assertCommand(a, "/retain editor prog -default", + "| Editor set to: prog"), + (a) -> assertCommand(a, "/ret ed prog -furball", + "| Editor set to: prog"), + (a) -> assertCommand(a, "/retain editor prog arg1 -furball arg3 -default arg4", + "| Editor set to: prog"), + (a) -> assertCommand(a, "/retain editor -default", + ""), + (a) -> assertCommand(a, "/reta edi -def", + ""), + (a) -> assertCommand(a, "/retain editor", + "") + ); + } + + public void setStartTest() { + test( + (a) -> assertCommand(a, "/set start -furball", + "| Unknown option: -furball -- /set start -furball"), + (a) -> assertCommand(a, "/set start -furball pyle", + "| Unknown option: -furball -- /set start -furball pyle"), + (a) -> assertCommand(a, "/se st pyle -furball", + "| Unknown option: -furball -- /set st pyle -furball"), + (a) -> assertCommand(a, "/set start -furball -mattress", + "| Unknown option: -furball -mattress -- /set start -furball -mattress"), + (a) -> assertCommand(a, "/set start foo -default", + "| Specify either one option or a startup file name -- /set start foo -default"), + (a) -> assertCommand(a, "/set start frfg", + "| File 'frfg' for '/set start' is not found."), + (a) -> assertCommand(a, "/set start -default", + ""), + (a) -> assertCommand(a, "/se sta -no", + ""), + (a) -> assertCommand(a, "/set start", + "| Specify either one option or a startup file name -- /set start") + ); + } + + public void retainStartTest() { + test( + (a) -> assertCommand(a, "/retain start -furball", + "| Unknown option: -furball -- /retain start -furball"), + (a) -> assertCommand(a, "/retain start -furball pyle", + "| Unknown option: -furball -- /retain start -furball pyle"), + (a) -> assertCommand(a, "/ret st pyle -furball", + "| Unknown option: -furball -- /retain st pyle -furball"), + (a) -> assertCommand(a, "/retain start -furball -mattress", + "| Unknown option: -furball -mattress -- /retain start -furball -mattress"), + (a) -> assertCommand(a, "/retain start foo -default", + "| Specify either one option or a startup file name -- /retain start foo -default"), + (a) -> assertCommand(a, "/retain start frfg", + "| File 'frfg' for '/retain start' is not found."), + (a) -> assertCommand(a, "/retain start -default", + ""), + (a) -> assertCommand(a, "/ret sta -no", + ""), + (a) -> assertCommand(a, "/retain start", + "") + ); + } + + public void setModeTest() { + test( + (a) -> assertCommandOutputStartsWith(a, "/set mode", + "| Missing the feedback mode"), + (a) -> assertCommandOutputStartsWith(a, "/set mode *", + "| Expected a feedback mode name: *"), + (a) -> assertCommandOutputStartsWith(a, "/set mode -quiet", + "| Missing the feedback mode"), + (a) -> assertCommandOutputStartsWith(a, "/set mode -quiet *", + "| Expected a feedback mode name: *"), + (a) -> assertCommandOutputStartsWith(a, "/set mode amode normal thing", + "| Unexpected arguments at end of command: thing"), + (a) -> assertCommand(a, "/set mode mymode", + "| Created new feedback mode: mymode"), + (a) -> assertCommand(a, "/set mode mymode -delete", + ""), + (a) -> assertCommand(a, "/set mode mymode normal", + "| Created new feedback mode: mymode"), + (a) -> assertCommand(a, "/set mode -del mymode", + ""), + (a) -> assertCommandOutputStartsWith(a, "/set mode mymode -command -quiet", + "| Conflicting options"), + (a) -> assertCommandOutputStartsWith(a, "/set mode mymode -delete -quiet", + "| Conflicting options"), + (a) -> assertCommandOutputStartsWith(a, "/set mode mymode -command -delete", + "| Conflicting options"), + (a) -> assertCommandOutputStartsWith(a, "/set mode mymode -d", + "| No feedback mode named: mymode"), + (a) -> assertCommandOutputStartsWith(a, "/set mode normal", + "| Not valid with a predefined mode: normal"), + (a) -> assertCommand(a, "/se mo -c mymode", + "| Created new feedback mode: mymode"), + (a) -> assertCommand(a, "/set feedback mymode", + "| Feedback mode: mymode"), + (a) -> assertCommandOutputStartsWith(a, "/set mode mymode -delete", + "| The current feedback mode 'mymode' cannot be deleted"), + (a) -> assertCommand(a, "/set feedback no", + "| Feedback mode: normal"), + (a) -> assertCommandOutputStartsWith(a, "/set mode mymode -delete", + ""), + (a) -> assertCommandCheckOutput(a, "/set feedback", + (s) -> assertFalse(s.contains("mymode"), "Didn't delete: " + s)) + ); + } + + public void setModeSmashTest() { + test( + (a) -> assertCommand(a, "/set mode mymode -command", + "| Created new feedback mode: mymode"), + (a) -> assertCommand(a, "/set feedback mymode", + "| Feedback mode: mymode"), + (a) -> assertCommand(a, "/set format mymode display 'blurb'", + ""), + (a) -> assertCommand(a, "45", + "blurb"), + (a) -> assertCommand(a, "/set mode mymode normal", + "| Created new feedback mode: mymode"), + (a) -> assertCommandOutputContains(a, "45", + " ==> 45") + ); + } + + public void retainModeTest() { + test( + (a) -> assertCommandOutputStartsWith(a, "/retain mode", + "| Missing the feedback mode"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode *", + "| Expected a feedback mode name: *"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode amode normal", + "| Unexpected arguments at end of command: normal"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode mymode", + "| Does not match any current feedback mode: mymode"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode mymode -delete", + "| No feedback mode named: mymode"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode -d mymode", + "| No feedback mode named: mymode"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode normal", + "| Not valid with a predefined mode: normal"), + (a) -> assertCommand(a, "/set mode mymode verbose", + "| Created new feedback mode: mymode"), + (a) -> assertCommand(a, "/retain mode mymode", + ""), + (a) -> assertCommand(a, "/set mode mymode -delete", + ""), + (a) -> assertCommand(a, "/retain mode mymode -delete", + ""), + (a) -> assertCommand(a, "/set mode kmode normal", + "| Created new feedback mode: kmode"), + (a) -> assertCommand(a, "/retain mode kmode", + ""), + (a) -> assertCommand(a, "/set mode kmode -delete", + ""), + (a) -> assertCommand(a, "/set mode tmode normal", + "| Created new feedback mode: tmode"), + (a) -> assertCommandOutputStartsWith(a, "/retain feedback tmode", + "| '/retain feedback ' requires that is predefined or has been retained with '/retain mode'"), + (a) -> assertCommand(a, "/set format tmode display 'YES'", + ""), + (a) -> assertCommand(a, "/set feedback tmode", + "| Feedback mode: tmode"), + (a) -> assertCommand(a, "45", + "YES"), + (a) -> assertCommand(a, "/retain mode tmode", + ""), + (a) -> assertCommand(a, "/retain feedback tmode", + "| Feedback mode: tmode"), + (a) -> assertCommand(a, "/set format tmode display 'blurb'", + ""), + (a) -> assertCommand(a, "45", + "blurb") + ); + test( + (a) -> assertCommand(a, "45", + "YES"), + (a) -> assertCommand(a, "/set feedback kmode", + "| Feedback mode: kmode"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode kmode -delete", + "| The current feedback mode 'kmode' cannot be deleted"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode tmode -delete", + "| The retained feedback mode 'tmode' cannot be deleted"), + (a) -> assertCommand(a, "/retain feedback normal", + "| Feedback mode: normal"), + (a) -> assertCommand(a, "/retain mode tmode -delete", + ""), + (a) -> assertCommandOutputStartsWith(a, "/retain mode kmode -delete", + "") + ); + test( + (a) -> assertCommandOutputStartsWith(a, "/set feedback tmode", + "| Does not match any current feedback mode: tmode"), + (a) -> assertCommandOutputStartsWith(a, "/set feedback kmode", + "| Does not match any current feedback mode: kmode"), + (a) -> assertCommandOutputStartsWith(a, "/set feedback mymode", + "| Does not match any current feedback mode: mymode"), + (a) -> assertCommandCheckOutput(a, "/set feedback", + (s) -> assertFalse(s.contains("mymode"), "Didn't delete mymode: " + s)), + (a) -> assertCommandCheckOutput(a, "/set feedback", + (s) -> assertFalse(s.contains("kmode"), "Didn't delete kmode: " + s)), + (a) -> assertCommandCheckOutput(a, "/set feedback", + (s) -> assertFalse(s.contains("tmode"), "Didn't delete tmode: " + s)) + ); + } + +} diff --git a/langtools/test/jdk/jshell/ToolFormatTest.java b/langtools/test/jdk/jshell/ToolFormatTest.java index f4758f8a876..2394c759b0c 100644 --- a/langtools/test/jdk/jshell/ToolFormatTest.java +++ b/langtools/test/jdk/jshell/ToolFormatTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8148316 8148317 8151755 8152246 8153551 + * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261 * @summary Tests for output customization * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.List; import org.testng.annotations.Test; +import static org.testng.Assert.assertTrue; @Test public class ToolFormatTest extends ReplToolTesting { @@ -43,7 +44,7 @@ public class ToolFormatTest extends ReplToolTesting { public void testSetFormat() { try { test( - (a) -> assertCommandOutputStartsWith(a, "/set newmode test command", "| Created new feedback mode: test"), + (a) -> assertCommandOutputStartsWith(a, "/set mode test -command", "| Created new feedback mode: test"), (a) -> assertCommand(a, "/set format test pre '$ '", ""), (a) -> assertCommand(a, "/set format test post ''", ""), (a) -> assertCommand(a, "/set format test act 'ADD' added", ""), @@ -82,7 +83,7 @@ public class ToolFormatTest extends ReplToolTesting { public void testSetFormatSelector() { List tests = new ArrayList<>(); - tests.add((a) -> assertCommandOutputStartsWith(a, "/set newmode ate quiet", + tests.add((a) -> assertCommandOutputStartsWith(a, "/set mode ate -quiet", "| Created new feedback mode: ate")); tests.add((a) -> assertCommand(a, "/set feedback ate", "")); StringBuilder sb = new StringBuilder(); @@ -155,6 +156,51 @@ public class ToolFormatTest extends ReplToolTesting { } } + public void testSetTruncation() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set feedback normal", ""), + (a) -> assertCommand(a, "String s = java.util.stream.IntStream.range(65, 74)"+ + ".mapToObj(i -> \"\"+(char)i).reduce((a,b) -> a + b + a).get()", + "s ==> \"ABACABADABACABAEABACABADABACABAFABACABADABACABAEABACABADABACABAGABACABADABA ..."), + (a) -> assertCommandOutputStartsWith(a, "/set mode test -quiet", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback test", ""), + (a) -> assertCommand(a, "/set format test display '{type}:{value}' primary", ""), + (a) -> assertCommand(a, "/set truncation test 20", ""), + (a) -> assertCommand(a, "/set trunc test 10 varvalue", ""), + (a) -> assertCommand(a, "/set trunc test 3 assignment", ""), + (a) -> assertCommand(a, "String r = s", "String:\"ABACABADABACABA ..."), + (a) -> assertCommand(a, "r", "String:\"ABACA ..."), + (a) -> assertCommand(a, "r=s", "String:\"AB") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testDefaultTruncation() { + test( + (a) -> assertCommand(a, "char[] cs = new char[2000];", null), + (a) -> assertCommand(a, "Arrays.fill(cs, 'A');", ""), + (a) -> assertCommandCheckOutput(a, "String s = new String(cs)", + (s) -> { + assertTrue(s.length() < 120, "Result too long (" + s.length() + ") -- " + s); + assertTrue(s.contains("AAAAAAAAAAAAAAAAAA"), "Bad value: " + s); + }), + (a) -> assertCommandCheckOutput(a, "s", + (s) -> { + assertTrue(s.length() > 300, "Result too short (" + s.length() + ") -- " + s); + assertTrue(s.contains("AAAAAAAAAAAAAAAAAA"), "Bad value: " + s); + }), + (a) -> assertCommandCheckOutput(a, "\"X\" + s", + (s) -> { + assertTrue(s.length() > 300, "Result too short (" + s.length() + ") -- " + s); + assertTrue(s.contains("XAAAAAAAAAAAAAAAAAA"), "Bad value: " + s); + }) + ); + } + public void testShowFeedbackModes() { test( (a) -> assertCommandOutputContains(a, "/set feedback", "normal") @@ -164,13 +210,13 @@ public class ToolFormatTest extends ReplToolTesting { public void testSetNewModeQuiet() { try { test( - (a) -> assertCommandOutputStartsWith(a, "/set newmode nmq quiet normal", "| Created new feedback mode: nmq"), + (a) -> assertCommandOutputStartsWith(a, "/set mode nmq -quiet normal", "| Created new feedback mode: nmq"), (a) -> assertCommand(a, "/set feedback nmq", ""), - (a) -> assertCommand(a, "/se ne nmq2 q nor", ""), + (a) -> assertCommand(a, "/se mo nmq2 -q nor", ""), (a) -> assertCommand(a, "/se fee nmq2", ""), - (a) -> assertCommand(a, "/set newmode nmc command normal", ""), + (a) -> assertCommand(a, "/set mode nmc -command normal", ""), (a) -> assertCommandOutputStartsWith(a, "/set feedback nmc", "| Feedback mode: nmc"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode nm", "| Created new feedback mode: nm"), + (a) -> assertCommandOutputStartsWith(a, "/set mode nm", "| Created new feedback mode: nm"), (a) -> assertCommandOutputStartsWith(a, "/set feedback nm", "| Feedback mode: nm"), (a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal") ); @@ -183,37 +229,37 @@ public class ToolFormatTest extends ReplToolTesting { public void testSetError() { try { test( - (a) -> assertCommandOutputStartsWith(a, "/set newmode tee command foo", + (a) -> assertCommandOutputStartsWith(a, "/set mode tee -command foo", "| Does not match any current feedback mode: foo"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode tee flurb", - "| Specify either 'command' or 'quiet'"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode te2", - "| Created new feedback mode: te2"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode te2 command", - "| Expected a new feedback mode name. 'te2' is a known feedback mode"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", + (a) -> assertCommandOutputStartsWith(a, "/set mode tee flurb", + "| Does not match any current feedback mode: flurb"), + (a) -> assertCommandOutputStartsWith(a, "/set mode tee", + "| Created new feedback mode: tee"), + (a) -> assertCommandOutputStartsWith(a, "/set mode verbose", + "| Not valid with a predefined mode: verbose"), + (a) -> assertCommandOutputStartsWith(a, "/set mode te -command normal", "| Created new feedback mode: te"), (a) -> assertCommand(a, "/set format te errorpre 'ERROR: '", ""), (a) -> assertCommandOutputStartsWith(a, "/set feedback te", ""), (a) -> assertCommandOutputStartsWith(a, "/set ", - "ERROR: The '/set' command requires a sub-command and arguments"), + "ERROR: The '/set' command requires a sub-command"), (a) -> assertCommandOutputStartsWith(a, "/set xyz", "ERROR: Invalid '/set' argument: xyz"), (a) -> assertCommandOutputStartsWith(a, "/set f", "ERROR: Ambiguous sub-command argument to '/set': f"), (a) -> assertCommandOutputStartsWith(a, "/set feedback", - "ERROR: Expected a feedback mode"), + "ERROR: Missing the feedback mode"), (a) -> assertCommandOutputStartsWith(a, "/set feedback xyz", "ERROR: Does not match any current feedback mode"), (a) -> assertCommandOutputStartsWith(a, "/set format", - "ERROR: Expected a feedback mode"), + "ERROR: Missing the feedback mode"), (a) -> assertCommandOutputStartsWith(a, "/set format xyz", "ERROR: Does not match any current feedback mode"), (a) -> assertCommandOutputStartsWith(a, "/set format t", "ERROR: Matches more then one current feedback mode: t"), (a) -> assertCommandOutputStartsWith(a, "/set format te", - "ERROR: Expected field name missing"), + "ERROR: Missing the field name"), (a) -> assertCommandOutputStartsWith(a, "/set format te fld", "ERROR: Expected format missing"), (a) -> assertCommandOutputStartsWith(a, "/set format te fld aaa", @@ -226,16 +272,18 @@ public class ToolFormatTest extends ReplToolTesting { "ERROR: Selector kind in multiple sections of"), (a) -> assertCommandOutputStartsWith(a, "/set format te fld 'aaa' import,added", "ERROR: Different selector kinds in same sections of"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode", - "ERROR: Expected new feedback mode"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode te", - "ERROR: Expected a new feedback mode name"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode x xyz", - "ERROR: Specify either 'command' or 'quiet'"), - (a) -> assertCommandOutputStartsWith(a, "/set newmode x quiet y", + (a) -> assertCommandOutputStartsWith(a, "/set trunc te 20x", + "ERROR: Truncation length must be an integer: 20x"), + (a) -> assertCommandOutputStartsWith(a, "/set trunc te", + "ERROR: Expected truncation length"), + (a) -> assertCommandOutputStartsWith(a, "/set truncation te 111 import,added", + "ERROR: Different selector kinds in same sections of"), + (a) -> assertCommandOutputStartsWith(a, "/set mode", + "ERROR: Missing the feedback mode"), + (a) -> assertCommandOutputStartsWith(a, "/set mode x -quiet y", "ERROR: Does not match any current feedback mode"), (a) -> assertCommandOutputStartsWith(a, "/set prompt", - "ERROR: Expected a feedback mode"), + "ERROR: Missing the feedback mode"), (a) -> assertCommandOutputStartsWith(a, "/set prompt te", "ERROR: Expected format missing"), (a) -> assertCommandOutputStartsWith(a, "/set prompt te aaa xyz", @@ -243,7 +291,7 @@ public class ToolFormatTest extends ReplToolTesting { (a) -> assertCommandOutputStartsWith(a, "/set prompt te 'aaa' xyz", "ERROR: Format 'xyz' must be quoted"), (a) -> assertCommandOutputStartsWith(a, "/set prompt", - "ERROR: Expected a feedback mode"), + "ERROR: Missing the feedback mode"), (a) -> assertCommandOutputStartsWith(a, "/set prompt te", "ERROR: Expected format missing"), (a) -> assertCommandOutputStartsWith(a, "/set prompt te aaa", diff --git a/langtools/test/jdk/jshell/ToolLocaleMessageTest.java b/langtools/test/jdk/jshell/ToolLocaleMessageTest.java index 76cc3ed120a..b2125d7c3dc 100644 --- a/langtools/test/jdk/jshell/ToolLocaleMessageTest.java +++ b/langtools/test/jdk/jshell/ToolLocaleMessageTest.java @@ -76,7 +76,7 @@ public class ToolLocaleMessageTest extends ReplToolTesting { public void testSample() { try { testLocale( - (a) -> assertCommandOK(a, "/set newmode test command normal", "test"), + (a) -> assertCommandOK(a, "/set mode test -command normal", "test"), (a) -> assertCommandOK(a, "/set format test errorpre 'ERROR: '"), (a) -> assertCommandOK(a, "/set feedback test", "test"), @@ -101,7 +101,7 @@ public class ToolLocaleMessageTest extends ReplToolTesting { public void testCommand() { try { testLocale( - (a) -> assertCommandOK(a, "/set newmode test command normal", "test"), + (a) -> assertCommandOK(a, "/set mode test -command normal", "test"), (a) -> assertCommandOK(a, "/set format test errorpre 'ERROR: '"), (a) -> assertCommandOK(a, "/set feedback test", "test"), @@ -118,10 +118,10 @@ public class ToolLocaleMessageTest extends ReplToolTesting { (a) -> assertCommandOK(a, "int dup"), (a) -> assertCommandFail(a, "/drop dup"), (a) -> assertCommandFail(a, "/edit zebra", "zebra"), - (a) -> assertCommandFail(a, "/list zebra", "zebra", "/list"), + (a) -> assertCommandFail(a, "/list zebra", "zebra", "No such snippet: zebra"), (a) -> assertCommandFail(a, "/open", "/open"), (a) -> assertCommandFail(a, "/open zebra", "zebra", "/open"), - (a) -> assertCommandFail(a, "/reload zebra", "zebra", "/reload"), + (a) -> assertCommandFail(a, "/reload zebra", "zebra", "Unexpected arguments at end of command"), (a) -> assertCommandFail(a, "/save", "/save"), (a) -> assertCommandFail(a, "/-99"), @@ -134,20 +134,20 @@ public class ToolLocaleMessageTest extends ReplToolTesting { public void testHelp() { testLocale( - (a) -> assertCommandOK(a, "/help", "/list", "/save", "/set", "[restore]"), - (a) -> assertCommandOK(a, "/help /list", "start", "all"), + (a) -> assertCommandOK(a, "/help", "/list", "/save", "/set", "[-restore]"), + (a) -> assertCommandOK(a, "/help /list", "-start", "-all"), (a) -> assertCommandOK(a, "/help /edit", "/set editor"), (a) -> assertCommandOK(a, "/help /drop", "/drop"), - (a) -> assertCommandOK(a, "/help /save", "all", "start"), + (a) -> assertCommandOK(a, "/help /save", "-all", "-start"), (a) -> assertCommandOK(a, "/help /open", "/open"), - (a) -> assertCommandOK(a, "/help /reload", "restore"), + (a) -> assertCommandOK(a, "/help /reload", "-restore"), (a) -> assertCommandOK(a, "/help /help", "intro"), - (a) -> assertCommandOK(a, "/help /set", "newmode"), + (a) -> assertCommandOK(a, "/help /set", "mode"), (a) -> assertCommandOK(a, "/help /?", "intro"), (a) -> assertCommandOK(a, "/help intro", "/help"), (a) -> assertCommandOK(a, "/help /set format", "import", "case", "{value}", "added"), - (a) -> assertCommandOK(a, "/help /set feedback", "newmode"), - (a) -> assertCommandOK(a, "/help /set newmode", "feedback"), + (a) -> assertCommandOK(a, "/help /set feedback", "mode"), + (a) -> assertCommandOK(a, "/help /set mode", "feedback"), (a) -> assertCommandOK(a, "/help /set prompt", "/set prompt"), (a) -> assertCommandOK(a, "/help /set editor", "/edit") ); @@ -156,11 +156,11 @@ public class ToolLocaleMessageTest extends ReplToolTesting { public void testFeedbackError() { try { testLocale( - (a) -> assertCommandOK(a, "/set newmode tee command foo", "foo"), - (a) -> assertCommandOK(a, "/set newmode tee flurb", "command", "quiet"), - (a) -> assertCommandOK(a, "/set newmode te2", "te2"), - (a) -> assertCommandOK(a, "/set newmode te2 command", "te2"), - (a) -> assertCommandOK(a, "/set newmode te command normal", "te"), + (a) -> assertCommandOK(a, "/set mode te2", "te2"), + (a) -> assertCommandOK(a, "/set mode te3 -command", "te3"), + (a) -> assertCommandOK(a, "/set mode te2 -command"), + (a) -> assertCommandOK(a, "/set mode te -command normal", "te"), + (a) -> assertCommandOK(a, "/set mode te"), (a) -> assertCommandOK(a, "/set format te errorpre 'ERROR: '"), (a) -> assertCommandOK(a, "/set feedback te"), @@ -179,16 +179,14 @@ public class ToolLocaleMessageTest extends ReplToolTesting { (a) -> assertCommandFail(a, "/set format te fld 'aaa' import-frog"), (a) -> assertCommandFail(a, "/set format te fld 'aaa' import-import"), (a) -> assertCommandFail(a, "/set format te fld 'aaa' import,added"), - (a) -> assertCommandFail(a, "/set newmode"), - (a) -> assertCommandFail(a, "/set newmode te"), - (a) -> assertCommandFail(a, "/set newmode x xyz"), - (a) -> assertCommandFail(a, "/set newmode x quiet y"), + (a) -> assertCommandFail(a, "/set mode"), + (a) -> assertCommandFail(a, "/set mode x xyz"), + (a) -> assertCommandFail(a, "/set mode x -quiet y"), + (a) -> assertCommandFail(a, "/set mode tee -command foo", "foo"), (a) -> assertCommandFail(a, "/set prompt"), (a) -> assertCommandFail(a, "/set prompt te"), (a) -> assertCommandFail(a, "/set prompt te aaa xyz", "aaa"), (a) -> assertCommandFail(a, "/set prompt te 'aaa' xyz", "xyz"), - (a) -> assertCommandFail(a, "/set prompt"), - (a) -> assertCommandFail(a, "/set prompt te"), (a) -> assertCommandFail(a, "/set prompt te aaa"), (a) -> assertCommandFail(a, "/set prompt te 'aaa'"), diff --git a/langtools/test/jdk/jshell/ToolReloadTest.java b/langtools/test/jdk/jshell/ToolReloadTest.java index 6779fc1eafb..0faf3e668dc 100644 --- a/langtools/test/jdk/jshell/ToolReloadTest.java +++ b/langtools/test/jdk/jshell/ToolReloadTest.java @@ -107,7 +107,7 @@ public class ToolReloadTest extends ReplToolTesting { "-: /drop A\n"), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), a -> assertCommandCheckOutput(a, "/methods", assertMethods()), - a -> assertCommandCheckOutput(a, "/classes", assertClasses()), + a -> assertCommandCheckOutput(a, "/types", assertClasses()), a -> assertCommandCheckOutput(a, "/imports", assertImports()) ); } @@ -120,11 +120,11 @@ public class ToolReloadTest extends ReplToolTesting { a -> dropMethod(a, "/drop b", "b ()I", "| dropped method b()"), a -> assertClass(a, "class A {}", "class", "A"), a -> dropClass(a, "/dr A", "class A", "| dropped class A"), - a -> assertCommand(a, "/reload quiet", + a -> assertCommand(a, "/reload -quiet", "| Restarting and restoring state."), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), a -> assertCommandCheckOutput(a, "/methods", assertMethods()), - a -> assertCommandCheckOutput(a, "/classes", assertClasses()), + a -> assertCommandCheckOutput(a, "/types", assertClasses()), a -> assertCommandCheckOutput(a, "/imports", assertImports()) ); } @@ -169,7 +169,7 @@ public class ToolReloadTest extends ReplToolTesting { "(int)int", "m"), (a) -> evaluateExpression(a, "int", "m(x)", "25"), (a) -> assertCommand(a, "/reset", "| Resetting state."), - (a) -> assertCommand(a, "/reload restore", + (a) -> assertCommand(a, "/reload -restore", "| Restarting and restoring from previous state.\n" + "-: int x = 5;\n" + "-: int m(int z) { return z * z; }\n" + @@ -188,8 +188,8 @@ public class ToolReloadTest extends ReplToolTesting { (a) -> evaluateExpression(a, "int", "m(x)", "25"), (a) -> assertCommand(a, "System.exit(1);", "| State engine terminated.\n" + - "| Restore definitions with: /reload restore"), - (a) -> assertCommand(a, "/reload restore", + "| Restore definitions with: /reload -restore"), + (a) -> assertCommand(a, "/reload -restore", "| Restarting and restoring from previous state.\n" + "-: int x = 5;\n" + "-: int m(int z) { return z * z; }\n" + @@ -208,7 +208,7 @@ public class ToolReloadTest extends ReplToolTesting { (a) -> evaluateExpression(a, "int", "m(x)", "25") ); test(false, new String[]{"-nostartup"}, - (a) -> assertCommand(a, "/reload restore", + (a) -> assertCommand(a, "/reload -restore", "| Restarting and restoring from previous state.\n" + "-: int x = 5;\n" + "-: int m(int z) { return z * z; }\n" + diff --git a/langtools/test/jdk/jshell/ToolRetainTest.java b/langtools/test/jdk/jshell/ToolRetainTest.java new file mode 100644 index 00000000000..e2eef0e8beb --- /dev/null +++ b/langtools/test/jdk/jshell/ToolRetainTest.java @@ -0,0 +1,168 @@ +/* + * 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 8157200 + * @summary Tests of what information is retained across jshell tool runs + * @modules jdk.jshell/jdk.internal.jshell.tool + * @build ToolRetainTest ReplToolTesting + * @run testng ToolRetainTest + */ + +import org.testng.annotations.Test; + +@Test +public class ToolRetainTest extends ReplToolTesting { + + public void testRetainMode() { + test( + (a) -> assertCommand(a, "/set mode trm -quiet", "| Created new feedback mode: trm"), + (a) -> assertCommand(a, "/set feedback trm", ""), + (a) -> assertCommand(a, "/set format trm display '{name}:{value}'", ""), + (a) -> assertCommand(a, "int x = 45", "x:45"), + (a) -> assertCommand(a, "/retain mode trm", ""), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommand(a, "/set feedback trm", ""), + (a) -> assertCommand(a, "int x = 45", "x:45") + ); + } + + public void testRetain2Mode() { + test( + (a) -> assertCommand(a, "/set mode trm1 -quiet", "| Created new feedback mode: trm1"), + (a) -> assertCommand(a, "/retain mode trm1", ""), + (a) -> assertCommand(a, "/retain feedback trm1", ""), + (a) -> assertCommand(a, "/set format trm1 display '{name}:{value}'", ""), + (a) -> assertCommand(a, "int x = 66", "x:66"), + (a) -> assertCommand(a, "/retain mode trm1", ""), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommand(a, "/set mode trm2 -quiet", ""), + (a) -> assertCommand(a, "/set format trm2 display '{name}={value}'", ""), + (a) -> assertCommand(a, "int x = 45", "x:45"), + (a) -> assertCommand(a, "/retain mode trm2", ""), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommand(a, "int x = 99", "x:99"), + (a) -> assertCommand(a, "/set feedback trm2", ""), + (a) -> assertCommand(a, "int z = 77", "z=77") + ); + } + + public void testRetainFeedback() { + test( + (a) -> assertCommand(a, "/retain feedback verbose", "| Feedback mode: verbose"), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommandOutputContains(a, "int h =8", "| created variable h : int") + ); + } + + public void testRetainFeedbackBlank() { + test( + (a) -> assertCommand(a, "/set feedback verbose", "| Feedback mode: verbose"), + (a) -> assertCommand(a, "/retain feedback", ""), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommandOutputContains(a, "int qw = 5", "| created variable qw : int") + ); + } + + public void testRetainEditor() { + test( + (a) -> assertCommand(a, "/retain editor nonexistent", "| Editor set to: nonexistent"), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommandOutputContains(a, "int h =8", ""), + (a) -> assertCommandOutputContains(a, "/edit h", "Edit Error:") + ); + } + + public void testRetainEditorBlank() { + test( + (a) -> assertCommand(a, "/set editor nonexistent", "| Editor set to: nonexistent"), + (a) -> assertCommand(a, "/retain editor", ""), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommandOutputContains(a, "int h =8", ""), + (a) -> assertCommandOutputContains(a, "/edit h", "Edit Error:") + ); + } + + public void testRetainModeNeg() { + test( + (a) -> assertCommandOutputStartsWith(a, "/retain mode verbose", + "| Not valid with a predefined mode"), + (a) -> assertCommandOutputStartsWith(a, "/retain mode ????", + "| Expected a feedback mode name: ????") + ); + } + + public void testRetainFeedbackNeg() { + test( + (a) -> assertCommandOutputStartsWith(a, "/retain feedback babble1", + "| Does not match any current feedback mode"), + (a) -> assertCommand(a, "/set mode trfn", + "| Created new feedback mode: trfn"), + (a) -> assertCommandOutputContains(a, "/retain feedback trfn", + "is predefined or has been retained"), + (a) -> assertCommandOutputStartsWith(a, "/retain feedback !!!!", + "| Expected a feedback mode name: !!!!") + ); + } + + public void testNoRetainMode() { + test( + (a) -> assertCommand(a, "/set mode trm -quiet", "| Created new feedback mode: trm"), + (a) -> assertCommand(a, "/set feedback trm", ""), + (a) -> assertCommand(a, "/set format trm display '{name}:{value}'", ""), + (a) -> assertCommand(a, "int x = 45", "x:45"), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommandOutputStartsWith(a, "/set feedback trm", + "| Does not match any current feedback mode"), + (a) -> assertCommandOutputContains(a, "int x = 45", "==> 45") + ); + } + + public void testNoRetainFeedback() { + test( + (a) -> assertCommand(a, "/set feedback verbose", "| Feedback mode: verbose"), + (a) -> assertCommand(a, "/exit", "") + ); + test( + (a) -> assertCommand(a, "int h =8", "h ==> 8") + ); + } + +} diff --git a/langtools/test/jdk/jshell/ToolSimpleTest.java b/langtools/test/jdk/jshell/ToolSimpleTest.java index b0c97a77f0b..064e63366f8 100644 --- a/langtools/test/jdk/jshell/ToolSimpleTest.java +++ b/langtools/test/jdk/jshell/ToolSimpleTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8153716 8143955 8151754 8150382 + * @bug 8153716 8143955 8151754 8150382 8153920 8156910 * @summary Simple jshell tool tests * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -101,22 +101,22 @@ public class ToolSimpleTest extends ReplToolTesting { ); } - public void defineClasses() { + public void defineTypes() { test( (a) -> assertCommandCheckOutput(a, "/list", assertList()), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertClass(a, "class A { }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/list", assertList()), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertClass(a, "interface A { }", "interface", "A"), (a) -> assertCommandCheckOutput(a, "/list", assertList()), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertClass(a, "enum A { }", "enum", "A"), (a) -> assertCommandCheckOutput(a, "/list", assertList()), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertClass(a, "@interface A { }", "@interface", "A"), (a) -> assertCommandCheckOutput(a, "/list", assertList()), - (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()) + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()) ); } @@ -179,15 +179,14 @@ public class ToolSimpleTest extends ReplToolTesting { } public void testNoArgument() { - String[] commands = {"/save", "/open", "/set start"}; - test(Stream.of(commands) - .map(cmd -> { - String c = cmd; - final String finalC = c; - return (ReplTest) after -> assertCommand(after, cmd, - "| '" + finalC + "' requires a filename argument."); - }) - .toArray(ReplTest[]::new)); + test( + (a) -> assertCommand(a, "/save", + "| '/save' requires a filename argument."), + (a) -> assertCommand(a, "/open", + "| '/open' requires a filename argument."), + (a) -> assertCommand(a, "/set start", + "| Specify either one option or a startup file name -- /set start") + ); } public void testDebug() { @@ -211,7 +210,7 @@ public class ToolSimpleTest extends ReplToolTesting { a -> dropImport(a, "/drop 4", "import java.util.stream.*", ""), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), a -> assertCommandCheckOutput(a, "/methods", assertMethods()), - a -> assertCommandCheckOutput(a, "/classes", assertClasses()), + a -> assertCommandCheckOutput(a, "/types", assertClasses()), a -> assertCommandCheckOutput(a, "/imports", assertImports()) ); test(false, new String[]{"-nostartup"}, @@ -223,20 +222,22 @@ public class ToolSimpleTest extends ReplToolTesting { a -> dropClass(a, "/drop A", "class A", "| dropped class A"), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), a -> assertCommandCheckOutput(a, "/methods", assertMethods()), - a -> assertCommandCheckOutput(a, "/classes", assertClasses()), + a -> assertCommandCheckOutput(a, "/types", assertClasses()), a -> assertCommandCheckOutput(a, "/imports", assertImports()) ); } public void testDropNegative() { test(false, new String[]{"-nostartup"}, - a -> assertCommandOutputStartsWith(a, "/drop 0", "| No definition or id found named: 0"), - a -> assertCommandOutputStartsWith(a, "/drop a", "| No definition or id found named: a"), + a -> assertCommandOutputStartsWith(a, "/drop 0", "| No such snippet: 0"), + a -> assertCommandOutputStartsWith(a, "/drop a", "| No such snippet: a"), a -> assertCommandCheckOutput(a, "/drop", assertStartsWith("| In the /drop argument, please specify an import, variable, method, or class to drop.")), a -> assertVariable(a, "int", "a"), a -> assertCommand(a, "a", "a ==> 0"), - a -> assertCommand(a, "/drop 2", "| The argument did not specify an active import, variable, method, or class to drop.") + a -> assertCommand(a, "/drop 2", + "| This command does not accept the snippet '2' : a\n" + + "| See /types, /methods, /vars, or /list") ); } @@ -253,7 +254,7 @@ public class ToolSimpleTest extends ReplToolTesting { a -> assertCommandCheckOutput(a, "/drop a", check), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), a -> assertCommandCheckOutput(a, "/methods", assertMethods()), - a -> assertCommandCheckOutput(a, "/classes", assertClasses()), + a -> assertCommandCheckOutput(a, "/types", assertClasses()), a -> assertCommandCheckOutput(a, "/imports", assertImports()) ); test( @@ -284,7 +285,7 @@ public class ToolSimpleTest extends ReplToolTesting { (a) -> assertHelp(a, "/?", "/list", "/help", "/exit", "intro"), (a) -> assertHelp(a, "/help", "/list", "/help", "/exit", "intro"), (a) -> assertHelp(a, "/help short", "shortcuts", ""), - (a) -> assertHelp(a, "/? /li", "/list all", "snippets"), + (a) -> assertHelp(a, "/? /li", "/list -all", "snippets"), (a) -> assertHelp(a, "/help /help", "/help ") ); } @@ -299,7 +300,10 @@ public class ToolSimpleTest extends ReplToolTesting { // Check that each line of output contains the corresponding string from the list private void checkLineToList(String in, List match) { - String[] res = in.trim().split("\n"); + String trimmed = in.trim(); + String[] res = trimmed.isEmpty() + ? new String[0] + : trimmed.split("\n"); assertEquals(res.length, match.size(), "Got: " + Arrays.asList(res)); for (int i = 0; i < match.size(); ++i) { assertTrue(res[i].contains(match.get(i))); @@ -311,23 +315,132 @@ public class ToolSimpleTest extends ReplToolTesting { List startVarList = new ArrayList<>(START_UP); startVarList.add("int aardvark"); test( - a -> assertCommandCheckOutput(a, "/list all", + a -> assertCommandCheckOutput(a, "/list -all", s -> checkLineToList(s, START_UP)), a -> assertCommandOutputStartsWith(a, "/list " + arg, - "| No definition or id found named: " + arg), + "| No such snippet: " + arg), a -> assertVariable(a, "int", "aardvark"), a -> assertCommandOutputContains(a, "/list aardvark", "aardvark"), - a -> assertCommandCheckOutput(a, "/list start", + a -> assertCommandCheckOutput(a, "/list -start", s -> checkLineToList(s, START_UP)), - a -> assertCommandCheckOutput(a, "/list all", + a -> assertCommandCheckOutput(a, "/list -all", s -> checkLineToList(s, startVarList)), a -> assertCommandCheckOutput(a, "/list printf", s -> assertTrue(s.contains("void printf"))), a -> assertCommandOutputStartsWith(a, "/list " + arg, - "| No definition or id found named: " + arg) + "| No such snippet: " + arg) ); } + public void testVarsArgs() { + String arg = "qqqq"; + List startVarList = new ArrayList<>(); + test( + a -> assertCommandCheckOutput(a, "/vars -all", + s -> checkLineToList(s, startVarList)), + a -> assertCommand(a, "/vars " + arg, + "| No such snippet: " + arg), + a -> assertVariable(a, "int", "aardvark"), + a -> assertMethod(a, "int f() { return 0; }", "()int", "f"), + a -> assertVariable(a, "int", "a"), + a -> assertVariable(a, "double", "a", "1", "1.0"), + a -> assertCommandOutputStartsWith(a, "/vars aardvark", + "| int aardvark = 0"), + a -> assertCommandCheckOutput(a, "/vars -start", + s -> checkLineToList(s, startVarList)), + a -> assertCommandOutputStartsWith(a, "/vars -all", + "| int aardvark = 0\n| int a = "), + a -> assertCommandOutputStartsWith(a, "/vars printf", + "| This command does not accept the snippet 'printf'"), + a -> assertCommand(a, "/var " + arg, + "| No such snippet: " + arg) + ); + } + + public void testMethodsArgs() { + String arg = "qqqq"; + List startMethodList = new ArrayList<>(START_UP_CMD_METHOD); + test( + a -> assertCommandCheckOutput(a, "/methods -all", + s -> checkLineToList(s, startMethodList)), + a -> assertCommandCheckOutput(a, "/methods -start", + s -> checkLineToList(s, startMethodList)), + a -> assertCommandCheckOutput(a, "/methods printf", + s -> checkLineToList(s, startMethodList)), + a -> assertCommandCheckOutput(a, "/methods", + s -> checkLineToList(s, startMethodList)), + a -> assertCommandOutputStartsWith(a, "/methods " + arg, + "| No such snippet: " + arg), + a -> assertMethod(a, "int f() { return 0; }", "()int", "f"), + a -> assertVariable(a, "int", "aardvark"), + a -> assertMethod(a, "void f(int a) { g(); }", "(int)void", "f"), + a -> assertMethod(a, "void g() {}", "()void", "g"), + a -> assertCommandOutputStartsWith(a, "/methods " + arg, + "| No such snippet: " + arg), + a -> assertCommandOutputStartsWith(a, "/methods aardvark", + "| This command does not accept the snippet 'aardvark' : int aardvark"), + a -> assertCommandCheckOutput(a, "/methods -start", + s -> checkLineToList(s, startMethodList)), + a -> assertCommandCheckOutput(a, "/methods printf", + s -> checkLineToList(s, startMethodList)), + a -> assertCommandOutputStartsWith(a, "/methods g", + "| g ()void"), + a -> assertCommandOutputStartsWith(a, "/methods f", + "| f ()int\n" + + "| f (int)void") + ); + } + + public void testTypesArgs() { + String arg = "qqqq"; + List startTypeList = new ArrayList<>(); + test( + a -> assertCommandCheckOutput(a, "/types -all", + s -> checkLineToList(s, startTypeList)), + a -> assertCommandCheckOutput(a, "/types -start", + s -> checkLineToList(s, startTypeList)), + a -> assertCommandOutputStartsWith(a, "/types " + arg, + "| No such snippet: " + arg), + a -> assertVariable(a, "int", "aardvark"), + (a) -> assertClass(a, "class A { }", "class", "A"), + (a) -> assertClass(a, "interface A { }", "interface", "A"), + a -> assertCommandOutputStartsWith(a, "/types -all", + "| class A\n" + + "| interface A"), + (a) -> assertClass(a, "enum E { }", "enum", "E"), + (a) -> assertClass(a, "@interface B { }", "@interface", "B"), + a -> assertCommand(a, "/types aardvark", + "| This command does not accept the snippet 'aardvark' : int aardvark;"), + a -> assertCommandOutputStartsWith(a, "/types A", + "| interface A"), + a -> assertCommandOutputStartsWith(a, "/types E", + "| enum E"), + a -> assertCommandOutputStartsWith(a, "/types B", + "| @interface B"), + a -> assertCommandOutputStartsWith(a, "/types " + arg, + "| No such snippet: " + arg), + a -> assertCommandCheckOutput(a, "/types -start", + s -> checkLineToList(s, startTypeList)) + ); + } + public void defineClasses() { + test( + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), + (a) -> assertClass(a, "class A { }", "class", "A"), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), + (a) -> assertClass(a, "interface A { }", "interface", "A"), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), + (a) -> assertClass(a, "enum A { }", "enum", "A"), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), + (a) -> assertClass(a, "@interface A { }", "@interface", "A"), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/types", assertClasses()) + ); + } public void testCommandPrefix() { test(a -> assertCommandCheckOutput(a, "/s", assertStartsWith("| Command: '/s' is ambiguous: /save, /set")), @@ -338,18 +451,6 @@ public class ToolSimpleTest extends ReplToolTesting { assertStartsWith("| '/save' requires a filename argument."))); } - public void testHeadlessEditPad() { - String prevHeadless = System.getProperty("java.awt.headless"); - try { - System.setProperty("java.awt.headless", "true"); - test( - (a) -> assertCommandOutputStartsWith(a, "/edit printf", "| Cannot launch editor -- unexpected exception:") - ); - } finally { - System.setProperty("java.awt.headless", prevHeadless==null? "false" : prevHeadless); - } - } - public void testOptionQ() { test(new String[]{"-q", "-nostartup"}, (a) -> assertCommand(a, "1+1", "$1 ==> 2"), @@ -384,4 +485,11 @@ public class ToolSimpleTest extends ReplToolTesting { "$1 ==> \"blorp\"") ); } + + public void test8156910() { + test( + (a) -> assertCommandOutputContains(a, "System.out.println(\"%5d\", 10);", "%5d"), + (a) -> assertCommandOutputContains(a, "1234", "==> 1234") + ); + } } diff --git a/langtools/test/tools/all/RunCodingRules.java b/langtools/test/tools/all/RunCodingRules.java index 4e3d5db7f33..8e345ce1b5e 100644 --- a/langtools/test/tools/all/RunCodingRules.java +++ b/langtools/test/tools/all/RunCodingRules.java @@ -50,6 +50,17 @@ import javax.tools.ToolProvider; import com.sun.tools.javac.util.Assert; +/** + * This is a test to verify specific coding standards for source code in the langtools repository. + * + * As such, it is not a standard unit, regression or functional test, and will + * automatically skip if the langtools source code is not available. + * + * If the source code is available, it will find and compile the coding + * style analyzers found in langtools/make/tools/crules/*.java, and run the resulting + * code on all source files under langtools/src/share/classes. Any coding style + * violations will cause the test to fail. + */ public class RunCodingRules { public static void main(String... args) throws Exception { new RunCodingRules().run(); diff --git a/langtools/test/tools/javac/DefiniteAssignment/8156180/T8156180.java b/langtools/test/tools/javac/DefiniteAssignment/8156180/T8156180.java new file mode 100644 index 00000000000..9a310817cb6 --- /dev/null +++ b/langtools/test/tools/javac/DefiniteAssignment/8156180/T8156180.java @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8156180 + * @summary javac accepts code that violates JLS chapter 16 + * + * @compile/fail/ref=T8156180.out -XDrawDiagnostics T8156180.java + */ + +class T8156180 { + public final int a1, b1, c1, d1; + public int a2, b2, c2, d2; + + T8156180(int value) { + a2 = this.a1; + b2 = (this).b1; + c2 = ((this)).c1; + d2 = (((this))).d1; + a1 = value; + b1 = value; + c1 = value; + d1 = value; + } +} diff --git a/langtools/test/tools/javac/DefiniteAssignment/8156180/T8156180.out b/langtools/test/tools/javac/DefiniteAssignment/8156180/T8156180.out new file mode 100644 index 00000000000..7668ee4a9cc --- /dev/null +++ b/langtools/test/tools/javac/DefiniteAssignment/8156180/T8156180.out @@ -0,0 +1,5 @@ +T8156180.java:14:18: compiler.err.var.might.not.have.been.initialized: a1 +T8156180.java:15:20: compiler.err.var.might.not.have.been.initialized: b1 +T8156180.java:16:22: compiler.err.var.might.not.have.been.initialized: c1 +T8156180.java:17:24: compiler.err.var.might.not.have.been.initialized: d1 +4 errors diff --git a/langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out b/langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out index 246900b8f49..fe2b6fd5297 100644 --- a/langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out +++ b/langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out @@ -1,5 +1,5 @@ T8012003b.java:30:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, java.lang.String, compiler.misc.no.args, kindname.class, T8012003b, (compiler.misc.arg.length.mismatch))) -T8012003b.java:31:16: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void)) +T8012003b.java:31:16: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) T8012003b.java:32:22: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.conditional.target.cant.be.void)) T8012003b.java:33:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String))) T8012003b.java:34:12: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer)) diff --git a/langtools/test/tools/javac/Paths/MineField.sh b/langtools/test/tools/javac/Paths/MineField.sh index f9843c44998..064071f0733 100644 --- a/langtools/test/tools/javac/Paths/MineField.sh +++ b/langtools/test/tools/javac/Paths/MineField.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2003, 2015, 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 @@ -25,7 +25,7 @@ # # @test -# @bug 4758537 4809833 +# @bug 4758537 4809833 8149599 # @summary Test that javac and java find files in similar ways # @author Martin Buchholz # @@ -49,14 +49,33 @@ # - Only for the user classpath is an empty string value equivalent to "." # - Specifying a bootclasspath on the command line obliterates any # previous -Xbootclasspath/p: or -Xbootclasspath/a: command line flags. +# +# JDK 9 update: +# java: The java launcher does not support any of the following: +# * -Xbootclasspath/p: -Xbootclasspath: +# * -endorseddirs -Djava.endorsed.dirs +# * -extdirs -Djava.ext.dirs +# All test cases exercising these features have been removed. +# javac: The following features are only supported when compiling +# for older releases: +# * -Xbootclasspath/p: -Xbootclasspath: -bootclasspath -Xbootclasspath/a: +# * -endorseddirs -Djava.endorsed.dirs +# * -extdirs -Djava.ext.dirs +# All test cases exercising these features have been modified to +# use -source 8 -target 8. In addition, javac test cases involving +# use of the runtime properties java.endorsed.dirs and java.extdirs +# (by means of -J-Dname=value) have been removed. +# Although the primary purpose of the test cases in this file is to +# compare javac and java behavior, some tests remain for javac for +# which there is no java equivalent. However, the cases remain as useful +# test cases for javac handling of the paths involved. + #---------------------------------------------------------------- . ${TESTSRC-.}/Util.sh set -u -# BCP=`DefaultBootClassPath` - #---------------------------------------------------------------- # Prepare the "Minefield" #---------------------------------------------------------------- @@ -64,6 +83,7 @@ Cleanup() { Sys rm -rf GooSrc GooJar GooZip GooClass Sys rm -rf BadSrc BadJar BadZip BadClass Sys rm -rf OneDir *.class Main.java MANIFEST.MF + Sys rm -f java-lang.jar } Cleanup @@ -88,215 +108,95 @@ CheckFiles BadZip/Lib.zip BadJar/Lib.jar BadSrc/Lib.java echo 'public class Main {public static void main(String[] a) {Lib.f();}}' > Main.java +# Create a jar file that is good enough to put on the javac boot class path (i.e. contains java.lang.**) +Sys "$jimage" extract --dir modules ${TESTJAVA}/lib/modules +Sys "$jar" cf java-lang.jar -C modules/java.base java/lang +Sys rm -rf modules + #---------------------------------------------------------------- # Verify that javac class search order is the same as java's #---------------------------------------------------------------- -# Failure "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"BadClass" \ -# -J-Djava.endorsed.dirs="GooJar" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \ -# -J-Djava.endorsed.dirs="BadJar${PS}GooZip" \ -# Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/p:"BadClass" \ -# -Djava.endorsed.dirs="GooJar" \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \ -# -Djava.endorsed.dirs="BadJar${PS}GooZip" \ -# Main +Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -Xbootclasspath/p:"GooClass" \ + -bootclasspath "java-lang.jar${PS}BadZip/Lib.zip" \ + Main.java +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -Xbootclasspath/p:"BadClass${PS}GooClass" \ + -bootclasspath "java-lang.jar${PS}GooZip/Lib.zip${PS}BadClass" \ + Main.java +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -Xbootclasspath/p:"BadJar/Lib.jar" \ + -Xbootclasspath:"java-lang.jar${PS}GooClass" \ + Main.java #---------------------------------------------------------------- -# Failure "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"GooClass" \ -# -bootclasspath "$BCP${PS}BadZip/Lib.zip" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"BadClass${PS}GooClass" \ -# -bootclasspath "$BCP${PS}GooZip/Lib.zip${PS}BadClass" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"BadJar/Lib.jar" \ -# -Xbootclasspath:"$BCP${PS}GooClass" \ -# Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/p:"GooClass" \ -# -Xbootclasspath:"$BCP${PS}BadZip/Lib.zip" \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/p:"BadClass${PS}GooClass" \ -# -Xbootclasspath:"$BCP${PS}GooZip/Lib.zip${PS}BadClass" \ -# Main +Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -bootclasspath "java-lang.jar${PS}GooZip/Lib.zip" \ + -Xbootclasspath/p:"BadClass" \ + Main.java +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -bootclasspath "java-lang.jar${PS}BadZip/Lib.zip" \ + -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \ + Main.java #---------------------------------------------------------------- -# Failure "$javac" ${TESTTOOLVMOPTS} \ -# -bootclasspath "$BCP${PS}GooZip/Lib.zip" \ -# -Xbootclasspath/p:"BadClass" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -bootclasspath "$BCP${PS}BadZip/Lib.zip" \ -# -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \ -# Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Xbootclasspath:"$BCP${PS}GooClass" \ -# -Xbootclasspath/p:"BadClass" \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Xbootclasspath:"$BCP${PS}BadClass" \ -# -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \ -# Main - -#---------------------------------------------------------------- -Failure "$javac" ${TESTTOOLVMOPTS} \ +Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ -Xbootclasspath/p:"BadClass" \ -Xbootclasspath/a:"GooClass" \ Main.java -Success "$javac" ${TESTTOOLVMOPTS} \ +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ -Xbootclasspath/p:"GooClass${PS}BadClass" \ -Xbootclasspath/a:"BadClass" \ Main.java -Failure "$java" ${TESTVMOPTS} \ - -Xbootclasspath/p:"BadClass" \ - -Xbootclasspath/a:"GooClass" \ - Main Success "$java" ${TESTVMOPTS} \ - -Xbootclasspath/p:"GooClass${PS}BadClass" \ - -Xbootclasspath/a:"BadClass" \ + -Xbootclasspath/a:"GooClass" \ Main #---------------------------------------------------------------- -# Failure "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"GooClass" \ -# -J-Djava.endorsed.dirs="BadZip" \ -# -bootclasspath "GooClass${PS}$BCP" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"BadClass" \ -# -J-Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \ -# -bootclasspath "BadClass${PS}$BCP" \ -# Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/p:"GooClass" \ -# -Djava.endorsed.dirs="BadZip" \ -# -Xbootclasspath:"GooClass${PS}$BCP" \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/p:"BadClass" \ -# -Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \ -# -Xbootclasspath:"BadClass${PS}$BCP" \ -# Main +Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -Xbootclasspath/p:"GooClass" \ + -Xbootclasspath:"BadClass${PS}java-lang.jar" \ + -Xbootclasspath/a:"GooClass" \ + Main.java +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -Xbootclasspath/p:"BadClass" \ + -Xbootclasspath:"GooClass${PS}BadClass${PS}java-lang.jar" \ + -Xbootclasspath/a:"BadClass" \ + Main.java #---------------------------------------------------------------- -# Failure "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"GooClass" \ -# -Xbootclasspath:"BadClass${PS}$BCP" \ -# -Xbootclasspath/a:"GooClass" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -Xbootclasspath/p:"BadClass" \ -# -Xbootclasspath:"GooClass${PS}BadClass${PS}$BCP" \ -# -Xbootclasspath/a:"BadClass" \ -# Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/p:"GooClass" \ -# -Xbootclasspath:"BadClass${PS}$BCP" \ -# -Xbootclasspath/a:"GooClass" \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/p:"BadClass" \ -# -Xbootclasspath:"GooClass${PS}BadClass${PS}$BCP" \ -# -Xbootclasspath/a:"BadClass" \ -# Main +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -endorseddirs "BadClass${PS}GooZip${PS}BadJar" \ + -Xbootclasspath:"BadClass${PS}java-lang.jar" \ + Main.java +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ + -Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \ + -Xbootclasspath:"BadClass${PS}java-lang.jar" \ + Main.java #---------------------------------------------------------------- -# Failure "$javac" ${TESTTOOLVMOPTS} \ -# -J-Djava.endorsed.dirs="BadZip" \ -# -Xbootclasspath:"GooClass${PS}$BCP" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -endorseddirs "BadClass${PS}GooZip${PS}BadJar" \ -# -Xbootclasspath:"BadClass${PS}$BCP" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \ -# -Xbootclasspath:"BadClass${PS}$BCP" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -J-Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \ -# -Xbootclasspath:"BadClass${PS}$BCP" \ -# Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Djava.endorsed.dirs="BadZip" \ -# -Xbootclasspath:"GooClass${PS}$BCP" \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \ -# -Xbootclasspath:"BadClass${PS}$BCP" \ -# Main - -#---------------------------------------------------------------- -Failure "$javac" ${TESTTOOLVMOPTS} \ +Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ -Xbootclasspath/a:"BadClass" \ -extdirs "GooZip" \ Main.java -Success "$javac" ${TESTTOOLVMOPTS} \ +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ -Xbootclasspath/a:"GooClass${PS}BadClass" \ -extdirs "BadZip" \ Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/a:"BadClass" \ -# -Djava.ext.dirs="GooZip" \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Xbootclasspath/a:"GooClass${PS}BadClass" \ -# -Djava.ext.dirs="BadZip" \ -# Main #---------------------------------------------------------------- -# Failure "$javac" ${TESTTOOLVMOPTS} \ -# -bootclasspath "$BCP${PS}BadJar/Lib.jar" \ -# -J-Djava.ext.dir="GooJar" \ -# Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -bootclasspath "$BCP${PS}GooJar/Lib.jar${PS}BadClass" \ -# -J-Djava.ext.dir="BadJar" \ -# Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Xbootclasspath:"$BCP${PS}BadJar/Lib.jar" \ -# -Djava.ext.dirs="GooJar" \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Xbootclasspath:"$BCP${PS}GooJar/Lib.jar${PS}BadClass" \ -# -Djava.ext.dirs="BadJar" \ -# Main - -#---------------------------------------------------------------- -Failure "$javac" ${TESTTOOLVMOPTS} \ +Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ -extdirs "GooClass${PS}BadZip" \ -cp "GooZip/Lib.zip" \ Main.java -Success "$javac" ${TESTTOOLVMOPTS} \ +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ -extdirs "BadClass${PS}GooZip${PS}BadJar" \ -cp "BadZip/Lib.zip" \ Main.java -Success "$javac" ${TESTTOOLVMOPTS} \ +Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \ -Djava.ext.dirs="GooZip${PS}BadJar" \ -classpath "BadZip/Lib.zip" \ Main.java -# Success "$javac" ${TESTTOOLVMOPTS} \ -# -J-Djava.ext.dirs="GooZip${PS}BadJar" \ -# -classpath "BadZip/Lib.zip" \ -# Main.java -# Failure "$java" ${TESTVMOPTS} \ -# -Djava.ext.dirs="GooClass${PS}BadZip" \ -# -cp "GooZip/Lib.zip${PS}." \ -# Main -# Success "$java" ${TESTVMOPTS} \ -# -Djava.ext.dirs="GooZip${PS}BadJar" \ -# -cp "BadZip/Lib.zip${PS}." \ -# Main #---------------------------------------------------------------- Failure "$javac" ${TESTTOOLVMOPTS} -classpath "BadClass${PS}GooClass" Main.java @@ -338,45 +238,32 @@ In GooClass Success "$javac" ${TESTTOOLVMOPTS} -cp "..${PS}${PS}/xyzzy" ../Main. In GooClass Success "$java" ${TESTVMOPTS} -cp "..${PS}${PS}/xyzzy" Main # All other empty path elements are ignored. -In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -extdirs "" -cp ".." ../Main.java -# In GooJar Failure "$java" ${TESTVMOPTS} -Djava.ext.dirs="" -cp ".." Main +In GooJar Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -extdirs "" -cp ".." ../Main.java -In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -extdirs "${PS}" -cp ".." ../Main.java -In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -Djava.ext.dirs="${PS}" -cp ".." ../Main.java -# In GooJar Failure "$java" ${TESTVMOPTS} -Djava.ext.dirs="${PS}" -cp ".." Main +In GooJar Failure "$javac" -source 8 -targt 8 ${TESTTOOLVMOPTS} -extdirs "${PS}" -cp ".." ../Main.java +In GooJar Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Djava.ext.dirs="${PS}" -cp ".." ../Main.java -In GooJar Success "$javac" ${TESTTOOLVMOPTS} -extdirs "." -cp ".." ../Main.java -In GooJar Success "$javac" ${TESTTOOLVMOPTS} -Djava.ext.dirs="." -cp ".." ../Main.java -# In GooJar Success "$java" ${TESTVMOPTS} -Djava.ext.dirs="." -cp ".." Main +In GooJar Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -extdirs "." -cp ".." ../Main.java +In GooJar Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Djava.ext.dirs="." -cp ".." ../Main.java -# In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -J-Djava.endorsed.dirs="" -cp ".." ../Main.java -In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -Djava.endorsed.dirs="" -cp ".." ../Main.java -# In GooJar Failure "$java" ${TESTVMOPTS} -Djava.endorsed.dirs="" -cp ".." Main +In GooJar Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Djava.endorsed.dirs="" -cp ".." ../Main.java -# In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -J-Djava.endorsed.dirs="${PS}" -cp ".." ../Main.java -In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -endorseddirs "${PS}" -cp ".." ../Main.java -# In GooJar Failure "$java" ${TESTVMOPTS} -Djava.endorsed.dirs="${PS}" -cp ".." Main +In GooJar Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -endorseddirs "${PS}" -cp ".." ../Main.java -# In GooJar Success "$javac" ${TESTTOOLVMOPTS} -J-Djava.endorsed.dirs="." -cp ".." ../Main.java -In GooJar Success "$javac" ${TESTTOOLVMOPTS} -Djava.endorsed.dirs="." -cp ".." ../Main.java -# In GooJar Success "$java" ${TESTVMOPTS} -Djava.endorsed.dirs="." -cp ".." Main +In GooJar Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Djava.endorsed.dirs="." -cp ".." ../Main.java -In GooClass Failure "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/p: -cp ".." ../Main.java -In GooClass Failure "$java" ${TESTVMOPTS} -Xbootclasspath/p: -cp ".." Main +In GooClass Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath/p: -cp ".." ../Main.java -In GooClass Success "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/p:. -cp ".." ../Main.java -In GooClass Success "$java" ${TESTVMOPTS} -Xbootclasspath/p:. -cp ".." Main +In GooClass Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath/p:. -cp ".." ../Main.java -# In GooClass Failure "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath:"$BCP" -cp ".." ../Main.java -# In GooClass Failure "$java" ${TESTVMOPTS} -Xbootclasspath:"$BCP" -cp ".." Main +In GooClass Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath:"../java-lang.jar" -cp ".." ../Main.java -# In GooClass Success "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath:"$BCP${PS}." -cp ".." ../Main.java -# In GooClass Success "$java" ${TESTVMOPTS} -Xbootclasspath:"$BCP${PS}." -cp ".." Main +In GooClass Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath:"../java-lang.jar${PS}." -cp ".." ../Main.java -In GooClass Failure "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/a: -cp ".." ../Main.java +In GooClass Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath/a: -cp ".." ../Main.java In GooClass Failure "$java" ${TESTVMOPTS} -Xbootclasspath/a: -cp ".." Main -In GooClass Success "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/a:. -cp ".." ../Main.java +In GooClass Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath/a:. -cp ".." ../Main.java In GooClass Success "$java" ${TESTVMOPTS} -Xbootclasspath/a:. -cp ".." Main Cleanup diff --git a/langtools/test/tools/javac/Paths/Util.sh b/langtools/test/tools/javac/Paths/Util.sh index 3f41f707804..1befd80ff10 100644 --- a/langtools/test/tools/javac/Paths/Util.sh +++ b/langtools/test/tools/javac/Paths/Util.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2014, 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 @@ -24,9 +24,10 @@ # Utilities for shell tests : ${TESTSRC=.} ${TESTCLASSES=.} - java="${TESTJAVA+${TESTJAVA}/bin/}java" -javac="${TESTJAVA+${TESTJAVA}/bin/}javac" - jar="${TESTJAVA+${TESTJAVA}/bin/}jar" + java="${TESTJAVA+${TESTJAVA}/bin/}java" + javac="${TESTJAVA+${TESTJAVA}/bin/}javac" + jar="${TESTJAVA+${TESTJAVA}/bin/}jar" +jimage="${TESTJAVA+${TESTJAVA}/bin/}jimage" case `uname -s` in Windows*|CYGWIN*) @@ -105,21 +106,6 @@ BadJarFile() { for jarfilename in "$@"; do pwd > "$jarfilename"; done } -# #---------------------------------------------------------------- -# # Usage: BCP=`DefaultBootClassPath` -# # Returns default bootclasspath, discarding non-existent entries -# #---------------------------------------------------------------- -# DefaultBootClassPath() { -# echo 'public class B {public static void main(String[] a) { -# System.out.println(System.getProperty("sun.boot.class.path"));}}' > B.java -# "$javac" ${TESTTOOLVMOPTS} B.java -# _BCP_="" -# for elt in `"$java" ${TESTVMOPTS} B | tr "${PS}" " "`; do -# test -r "$elt" -a -n "$elt" && _BCP_="${_BCP_:+${_BCP_}${PS}}${elt}" -# done -# rm -f B.java B.class -# printf "%s" "$_BCP_" # Don't use echo -- unsafe on Windows -# } #---------------------------------------------------------------- # Foil message localization diff --git a/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java b/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java index a6a4cde8f55..3134c72991c 100644 --- a/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java +++ b/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java @@ -108,14 +108,14 @@ public class DetectMutableStaticFields { // when running javac on JDK 8. ignore("com/sun/tools/javac/util/ModuleHelper", "addExportsMethod", "getModuleMethod", "getUnnamedModuleMethod"); - ignore("com/sun/tools/javac/util/ModuleWrappers$ConfigurationHelper", + ignore("com/sun/tools/javac/util/JDK9Wrappers$Configuration", "resolveRequiresAndUsesMethod", "configurationClass"); - ignore("com/sun/tools/javac/util/ModuleWrappers$LayerHelper", + ignore("com/sun/tools/javac/util/JDK9Wrappers$Layer", "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod", "layerClass"); - ignore("com/sun/tools/javac/util/ModuleWrappers$ModuleFinderHelper", - "emptyMethod", "moduleFinderInterface", "ofMethod"); - - + ignore("com/sun/tools/javac/util/JDK9Wrappers$ModuleFinder", + "moduleFinderClass", "ofMethod"); + ignore("com/sun/tools/javac/util/JDK9Wrappers$ServiceLoaderHelper", + "loadMethod"); } private final List errors = new ArrayList<>(); diff --git a/langtools/test/tools/javac/T8152360/DeprecateJavahTest.java b/langtools/test/tools/javac/T8152360/DeprecateJavahTest.java new file mode 100644 index 00000000000..f0a0a41dadc --- /dev/null +++ b/langtools/test/tools/javac/T8152360/DeprecateJavahTest.java @@ -0,0 +1,79 @@ +/* + * 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 8152360 + * @summary deprecate javah + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javah + * @build toolbox.ToolBox toolbox.JavahTask + * @run main DeprecateJavahTest + */ + +import toolbox.JavahTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class DeprecateJavahTest { + public static void main(String... args) throws Exception { + new DeprecateJavahTest().run(); + } + + ToolBox tb = new ToolBox(); + + void printDeprecationWarning() throws Exception { + String output = new JavahTask(tb) + .options("-version") + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!output.contains( + "Warning: The javah tool is planned to be removed in the next major\n" + + "JDK release. The tool has been superseded by the '-h' option added\n" + + "to javac in JDK 8. Users are recommended to migrate to using the\n" + + "javac '-h' option; see the javac man page for more information.")) { + throw new Exception("test failed"); + } + } + + void dontPrintDeprecationWarning() throws Exception { + String output = new JavahTask(tb) + .options("-version", "-XDsuppress-tool-removal-message") + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!output.startsWith("javah version")) { + throw new Exception("test failed"); + } + } + + void run() throws Exception { + printDeprecationWarning(); + dontPrintDeprecationWarning(); + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/8047024/T8047024.java b/langtools/test/tools/javac/annotations/typeAnnotations/8047024/T8047024.java new file mode 100644 index 00000000000..e749bc73b15 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/8047024/T8047024.java @@ -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. + */ + +/* + * @test + * @bug 8047024 + * @summary AssertionError: exception_index already contains a bytecode offset + * @compile T8047024_01.java + * @compile -XDsave-parameter-names=true T8047024.java + */ + +public class T8047024 { + public static void main(String [] args) { + T8047024_01.run(); + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/8047024/T8047024_01.java b/langtools/test/tools/javac/annotations/typeAnnotations/8047024/T8047024_01.java new file mode 100644 index 00000000000..fa1a06f748f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/8047024/T8047024_01.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +public class T8047024_01 { + + @Target(ElementType.TYPE_USE) + @interface TA {} + + public static void run() { + try { + System.out.println(""); + } catch (@TA Throwable e) { + + } + } +} diff --git a/langtools/test/tools/javac/diags/EagerInitCheck.java b/langtools/test/tools/javac/diags/EagerInitCheck.java new file mode 100644 index 00000000000..d0f34d5ca8f --- /dev/null +++ b/langtools/test/tools/javac/diags/EagerInitCheck.java @@ -0,0 +1,33 @@ +/* + * 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 8154052 + * @summary Java compiler error displays line from the wrong file + * @compile/fail/ref=EagerInitCheck.out -XDrawDiagnostics EagerInitCheck.java + */ + +public class EagerInitCheck implements IEagerInitCheck { + float x = VAL; +} \ No newline at end of file diff --git a/langtools/test/tools/javac/diags/EagerInitCheck.out b/langtools/test/tools/javac/diags/EagerInitCheck.out new file mode 100644 index 00000000000..6c2c03563eb --- /dev/null +++ b/langtools/test/tools/javac/diags/EagerInitCheck.out @@ -0,0 +1,2 @@ +IEagerInitCheck.java:25:17: compiler.err.prob.found.req: (compiler.misc.possible.loss.of.precision: double, float) +1 error \ No newline at end of file diff --git a/langtools/test/tools/javac/diags/Example.java b/langtools/test/tools/javac/diags/Example.java index e7e25560048..b9c09cf0e2e 100644 --- a/langtools/test/tools/javac/diags/Example.java +++ b/langtools/test/tools/javac/diags/Example.java @@ -63,6 +63,8 @@ class Example implements Comparable { procFiles = new ArrayList(); supportFiles = new ArrayList(); srcPathFiles = new ArrayList(); + moduleSourcePathFiles = new ArrayList(); + additionalFiles = new ArrayList(); findFiles(file, srcFiles); for (File f: srcFiles) { @@ -81,13 +83,23 @@ class Example implements Comparable { else if (files == srcFiles && c.getName().equals("sourcepath")) { srcPathDir = c; findFiles(c, srcPathFiles); + } else if (files == srcFiles && c.getName().equals("modulesourcepath")) { + moduleSourcePathDir = c; + findFiles(c, moduleSourcePathFiles); + } else if (files == srcFiles && c.getName().equals("additional")) { + additionalFilesDir = c; + findFiles(c, additionalFiles); } else if (files == srcFiles && c.getName().equals("support")) findFiles(c, supportFiles); else findFiles(c, files); } - } else if (f.isFile() && f.getName().endsWith(".java")) { - files.add(f); + } else if (f.isFile()) { + if (f.getName().endsWith(".java")) { + files.add(f); + } else if (f.getName().equals("modulesourcepath")) { + moduleSourcePathDir = f; + } } } @@ -228,14 +240,27 @@ class Example implements Comparable { } } + List files = srcFiles; + if (srcPathDir != null) { opts.add("-sourcepath"); opts.add(srcPathDir.getPath()); } + if (moduleSourcePathDir != null) { + opts.add("-modulesourcepath"); + opts.add(moduleSourcePathDir.getPath()); + files = moduleSourcePathFiles; + } + + if (additionalFiles.size() > 0) { + List sOpts = Arrays.asList("-d", classesDir.getPath()); + new Jsr199Compiler(verbose).run(null, null, false, sOpts, additionalFiles); + } + try { Compiler c = Compiler.getCompiler(runOpts, verbose); - c.run(out, keys, raw, opts, srcFiles); + c.run(out, keys, raw, opts, files); } catch (IllegalArgumentException e) { if (out != null) { out.println("Invalid value for run tag: " + runOpts); @@ -298,7 +323,11 @@ class Example implements Comparable { List srcFiles; List procFiles; File srcPathDir; + File moduleSourcePathDir; + File additionalFilesDir; List srcPathFiles; + List moduleSourcePathFiles; + List additionalFiles; List supportFiles; File infoFile; private List runOpts; diff --git a/langtools/test/tools/javac/diags/IEagerInitCheck.java b/langtools/test/tools/javac/diags/IEagerInitCheck.java new file mode 100644 index 00000000000..24ae4074505 --- /dev/null +++ b/langtools/test/tools/javac/diags/IEagerInitCheck.java @@ -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. + */ + +public interface IEagerInitCheck { + float VAL = 1.0; +} \ No newline at end of file diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 6e2e5e70ffc..cfe33c94385 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -110,67 +110,26 @@ compiler.err.cant.inherit.from.anon # error for subclass of compiler.misc.bad.class.file # class file is malformed compiler.misc.bad.const.pool.entry # constant pool entry has wrong type -# The following are new module-related messages, that need new examples to be created -compiler.err.addmods.all.module.path.invalid -compiler.err.cant.find.module -compiler.err.cyclic.requires -compiler.err.duplicate.exports -compiler.err.duplicate.module +# The following module-related messages will have to stay on the not-yet list for various reasons: +compiler.warn.locn.unknown.file.on.module.path # Never issued ATM (short circuited with an if (false)) +compiler.err.no.output.dir # -d is always specified by test infrastructure +compiler.err.output.dir.must.be.specified.with.dash.m.option # -d is always specified by test infrastructure +compiler.warn.outdir.is.in.exploded.module # No control over -d specified by test infrastructure +compiler.err.invalid.module.specifier # Not possible (?) +compiler.err.locn.cant.get.module.name.for.jar # bad binary ? Infer module name failure +compiler.misc.bad.module-info.name # bad class file +compiler.err.locn.bad.module-info # bad class file +compiler.err.locn.cant.read.file # bad class file +compiler.err.locn.cant.read.directory # file system issue +compiler.misc.unnamed.module # fragment uninteresting in and of itself +compiler.misc.kindname.module # fragment uninteresting in and of itself +compiler.misc.locn.module_path # fragment uninteresting in and of itself +compiler.misc.locn.module_source_path # fragment uninteresting in and of itself +compiler.misc.locn.system_modules # fragment uninteresting in and of itself +compiler.misc.locn.upgrade_module_path # fragment uninteresting in and of itself + +# The following are new module-related messages, that need new examples to be created compiler.err.duplicate.module.on.path -compiler.err.duplicate.provides -compiler.err.duplicate.requires -compiler.err.duplicate.uses -compiler.err.expected.module -compiler.err.illegal.argument.for.option -compiler.err.invalid.module.specifier -compiler.err.locn.bad.module-info -compiler.err.locn.cant.get.module.name.for.jar -compiler.err.locn.cant.read.directory -compiler.err.locn.cant.read.file -compiler.err.locn.invalid.arg.for.xpatch compiler.err.locn.module-info.not.allowed.on.patch.path -compiler.err.module-info.with.xmodule.classpath -compiler.err.module-info.with.xmodule.sourcepath -compiler.err.module.decl.sb.in.module-info.java -compiler.err.module.name.mismatch -compiler.err.module.not.found -compiler.err.module.not.found.in.module.source.path -compiler.err.modules.not.supported.in.source -compiler.err.modulesourcepath.must.be.specified.with.dash.m.option -compiler.err.multi-module.outdir.cannot.be.exploded.module -compiler.err.no.output.dir -compiler.err.not.def.access.package.cant.access -compiler.err.output.dir.must.be.specified.with.dash.m.option -compiler.err.package.clash.from.requires -compiler.err.package.empty.or.not.found -compiler.err.package.in.other.module -compiler.err.processorpath.no.processormodulepath -compiler.err.service.definition.is.inner -compiler.err.service.definition.is.enum -compiler.err.service.implementation.doesnt.have.a.no.args.constructor -compiler.err.service.implementation.is.abstract -compiler.err.service.implementation.is.inner -compiler.err.service.implementation.no.args.constructor.not.public -compiler.err.service.implementation.not.in.right.module -compiler.err.too.many.modules -compiler.err.unexpected.after.module -compiler.err.unnamed.pkg.not.allowed.named.modules -compiler.err.xaddexports.malformed.entry -compiler.err.xaddexports.too.many -compiler.err.xaddreads.malformed.entry -compiler.err.xaddreads.too.many -compiler.err.xmodule.no.module.sourcepath -compiler.misc.bad.module-info.name compiler.misc.cant.resolve.modules compiler.misc.file.does.not.contain.module -compiler.misc.kindname.module -compiler.misc.locn.module_path -compiler.misc.locn.module_source_path -compiler.misc.locn.system_modules -compiler.misc.locn.upgrade_module_path -compiler.misc.unnamed.module -compiler.warn.dir.path.element.not.directory -compiler.warn.locn.unknown.file.on.module.path -compiler.warn.outdir.is.in.exploded.module -compiler.warn.service.provided.but.not.exported.or.used - diff --git a/langtools/test/tools/javac/diags/examples/AddmodsAllModulePathInvalid/module-info.java b/langtools/test/tools/javac/diags/examples/AddmodsAllModulePathInvalid/module-info.java new file mode 100644 index 00000000000..95c566a9467 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/AddmodsAllModulePathInvalid/module-info.java @@ -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. + */ + +// key: compiler.err.addmods.all.module.path.invalid +// options: -addmods ALL-MODULE-PATH +module m {} diff --git a/langtools/test/tools/javac/diags/examples/CantFindModule/CantFindModule.java b/langtools/test/tools/javac/diags/examples/CantFindModule/CantFindModule.java new file mode 100644 index 00000000000..5446a4b1ee8 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/CantFindModule/CantFindModule.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +// key: compiler.err.cant.find.module +// key: compiler.err.doesnt.exist + +// options: -XaddExports:undef/undef=ALL-UNNAMED + +import undef.Any; + +class Test {} diff --git a/langtools/test/tools/javac/diags/examples/CyclicRequires/CyclicRequires.java b/langtools/test/tools/javac/diags/examples/CyclicRequires/CyclicRequires.java new file mode 100644 index 00000000000..0d852014dae --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/CyclicRequires/CyclicRequires.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.err.cyclic.requires diff --git a/langtools/test/tools/javac/diags/examples/CyclicRequires/modulesourcepath/m1/module-info.java b/langtools/test/tools/javac/diags/examples/CyclicRequires/modulesourcepath/m1/module-info.java new file mode 100644 index 00000000000..438f579baac --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/CyclicRequires/modulesourcepath/m1/module-info.java @@ -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 { + requires m2; +} diff --git a/langtools/test/tools/javac/diags/examples/CyclicRequires/modulesourcepath/m2/module-info.java b/langtools/test/tools/javac/diags/examples/CyclicRequires/modulesourcepath/m2/module-info.java new file mode 100644 index 00000000000..45858e70c3f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/CyclicRequires/modulesourcepath/m2/module-info.java @@ -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 m2 { + requires m1; +} diff --git a/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java b/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java new file mode 100644 index 00000000000..9fb276d932e --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.warn.dir.path.element.not.directory +// options: -Xlint:path +// run: simple + +class DirPathElementNotDirectory { } diff --git a/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/modulesourcepath b/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/modulesourcepath new file mode 100644 index 00000000000..42c5a0cf3a1 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/modulesourcepath @@ -0,0 +1,25 @@ +/* + * 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. + */ + +// a file to be passed in where a directory is expected (-modulesourcepath option) +// to trigger an error deliberately. diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java b/langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java new file mode 100644 index 00000000000..31f14202663 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public class Class { +} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java new file mode 100644 index 00000000000..4c3b2903508 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.duplicate.exports + +module DuplicateExports { + exports exported; + exports exported; +} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateModule/DuplicateModule.java b/langtools/test/tools/javac/diags/examples/DuplicateModule/DuplicateModule.java new file mode 100644 index 00000000000..d5350d4368b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateModule/DuplicateModule.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +// key: compiler.err.duplicate.module +// key: compiler.err.module.name.mismatch diff --git a/langtools/test/tools/javac/diags/examples/DuplicateModule/modulesourcepath/m1/module-info.java b/langtools/test/tools/javac/diags/examples/DuplicateModule/modulesourcepath/m1/module-info.java new file mode 100644 index 00000000000..c46643d1805 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateModule/modulesourcepath/m1/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 blah {} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateModule/modulesourcepath/m2/module-info.java b/langtools/test/tools/javac/diags/examples/DuplicateModule/modulesourcepath/m2/module-info.java new file mode 100644 index 00000000000..c46643d1805 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateModule/modulesourcepath/m2/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 blah {} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateProvides/exported/Service.java b/langtools/test/tools/javac/diags/examples/DuplicateProvides/exported/Service.java new file mode 100644 index 00000000000..b5b1029655b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateProvides/exported/Service.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public interface Service { +} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateProvides/impl/ServiceImplementation.java b/langtools/test/tools/javac/diags/examples/DuplicateProvides/impl/ServiceImplementation.java new file mode 100644 index 00000000000..37403f59660 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateProvides/impl/ServiceImplementation.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 impl; + +import exported.Service; + +public class ServiceImplementation implements Service { +} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateProvides/module-info.java b/langtools/test/tools/javac/diags/examples/DuplicateProvides/module-info.java new file mode 100644 index 00000000000..d8e2916f86d --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateProvides/module-info.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +// key: compiler.err.duplicate.provides + +module DuplicateExports { + exports exported; + provides exported.Service with impl.ServiceImplementation; + provides exported.Service with impl.ServiceImplementation; +} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateRequires/module-info.java b/langtools/test/tools/javac/diags/examples/DuplicateRequires/module-info.java new file mode 100644 index 00000000000..b253c6ef0de --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateRequires/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.duplicate.requires + +module DuplicateRequires { + requires java.se; + requires java.se; +} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateUses/exported/Service.java b/langtools/test/tools/javac/diags/examples/DuplicateUses/exported/Service.java new file mode 100644 index 00000000000..b5b1029655b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateUses/exported/Service.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public interface Service { +} diff --git a/langtools/test/tools/javac/diags/examples/DuplicateUses/module-info.java b/langtools/test/tools/javac/diags/examples/DuplicateUses/module-info.java new file mode 100644 index 00000000000..6edf4c0b972 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateUses/module-info.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +// key: compiler.err.duplicate.uses + +module DuplicateExports { + exports exported; + uses exported.Service; + uses exported.Service; +} diff --git a/langtools/test/tools/javac/diags/examples/IllegalArgumentForOption/IllegalArgumentForOption.java b/langtools/test/tools/javac/diags/examples/IllegalArgumentForOption/IllegalArgumentForOption.java new file mode 100644 index 00000000000..81205c4a845 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/IllegalArgumentForOption/IllegalArgumentForOption.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.illegal.argument.for.option +// options: -modulepath doesNotExist +// run: simple + +class X {} diff --git a/langtools/test/tools/javac/diags/examples/InvalidArgForXPatch/InvalidArgForXpatch.java b/langtools/test/tools/javac/diags/examples/InvalidArgForXPatch/InvalidArgForXpatch.java new file mode 100644 index 00000000000..20d501b0dd7 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/InvalidArgForXPatch/InvalidArgForXpatch.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +// key: compiler.err.locn.invalid.arg.for.xpatch +// options: -Xpatch:blah + +class InvalidArgForXpatch {} diff --git a/langtools/test/tools/javac/diags/examples/ModuleDeclSbInModuleInfoJava.java b/langtools/test/tools/javac/diags/examples/ModuleDeclSbInModuleInfoJava.java new file mode 100644 index 00000000000..f5db585301b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleDeclSbInModuleInfoJava.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +//key: compiler.err.module.decl.sb.in.module-info.java + +module ModuleDeclSbInModuleInfoJava { +} diff --git a/langtools/test/tools/javac/diags/examples/ModuleInfoWithXModuleSourcePath/Extra.java b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXModuleSourcePath/Extra.java new file mode 100644 index 00000000000..cafc425479d --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXModuleSourcePath/Extra.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.module-info.with.xmodule.sourcepath +// options: -Xmodule:java.compiler + +package javax.lang.model.element; + +public interface Extra {} diff --git a/langtools/test/tools/javac/diags/examples/ModuleInfoWithXModuleSourcePath/module-info.java b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXModuleSourcePath/module-info.java new file mode 100644 index 00000000000..79715268b7a --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXModuleSourcePath/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 java.compiler {} diff --git a/langtools/test/tools/javac/diags/examples/ModuleInfoWithXmoduleClasspath/ModuleInfoWithXmoduleClasspath.java b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXmoduleClasspath/ModuleInfoWithXmoduleClasspath.java new file mode 100644 index 00000000000..a9ea8197d3b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXmoduleClasspath/ModuleInfoWithXmoduleClasspath.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.module-info.with.xmodule.classpath +// options: -Xmodule:java.compiler + +package javax.lang.model.element; + +public interface ModuleInfoWithXModuleClasspath {} diff --git a/langtools/test/tools/javac/diags/examples/ModuleInfoWithXmoduleClasspath/additional/module-info.java b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXmoduleClasspath/additional/module-info.java new file mode 100644 index 00000000000..6faf7dbee92 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXmoduleClasspath/additional/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 mod {} diff --git a/langtools/test/tools/javac/diags/examples/ModuleInfoWithoutModule/ModuleInfoWithoutModule.java b/langtools/test/tools/javac/diags/examples/ModuleInfoWithoutModule/ModuleInfoWithoutModule.java new file mode 100644 index 00000000000..ce34abe92d0 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithoutModule/ModuleInfoWithoutModule.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.err.expected.module diff --git a/langtools/test/tools/javac/diags/examples/ModuleInfoWithoutModule/modulesourcepath/m1/module-info.java b/langtools/test/tools/javac/diags/examples/ModuleInfoWithoutModule/modulesourcepath/m1/module-info.java new file mode 100644 index 00000000000..7c7bc4d83ed --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithoutModule/modulesourcepath/m1/module-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// No module description here diff --git a/langtools/test/tools/javac/diags/examples/ModuleNameMismatch/ModuleNameMismatch.java b/langtools/test/tools/javac/diags/examples/ModuleNameMismatch/ModuleNameMismatch.java new file mode 100644 index 00000000000..9b55ba79eb9 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleNameMismatch/ModuleNameMismatch.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.err.module.name.mismatch diff --git a/langtools/test/tools/javac/diags/examples/ModuleNameMismatch/modulesourcepath/m/module-info.java b/langtools/test/tools/javac/diags/examples/ModuleNameMismatch/modulesourcepath/m/module-info.java new file mode 100644 index 00000000000..760ce2e4d8c --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleNameMismatch/modulesourcepath/m/module-info.java @@ -0,0 +1,25 @@ +/* + * 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 other { +} diff --git a/langtools/test/tools/javac/diags/examples/ModuleNotFound/module-info.java b/langtools/test/tools/javac/diags/examples/ModuleNotFound/module-info.java new file mode 100644 index 00000000000..3d6b488f976 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleNotFound/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.module.not.found + +module m { + requires does.not.exist; +} diff --git a/langtools/test/tools/javac/diags/examples/ModuleNotFoundInModuleSourcePath/ModuleNotFoundInModuleSourcePath.java b/langtools/test/tools/javac/diags/examples/ModuleNotFoundInModuleSourcePath/ModuleNotFoundInModuleSourcePath.java new file mode 100644 index 00000000000..71d1df029d1 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleNotFoundInModuleSourcePath/ModuleNotFoundInModuleSourcePath.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +// key: compiler.err.module.not.found.in.module.source.path +// options: -m m1 -modulesourcepath src + +class ModuleNotFoundInModuleSourcePath {} diff --git a/langtools/test/tools/javac/diags/examples/ModuleSourcePathMustWithDashM/ModuleSourcePathMustWithDashM.java b/langtools/test/tools/javac/diags/examples/ModuleSourcePathMustWithDashM/ModuleSourcePathMustWithDashM.java new file mode 100644 index 00000000000..8c920104d1e --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModuleSourcePathMustWithDashM/ModuleSourcePathMustWithDashM.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +// key: compiler.err.modulesourcepath.must.be.specified.with.dash.m.option +// options: -m m1 -d blah diff --git a/langtools/test/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java b/langtools/test/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java new file mode 100644 index 00000000000..5b53cb4d956 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.modules.not.supported.in.source +// key: compiler.warn.source.no.bootclasspath +// options: -source 8 -Xlint:-path + +module ModulesNotSupportedInSource { +} diff --git a/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/MultiModuleOutputCannotBeExplodedModule.java b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/MultiModuleOutputCannotBeExplodedModule.java new file mode 100644 index 00000000000..095f629a6b9 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/MultiModuleOutputCannotBeExplodedModule.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.err.multi-module.outdir.cannot.be.exploded.module diff --git a/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/additional/m1/module-info.java b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/additional/m1/module-info.java new file mode 100644 index 00000000000..f6ecf6b2bf5 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/additional/m1/module-info.java @@ -0,0 +1,25 @@ +/* + * 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 { +} diff --git a/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/modulesourcepath/m2/module-info.java b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/modulesourcepath/m2/module-info.java new file mode 100644 index 00000000000..3c14a447dbd --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/modulesourcepath/m2/module-info.java @@ -0,0 +1,25 @@ +/* + * 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 m2 { +} diff --git a/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/NotDefAccessClassPackageCantAccess.java b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/NotDefAccessClassPackageCantAccess.java new file mode 100644 index 00000000000..e40cbd30a7e --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/NotDefAccessClassPackageCantAccess.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.err.not.def.access.package.cant.access diff --git a/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m1/module-info.java b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m1/module-info.java new file mode 100644 index 00000000000..7a304970b51 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m1/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 {} diff --git a/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m1/p1/C1.java b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m1/p1/C1.java new file mode 100644 index 00000000000..08db623ec1f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m1/p1/C1.java @@ -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. + */ + +package p1; + +public class C1 {} diff --git a/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m2/module-info.java b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m2/module-info.java new file mode 100644 index 00000000000..8963c28c731 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m2/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 m2 {} diff --git a/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m2/p2/C2.java b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m2/p2/C2.java new file mode 100644 index 00000000000..0f9bf2104d4 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m2/p2/C2.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 p2; + +public class C2 { + p1.C1 c1; +} diff --git a/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/PackageClashFromRequires.java b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/PackageClashFromRequires.java new file mode 100644 index 00000000000..743f585c05b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/PackageClashFromRequires.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.err.package.clash.from.requires diff --git a/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib1/exported/Api1.java b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib1/exported/Api1.java new file mode 100644 index 00000000000..48ffdf78717 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib1/exported/Api1.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public class Api1 { +} diff --git a/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib1/module-info.java b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib1/module-info.java new file mode 100644 index 00000000000..fbe84ddc5b2 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib1/module-info.java @@ -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 lib1 { + exports exported; +} diff --git a/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib2/exported/Api2.java b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib2/exported/Api2.java new file mode 100644 index 00000000000..9470a22439d --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib2/exported/Api2.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public class Api2 { +} diff --git a/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib2/module-info.java b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib2/module-info.java new file mode 100644 index 00000000000..d1ede79a1c4 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib2/module-info.java @@ -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 lib2 { + exports exported; +} diff --git a/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/use/module-info.java b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/use/module-info.java new file mode 100644 index 00000000000..00d5d0c750f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/use/module-info.java @@ -0,0 +1,27 @@ +/* + * 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 use { + requires lib1; + requires lib2; +} diff --git a/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/PackageEmptyOrNotFound.java b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/PackageEmptyOrNotFound.java new file mode 100644 index 00000000000..fe43a9f9729 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/PackageEmptyOrNotFound.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.err.package.empty.or.not.found diff --git a/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/modulesourcepath/m1/module-info.java b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/modulesourcepath/m1/module-info.java new file mode 100644 index 00000000000..44b2d01cb41 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/modulesourcepath/m1/module-info.java @@ -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 p1; +} diff --git a/langtools/test/tools/javac/diags/examples/PackageInOtherModule/PackageInOtherModule.java b/langtools/test/tools/javac/diags/examples/PackageInOtherModule/PackageInOtherModule.java new file mode 100644 index 00000000000..9922411df52 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PackageInOtherModule/PackageInOtherModule.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.package.in.other.module + +package java.util; + +class PackageInOtherModule {} diff --git a/langtools/test/tools/javac/diags/examples/ProcessorPathNoProcessorModulePath/ProcessorPathNoProcessorModulePath.java b/langtools/test/tools/javac/diags/examples/ProcessorPathNoProcessorModulePath/ProcessorPathNoProcessorModulePath.java new file mode 100644 index 00000000000..2e5d323df34 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ProcessorPathNoProcessorModulePath/ProcessorPathNoProcessorModulePath.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +// key: compiler.err.processorpath.no.processormodulepath +// options: -processormodulepath mods -processorpath mods + +class ProcessorPathNoProcessorModulePath {} diff --git a/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/ServiceDefinitionInner.java b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/ServiceDefinitionInner.java new file mode 100644 index 00000000000..f519259636d --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/ServiceDefinitionInner.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +// key: compiler.err.service.definition.is.inner +// key: compiler.err.encl.class.required diff --git a/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/module-info.java new file mode 100644 index 00000000000..137812f03fb --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/module-info.java @@ -0,0 +1,27 @@ +/* + * 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 m { + provides p1.C1.InnerDefinition with p2.C2; + exports p1; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p1/C1.java b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p1/C1.java new file mode 100644 index 00000000000..ac25babd764 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p1/C1.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 p1; + +public class C1 { + public class InnerDefinition {} +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p2/C2.java b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p2/C2.java new file mode 100644 index 00000000000..cb3738cd735 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p2/C2.java @@ -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. + */ + +package p2; + +public class C2 extends p1.C1.InnerDefinition {} diff --git a/langtools/test/tools/javac/diags/examples/ServiceDefinitionIsEnum/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceDefinitionIsEnum/module-info.java new file mode 100644 index 00000000000..5a227501119 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionIsEnum/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.service.definition.is.enum + +module m { + uses pkg.EnumST; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceDefinitionIsEnum/pkg/EnumST.java b/langtools/test/tools/javac/diags/examples/ServiceDefinitionIsEnum/pkg/EnumST.java new file mode 100644 index 00000000000..4f75a1f969b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionIsEnum/pkg/EnumST.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 pkg; + +public enum EnumST { + A, + B +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/exported/Service.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/exported/Service.java new file mode 100644 index 00000000000..b5b1029655b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/exported/Service.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public interface Service { +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/impl/ServiceImplementation.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/impl/ServiceImplementation.java new file mode 100644 index 00000000000..0534dd83ba8 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/impl/ServiceImplementation.java @@ -0,0 +1,31 @@ +/* + * 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 impl; + +import exported.Service; + +public class ServiceImplementation implements Service { + public ServiceImplementation(int i) { + } +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/module-info.java new file mode 100644 index 00000000000..24dc3f6bbad --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.service.implementation.doesnt.have.a.no.args.constructor + +module ServiceImplementationDoesntHaveANoArgsConstructor { + exports exported; + provides exported.Service with impl.ServiceImplementation; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/exported/Service.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/exported/Service.java new file mode 100644 index 00000000000..b5b1029655b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/exported/Service.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public interface Service { +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/impl/ServiceImplementation.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/impl/ServiceImplementation.java new file mode 100644 index 00000000000..a3a3ed48e9f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/impl/ServiceImplementation.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 impl; + +import exported.Service; + +public abstract class ServiceImplementation implements Service { +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/module-info.java new file mode 100644 index 00000000000..7f5fb6179a8 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.service.implementation.is.abstract + +module ServiceImplementationDoesntHaveANoArgsConstructor { + exports exported; + provides exported.Service with impl.ServiceImplementation; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/exported/Service.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/exported/Service.java new file mode 100644 index 00000000000..b5b1029655b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/exported/Service.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public interface Service { +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/impl/ServiceImplementation.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/impl/ServiceImplementation.java new file mode 100644 index 00000000000..947b34bb09f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/impl/ServiceImplementation.java @@ -0,0 +1,31 @@ +/* + * 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 impl; + +import exported.Service; + +public class ServiceImplementation { + public class Inner implements Service { + } +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/module-info.java new file mode 100644 index 00000000000..4ebe4a79c23 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.service.implementation.is.inner + +module ServiceImplementationIsInner { + exports exported; + provides exported.Service with impl.ServiceImplementation.Inner; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/exported/Service.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/exported/Service.java new file mode 100644 index 00000000000..b5b1029655b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/exported/Service.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public interface Service { +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/impl/ServiceImplementation.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/impl/ServiceImplementation.java new file mode 100644 index 00000000000..ee554053289 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/impl/ServiceImplementation.java @@ -0,0 +1,31 @@ +/* + * 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 impl; + +import exported.Service; + +public class ServiceImplementation implements Service { + ServiceImplementation() { + } +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/module-info.java new file mode 100644 index 00000000000..379f771026c --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.service.implementation.no.args.constructor.not.public + +module ServiceImplementationNoArgsConstructorNotPublic { + exports exported; + provides exported.Service with impl.ServiceImplementation; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/ServiceImplementationNotInRightModule.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/ServiceImplementationNotInRightModule.java new file mode 100644 index 00000000000..f5eb40bb66a --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/ServiceImplementationNotInRightModule.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.err.service.implementation.not.in.right.module diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/exported/Service.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/exported/Service.java new file mode 100644 index 00000000000..b5b1029655b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/exported/Service.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public interface Service { +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/exported/ServiceImplementation.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/exported/ServiceImplementation.java new file mode 100644 index 00000000000..d45b0debd4d --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/exported/ServiceImplementation.java @@ -0,0 +1,27 @@ +/* + * 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 exported; + +public class ServiceImplementation implements Service { +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/module-info.java new file mode 100644 index 00000000000..1f2444a12f0 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/module-info.java @@ -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 exported; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m2/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m2/module-info.java new file mode 100644 index 00000000000..cd0acce6a1f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m2/module-info.java @@ -0,0 +1,27 @@ +/* + * 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 m2 { + requires m1; + provides exported.Service with exported.ServiceImplementation; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/ServiceProvidedButNotExportedOrUsed.java b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/ServiceProvidedButNotExportedOrUsed.java new file mode 100644 index 00000000000..3d245ddf94b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/ServiceProvidedButNotExportedOrUsed.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// key: compiler.warn.service.provided.but.not.exported.or.used diff --git a/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/module-info.java new file mode 100644 index 00000000000..9242f68814d --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/module-info.java @@ -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 m { + provides p1.C1 with p2.C2; +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/p1/C1.java b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/p1/C1.java new file mode 100644 index 00000000000..fbc31590ccc --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/p1/C1.java @@ -0,0 +1,27 @@ +/* + * 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 p1; + +public class C1 { +} diff --git a/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/p2/C2.java b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/p2/C2.java new file mode 100644 index 00000000000..4255515f55e --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/p2/C2.java @@ -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. + */ + +package p2; + +public class C2 extends p1.C1 {} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java b/langtools/test/tools/javac/diags/examples/StatExprExpected.java similarity index 83% rename from jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java rename to langtools/test/tools/javac/diags/examples/StatExprExpected.java index 9e5a4a7df61..b0091820610 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java +++ b/langtools/test/tools/javac/diags/examples/StatExprExpected.java @@ -22,16 +22,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.tools.jlink.plugin; -import java.util.Properties; +// key: compiler.err.prob.found.req +// key: compiler.misc.stat.expr.expected -/** - * Interface to plugin (container) context. - */ -public interface PluginContext { - /** - * Returns 'release' properties - */ - public Properties getReleaseProperties(); +class StatExprExpected { + void test() { + Runnable r = () -> (foo()); + } + + int foo() { return 1; } } diff --git a/langtools/test/tools/javac/diags/examples/TooManyModules/TooManyModules.java b/langtools/test/tools/javac/diags/examples/TooManyModules/TooManyModules.java new file mode 100644 index 00000000000..23268732c5a --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/TooManyModules/TooManyModules.java @@ -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. + */ + +// key: compiler.err.too.many.modules + +class TooManyModules {} diff --git a/langtools/test/tools/javac/diags/examples/TooManyModules/p1/module-info.java b/langtools/test/tools/javac/diags/examples/TooManyModules/p1/module-info.java new file mode 100644 index 00000000000..7a304970b51 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/TooManyModules/p1/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 {} diff --git a/langtools/test/tools/javac/diags/examples/TooManyModules/p2/module-info.java b/langtools/test/tools/javac/diags/examples/TooManyModules/p2/module-info.java new file mode 100644 index 00000000000..8963c28c731 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/TooManyModules/p2/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 m2 {} diff --git a/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/UnnamedPackageInNamedModule.java b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/UnnamedPackageInNamedModule.java new file mode 100644 index 00000000000..ed94f3e85fb --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/UnnamedPackageInNamedModule.java @@ -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. + */ + +// key: compiler.err.unnamed.pkg.not.allowed.named.modules + +class UnnamedPackageInNamedModule {} diff --git a/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/modulesourcepath/m1/UnnamedPackageInNamedModule.java b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/modulesourcepath/m1/UnnamedPackageInNamedModule.java new file mode 100644 index 00000000000..bfc760e51a3 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/modulesourcepath/m1/UnnamedPackageInNamedModule.java @@ -0,0 +1,24 @@ +/* + * 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 UnnamedPackageInNamedModule {} diff --git a/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/modulesourcepath/m1/module-info.java b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/modulesourcepath/m1/module-info.java new file mode 100644 index 00000000000..7a304970b51 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/modulesourcepath/m1/module-info.java @@ -0,0 +1,24 @@ +/* + * 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 {} diff --git a/langtools/test/tools/javac/diags/examples/XModuleWithModulePath/XModuleWithModulePath.java b/langtools/test/tools/javac/diags/examples/XModuleWithModulePath/XModuleWithModulePath.java new file mode 100644 index 00000000000..a378792e520 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/XModuleWithModulePath/XModuleWithModulePath.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +// key: compiler.err.xmodule.no.module.sourcepath +// options: -Xmodule:java.compiler -modulesourcepath src + +class XModuleWithModulePath {} diff --git a/langtools/test/tools/javac/diags/examples/XaddexportsMalformedEntry.java b/langtools/test/tools/javac/diags/examples/XaddexportsMalformedEntry.java new file mode 100644 index 00000000000..07d54310038 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/XaddexportsMalformedEntry.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.xaddexports.malformed.entry +// options: -XaddExports:jdk.compiler/com.sun.tools.javac.util + +public class XaddexportsMalformedEntry { +} diff --git a/langtools/test/tools/javac/diags/examples/XaddexportsTooMany.java b/langtools/test/tools/javac/diags/examples/XaddexportsTooMany.java new file mode 100644 index 00000000000..6f6c064dd40 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/XaddexportsTooMany.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.xaddexports.too.many +// options: -XaddExports:jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -XaddExports:jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED + +public class XaddexportsTooMany { +} diff --git a/langtools/test/tools/javac/diags/examples/XaddreadsMalformedEntry.java b/langtools/test/tools/javac/diags/examples/XaddreadsMalformedEntry.java new file mode 100644 index 00000000000..650cf6196a6 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/XaddreadsMalformedEntry.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.xaddreads.malformed.entry +// options: -XaddReads:jdk.compiler + +public class XaddreadsMalformedEntry { +} diff --git a/langtools/test/tools/javac/diags/examples/XaddreadsTooMany.java b/langtools/test/tools/javac/diags/examples/XaddreadsTooMany.java new file mode 100644 index 00000000000..d0b2551abc6 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/XaddreadsTooMany.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.xaddreads.too.many +// options: -XaddReads:jdk.compiler=ALL-UNNAMED -XaddReads:jdk.compiler=ALL-UNNAMED + +public class XaddreadsTooMany { +} diff --git a/langtools/test/tools/javac/file/MultiReleaseJar/MultiReleaseJarAwareSJFM.java b/langtools/test/tools/javac/file/MultiReleaseJar/MultiReleaseJarAwareSJFM.java index b4475468846..ae83a78ee7b 100644 --- a/langtools/test/tools/javac/file/MultiReleaseJar/MultiReleaseJarAwareSJFM.java +++ b/langtools/test/tools/javac/file/MultiReleaseJar/MultiReleaseJarAwareSJFM.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8149757 + * @bug 8149757 8144062 * @summary Test that StandardJavaFileManager uses the correct version of a * class from a multi-release jar on classpath * @library /tools/lib @@ -164,7 +164,7 @@ public class MultiReleaseJarAwareSJFM { {"", 8}, {"8", 8}, {"9", 9}, - {"runtime", jdk.Version.current().major()} + {"runtime", Runtime.version().major()} }; } diff --git a/jdk/src/java.desktop/share/native/libmlib_image/mlib_c_ImageBlendTable.h b/langtools/test/tools/javac/generics/inference/8156954/T8156954.java similarity index 69% rename from jdk/src/java.desktop/share/native/libmlib_image/mlib_c_ImageBlendTable.h rename to langtools/test/tools/javac/generics/inference/8156954/T8156954.java index 2e95d502478..0baab4239ab 100644 --- a/jdk/src/java.desktop/share/native/libmlib_image/mlib_c_ImageBlendTable.h +++ b/langtools/test/tools/javac/generics/inference/8156954/T8156954.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,19 +23,21 @@ * questions. */ -/* - * These tables are used by C versions of the - * mlib_ImageBlend_... functions. +/** + * @test + * @bug 8156954 + * @summary javac incorrectly complains of incompatible types + * @compile T8156954.java */ +import java.util.function.Function; -#ifndef MLIB_C_IMAGE_BLEND_TABLE_H -#define MLIB_C_IMAGE_BLEND_TABLE_H +class T8156954 { -#include "mlib_image.h" + void m1(Function f1, Function f2, R r) { } + void m2(Function f1, Function f2, R r) { } -extern const mlib_f32 mlib_c_blend_u8[]; -extern const mlib_f32 mlib_U82F32[]; -extern const mlib_f32 mlib_c_blend_Q8[]; -extern const mlib_f32 mlib_c_blend_u8_sat[]; - -#endif /* MLIB_C_IMAGEF_BLEND_TABLE_H */ + void m(Integer intValue) { + m1(o -> o, o -> o , intValue); + m2(o -> o, o -> o , intValue); + } +} diff --git a/langtools/test/tools/javac/generics/inference/8157149/T8157149a.java b/langtools/test/tools/javac/generics/inference/8157149/T8157149a.java new file mode 100644 index 00000000000..8808b2f7cef --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/8157149/T8157149a.java @@ -0,0 +1,28 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8157149 + * @summary Inference: weird propagation of thrown inference variables + * + * @compile/fail/ref=T8157149a.out -XDrawDiagnostics T8157149a.java + */ + +import java.io.IOException; + +class T8157149a { + Z m_T() throws Z { return null; } + Z m_E() throws Z { return null; } + + void test_T() { + Throwable t1 = m_T(); + Exception t2 = m_T(); + RuntimeException t3 = m_T(); + IOException t4 = m_T(); //thrown not caught + } + + void test_E() { + Throwable t1 = m_E(); + Exception t2 = m_E(); + RuntimeException t3 = m_E(); + IOException t4 = m_E(); //thrown not caught + } +} diff --git a/langtools/test/tools/javac/generics/inference/8157149/T8157149a.out b/langtools/test/tools/javac/generics/inference/8157149/T8157149a.out new file mode 100644 index 00000000000..057238dee69 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/8157149/T8157149a.out @@ -0,0 +1,3 @@ +T8157149a.java:19:28: compiler.err.unreported.exception.need.to.catch.or.throw: java.io.IOException +T8157149a.java:26:28: compiler.err.unreported.exception.need.to.catch.or.throw: java.io.IOException +2 errors diff --git a/langtools/test/tools/javac/generics/inference/8157149/T8157149b.java b/langtools/test/tools/javac/generics/inference/8157149/T8157149b.java new file mode 100644 index 00000000000..adacefd5fb4 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/8157149/T8157149b.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8157149 + * @summary Inference: weird propagation of thrown inference variables + * + * @compile T8157149b.java + */ + +class T8157149b { + + void test() { + computeException1(this::computeThrowable); + computeException2(this::computeThrowable); + computeException1(() -> { + Integer integer = computeThrowable(); + return integer; + }); + computeException2(() -> { + Integer integer = computeThrowable(); + return integer; + }); + } + + void computeException1(ThrowableComputable1 c) throws E {} + + void computeException2(ThrowableComputable2 c) throws E {} + + Integer computeThrowable() throws E1 { + return 0; + } + + interface ThrowableComputable1 { + T compute() throws E; + } + + interface ThrowableComputable2 { + Integer compute() throws E; + } +} diff --git a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java b/langtools/test/tools/javac/generics/inference/8157149/T8157149c.java similarity index 76% rename from jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java rename to langtools/test/tools/javac/generics/inference/8157149/T8157149c.java index 55be308348a..41fc4207a29 100644 --- a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java +++ b/langtools/test/tools/javac/generics/inference/8157149/T8157149c.java @@ -23,20 +23,27 @@ * questions. */ -package jdk.internal.vm.agent.spi; - -/** - * Service interface for jdk.hotspot.agent to provide the tools that - * jstack, jmap, jinfo will invoke, if present. +/* + * @test + * @bug 8157149 + * @summary Inference: weird propagation of thrown inference variables + * + * @compile T8157149c.java */ -public interface ToolProvider { - /** - * Returns the name of the tool provider - */ - String getName(); - /** - * Invoke the tool provider with the given arguments - */ - void run(String... arguments); +class T8157149c { + + interface I, U> { + T m(U o); + } + + static class C { + C(T f) { } + } + + void m(I, A> o1, A o2) { } + + void test(Object o) { + m(C::new, o); + } } diff --git a/langtools/test/tools/javac/lambda/8153884/T8153884.java b/langtools/test/tools/javac/lambda/8153884/T8153884.java new file mode 100644 index 00000000000..23aef92be8c --- /dev/null +++ b/langtools/test/tools/javac/lambda/8153884/T8153884.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8153884 + * @summary Expression lambda erroneously compatible with void-returning descriptor + * @compile/fail/ref=T8153884.out -XDrawDiagnostics T8153884.java + */ + +class T8153884 { + void test() { + Runnable r = () -> (foo()); + } + + void foo() { } +} diff --git a/langtools/test/tools/javac/lambda/8153884/T8153884.out b/langtools/test/tools/javac/lambda/8153884/T8153884.out new file mode 100644 index 00000000000..90826a89eab --- /dev/null +++ b/langtools/test/tools/javac/lambda/8153884/T8153884.out @@ -0,0 +1,2 @@ +T8153884.java:10:32: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) +1 error diff --git a/langtools/test/tools/javac/lambda/LambdaExpr10.out b/langtools/test/tools/javac/lambda/LambdaExpr10.out index 9270b144671..7be53354d1f 100644 --- a/langtools/test/tools/javac/lambda/LambdaExpr10.out +++ b/langtools/test/tools/javac/lambda/LambdaExpr10.out @@ -4,6 +4,6 @@ LambdaExpr10.java:23:40: compiler.err.prob.found.req: (compiler.misc.not.a.funct LambdaExpr10.java:24:46: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) LambdaExpr10.java:28:29: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) LambdaExpr10.java:29:33: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) -LambdaExpr10.java:33:35: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void)) -LambdaExpr10.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void)) +LambdaExpr10.java:33:35: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) +LambdaExpr10.java:34:49: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) 8 errors diff --git a/langtools/test/tools/javac/lambda/LambdaExprNotVoid.out b/langtools/test/tools/javac/lambda/LambdaExprNotVoid.out index 97b66c8a5ea..c2b7a682a21 100644 --- a/langtools/test/tools/javac/lambda/LambdaExprNotVoid.out +++ b/langtools/test/tools/javac/lambda/LambdaExprNotVoid.out @@ -1,3 +1,3 @@ -LambdaExprNotVoid.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void)) -LambdaExprNotVoid.java:15:21: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void)) +LambdaExprNotVoid.java:14:21: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) +LambdaExprNotVoid.java:15:21: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) 2 errors diff --git a/langtools/test/tools/javac/lambda/speculative/8154180/T8154180a.java b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180a.java new file mode 100644 index 00000000000..eebebd75712 --- /dev/null +++ b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180a.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +import java.util.function.Consumer; +import java.nio.ByteBuffer; + +/* + * @test + * @bug 8154180 + * @summary Regression: stuck expressions do not behave correctly + * @compile T8154180a.java + */ +class T8154180a { + T8154180a(Consumer cb) { } + + public static void main(String[] args) { + new T8154180a(b -> System.out.println(asString(b))); + new T8154180a((b -> System.out.println(asString(b)))); + new T8154180a(true ? b -> System.out.println(asString(b)) : b -> System.out.println(asString(b))); + new T8154180a((true ? b -> System.out.println(asString(b)) : b -> System.out.println(asString(b)))); + new T8154180a((true ? (b -> System.out.println(asString(b))) : (b -> System.out.println(asString(b))))); + } + + static String asString(ByteBuffer buf) { + return null; + } +} diff --git a/langtools/test/tools/javac/lambda/speculative/8154180/T8154180b.java b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180b.java new file mode 100644 index 00000000000..6565f66ba8b --- /dev/null +++ b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180b.java @@ -0,0 +1,27 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8154180 + * @summary Regression: stuck expressions do not behave correctly + * @compile/fail/ref=T8154180b.out -XDrawDiagnostics T8154180b.java + */ +class T8154180b { + interface Foo1 { + Object m(String s); + } + + interface Foo2 { + String m(String s); + } + + + void m(Foo1 f1) { } + void m(Foo2 f2) { } + + void test() { + m(x->""); + m((x->"")); + m(true ? x -> "" : x -> ""); + m((true ? x -> "" : x -> "")); + m((true ? (x -> "") : (x -> ""))); + } +} diff --git a/langtools/test/tools/javac/lambda/speculative/8154180/T8154180b.out b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180b.out new file mode 100644 index 00000000000..690634cc2f2 --- /dev/null +++ b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180b.out @@ -0,0 +1,6 @@ +T8154180b.java:21:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b +T8154180b.java:22:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b +T8154180b.java:23:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b +T8154180b.java:24:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b +T8154180b.java:25:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b +5 errors diff --git a/langtools/test/tools/javac/meth/TestCP.java b/langtools/test/tools/javac/meth/TestCP.java index 413c6f6c19e..4b2b277dfb2 100644 --- a/langtools/test/tools/javac/meth/TestCP.java +++ b/langtools/test/tools/javac/meth/TestCP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,9 @@ import java.io.*; public class TestCP { - static class TestClass { + static class TestMethodHandleInvokeExact { + static final String PS_TYPE = "(Ljava/lang/String;IC)Ljava/lang/Number;"; + void test(MethodHandle mh) throws Throwable { Number n = (Number)mh.invokeExact("daddy",1,'n'); n = (Number)mh.invokeExact("bunny",1,'d'); @@ -50,9 +52,43 @@ public class TestCP { } } - static final String PS_TYPE = "(Ljava/lang/String;IC)Ljava/lang/Number;"; + static class TestVarHandleGet { + static final String PS_TYPE = "(Ljava/lang/String;IC)Ljava/lang/Number;"; + + // Test with sig-poly return type + void test(VarHandle vh) throws Throwable { + Number n = (Number)vh.get("daddy",1,'n'); + n = (Number)vh.get("bunny",1,'d'); + n = (Number)(vh.get("foo",1,'d')); + n = (Number)((vh.get("bar",1,'d'))); + } + } + + static class TestVarHandleSet { + static final String PS_TYPE = "(Ljava/lang/String;IC)V"; + + // Test with non-sig-poly void return type + void test(VarHandle vh) throws Throwable { + vh.set("daddy",1,'n'); + vh.set("bunny",1,'d'); + vh.set("foo",1,'d'); + vh.set("bar",1,'d'); + } + } + + static class TestVarHandleCompareAndSet { + static final String PS_TYPE = "(Ljava/lang/String;IC)Z"; + + // Test with non-sig-poly boolean return type + void test(VarHandle vh) throws Throwable { + boolean r = vh.compareAndSet("daddy",1,'n'); + r = vh.compareAndSet("bunny",1,'d'); + r = (vh.compareAndSet("foo",1,'d')); + r = ((vh.compareAndSet("bar",1,'d'))); + } + } + static final int PS_CALLS_COUNT = 4; - static final String SUBTEST_NAME = TestClass.class.getName() + ".class"; static final String TEST_METHOD_NAME = "test"; public static void main(String... args) throws Exception { @@ -60,12 +96,32 @@ public class TestCP { } public void run() throws Exception { - String workDir = System.getProperty("test.classes"); - File compiledTest = new File(workDir, SUBTEST_NAME); - verifyMethodHandleInvocationDescriptors(compiledTest); + verifySigPolyInvokeVirtual( + getTestFile(TestMethodHandleInvokeExact.class), + TestMethodHandleInvokeExact.PS_TYPE); + + verifySigPolyInvokeVirtual( + getTestFile(TestVarHandleGet.class), + TestVarHandleGet.PS_TYPE); + + verifySigPolyInvokeVirtual( + getTestFile(TestVarHandleSet.class), + TestVarHandleSet.PS_TYPE); + + verifySigPolyInvokeVirtual( + getTestFile(TestVarHandleCompareAndSet.class), + TestVarHandleCompareAndSet.PS_TYPE); } - void verifyMethodHandleInvocationDescriptors(File f) { + static File getTestFile(Class c) { + String workDir = System.getProperty("test.classes"); + return new File(workDir, getTestName(c)); + } + static String getTestName(Class c) { + return c.getName() + ".class"; + } + + void verifySigPolyInvokeVirtual(File f, String psType) { System.err.println("verify: " + f); try { int count = 0; @@ -98,7 +154,7 @@ public class TestCP { CONSTANT_Methodref_info methRef = (CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry); String type = methRef.getNameAndTypeInfo().getType(); - if (!type.equals(PS_TYPE)) { + if (!type.equals(psType)) { throw new Error("Unexpected type in polymorphic signature call: " + type); } } diff --git a/langtools/test/tools/javac/modules/EnvVarTest.java b/langtools/test/tools/javac/modules/EnvVarTest.java new file mode 100644 index 00000000000..5d134d7fe56 --- /dev/null +++ b/langtools/test/tools/javac/modules/EnvVarTest.java @@ -0,0 +1,94 @@ +/* + * 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 8156962 + * @summary Tests use of _JAVAC_OPTIONS env variable + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @run main EnvVarTest + */ + +import java.nio.file.Path; + +import toolbox.JavacTask; +import toolbox.Task.Expect; +import toolbox.Task.Mode; + +public class EnvVarTest extends ModuleTestBase { + + public static void main(String... args) throws Exception { + new EnvVarTest().runTests(); + } + + @Test + public void testAddExports(Path base) throws Exception { + Path src = base.resolve("src"); + // the package in the following call should be one that is not + // available by default, including via @modules + tb.writeJavaFiles(src, + "package p; public class C { com.sun.tools.javac.jvm.Target t; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + tb.out.println("test that compilation fails if addExports is not provided"); + new JavacTask(tb) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Expect.FAIL) + .writeAll(); + + tb.out.println("test that addExports can be given to javac"); + new JavacTask(tb) + .options("-XaddExports:jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Expect.SUCCESS) + .writeAll(); + + tb.out.println("test that addExports can be provided with env variable"); + new JavacTask(tb, Mode.EXEC) + .envVar("_JAVAC_OPTIONS", "-XaddExports:jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Expect.SUCCESS) + .writeAll(); + + tb.out.println("test that addExports can be provided with env variable using @file"); + Path atFile = src.resolve("at-file.txt"); + tb.writeFile(atFile, + "-XaddExports:jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED"); + + new JavacTask(tb, Mode.EXEC) + .envVar("_JAVAC_OPTIONS", "@" + atFile) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Expect.SUCCESS) + .writeAll(); + } + +} + diff --git a/langtools/test/tools/javac/modules/MissingJarInModulePathTest.java b/langtools/test/tools/javac/modules/MissingJarInModulePathTest.java new file mode 100644 index 00000000000..ec4e637383a --- /dev/null +++ b/langtools/test/tools/javac/modules/MissingJarInModulePathTest.java @@ -0,0 +1,31 @@ +/* + * 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 8154824 + * @summary Compiler should handle java.nio.file.FileSystemNotFoundException gracefully and not abort + * @compile/fail/ref=MissingJarInModulePathTest.out -XDrawDiagnostics -Xlint:path -Werror -modulepath missing.jar MissingJarInModulePathTest.java + */ + +class MissingJarInModulePathTest {} diff --git a/langtools/test/tools/javac/modules/MissingJarInModulePathTest.out b/langtools/test/tools/javac/modules/MissingJarInModulePathTest.out new file mode 100644 index 00000000000..7bcef9d70bf --- /dev/null +++ b/langtools/test/tools/javac/modules/MissingJarInModulePathTest.out @@ -0,0 +1,4 @@ +- compiler.warn.path.element.not.found: missing.jar +- compiler.err.warnings.and.werror +1 error +1 warning \ No newline at end of file diff --git a/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java b/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java index b252ddc995d..fd735ba2059 100644 --- a/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java +++ b/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938 6911854 8030049 8038080 + * @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938 6911854 8030049 8038080 8032230 * @summary Tests that getElementsAnnotatedWith works properly. * @author Joseph D. Darcy * @library /tools/javac/lib @@ -51,69 +51,183 @@ import java.util.Collections; import java.util.Set; import java.util.HashSet; import java.util.Arrays; +import java.util.Objects; import javax.annotation.processing.*; import javax.lang.model.element.*; import static javax.lang.model.util.ElementFilter.*; /** * This processor verifies that the information returned by - * getElementsAnnotatedWith is consistent with the expected results - * stored in an AnnotatedElementInfo annotation. + * getElementsAnnotatedWith and getElementsAnnotatedWithAny is + * consistent with the expected results stored in an + * AnnotatedElementInfo annotation. */ @AnnotatedElementInfo(annotationName="java.lang.SuppressWarnings", expectedSize=0, names={}) public class TestElementsAnnotatedWith extends JavacTestingAbstractProcessor { public boolean process(Set annotations, - RoundEnvironment roundEnvironment) { - TypeElement annotatedElementInfoElement = - elements.getTypeElement("AnnotatedElementInfo"); - Set resultsMeta = Collections.emptySet(); - Set resultsBase = Collections.emptySet(); + RoundEnvironment roundEnv) { + // First check sets of annotated elements using the round + // environment from the annotation processing tool framework. + checkSetOfAnnotatedElements(roundEnv); - if (!roundEnvironment.processingOver()) { - testNonAnnotations(roundEnvironment); + // Next check sets of annotated elements using a round + // environment which uses the default implementations of the + // getElementsAnnotatedWithAny methods from the interface. + checkSetOfAnnotatedElements(new TestingRoundEnvironment(roundEnv)); + return true; + } + + /** + * To allow testing of the executable code of the default methods + * for the two overloaded getElementsAnnotatedWithAny methods + * defined in the RoundEnvironment interface, this class delegates + * the non-default methods of RoundEnvironment to a given + * RoundEnvironment object and then explicitly calls the default + * methods of the interface instead of relying on the object's + * implementation of those methods. + */ + private class TestingRoundEnvironment implements RoundEnvironment { + private RoundEnvironment re; + + public TestingRoundEnvironment(RoundEnvironment re) { + this.re = re; + } + + @Override + public boolean errorRaised() { + return re.errorRaised(); + } + + @Override + public Set getElementsAnnotatedWith(Class a) { + return re.getElementsAnnotatedWith(a); + } + + @Override + public Set getElementsAnnotatedWithAny(Set> a) { + // Default method defined in the interface + return RoundEnvironment.super.getElementsAnnotatedWithAny(a); + } + + @Override + public Set getElementsAnnotatedWith(TypeElement a) { + return re.getElementsAnnotatedWith(a); + } + + @Override + public Set getElementsAnnotatedWithAny(TypeElement... a) { + // Default method defined in the interface + return RoundEnvironment.super.getElementsAnnotatedWithAny(a); + } + + @Override + public Set getRootElements() { + return re.getRootElements(); + } + + @Override + public boolean processingOver() { + return re.processingOver(); + } + + } + + /** + * The method checks the following conditions: + * + * 1) The sets of elements found are equal for the TypeElement and + * Class methods on logically equivalent + * arguments. + * + * 2) getElementsAnnotatedWithAny(X) is equal to + * getElementsAnnotatedWith(X') where X is a set/var-args array + * with one element and X' is the element. + * + * 3) Verify the result of getElementsAnnotatedWithAny({X, Y}) is equal to + * getElementsAnnotatedWith(X) UNION getElementsAnnotatedWith(Y). + */ + void checkSetOfAnnotatedElements(RoundEnvironment re) { + TypeElement annotatedElemInfoElem = elements.getTypeElement("AnnotatedElementInfo"); + + // For the "Any" methods, search for both the expected + // annotation and AnnotatedElementInfo and verify the return + // set is the union of searching for AnnotatedElementInfo and + // the other annotation + Set resultsMeta = Collections.emptySet(); + Set resultsMetaAny = Collections.emptySet(); + Set resultsMetaMulti = new HashSet<>(); + Set resultsMetaAnyMulti = Collections.emptySet(); + Set resultsBase = Collections.emptySet(); + Set resultsBaseAny = Collections.emptySet(); + Set resultsBaseAnyMulti = Collections.emptySet(); + + if (!re.processingOver()) { + testNonAnnotations(re); // Verify AnnotatedElementInfo is present on the first // specified type. - TypeElement firstType = typesIn(roundEnvironment.getRootElements()).iterator().next(); + TypeElement firstType = typesIn(re.getRootElements()).iterator().next(); - AnnotatedElementInfo annotatedElementInfo = firstType.getAnnotation(AnnotatedElementInfo.class); + AnnotatedElementInfo annotatedElemInfo = + firstType.getAnnotation(AnnotatedElementInfo.class); boolean failed = false; - if (annotatedElementInfo == null) - throw new IllegalArgumentException("Missing AnnotatedElementInfo annotation on " + - firstType); - else { - // Verify that the annotation information is as - // expected. + Objects.requireNonNull(annotatedElemInfo, + "Missing AnnotatedElementInfo annotation on " + firstType); - Set expectedNames = new HashSet(Arrays.asList(annotatedElementInfo.names())); + // Verify that the annotation information is as expected. + Set expectedNames = + new HashSet<>(Arrays.asList(annotatedElemInfo.names())); - resultsMeta = - roundEnvironment. - getElementsAnnotatedWith(elements.getTypeElement(annotatedElementInfo.annotationName())); + String annotationName = annotatedElemInfo.annotationName(); + TypeElement annotationTypeElem = elements.getTypeElement(annotationName); - if (!resultsMeta.isEmpty()) - System.err.println("Results: " + resultsMeta); + resultsMeta = re.getElementsAnnotatedWith(annotationTypeElem); + resultsMetaAny = re.getElementsAnnotatedWithAny(annotationTypeElem); + resultsMetaMulti.addAll(resultsMeta); + resultsMetaMulti.addAll(re.getElementsAnnotatedWith(annotatedElemInfoElem)); + resultsMetaAnyMulti = re.getElementsAnnotatedWithAny(annotationTypeElem, annotatedElemInfoElem); - if (resultsMeta.size() != annotatedElementInfo.expectedSize()) { - failed = true; - System.err.printf("Bad number of elements; expected %d, got %d%n", - annotatedElementInfo.expectedSize(), resultsMeta.size()); - } else { - for(Element element : resultsMeta) { - String simpleName = element.getSimpleName().toString(); - if (!expectedNames.contains(simpleName) ) { - failed = true; - System.err.println("Name ``" + simpleName + "'' not expected."); - } + if (!resultsMeta.isEmpty()) + System.err.println("Results: " + resultsMeta); + + if (!resultsMeta.equals(resultsMetaAny)) { + failed = true; + System.err.printf("Inconsistent Meta with vs withAny results"); + } + + if (resultsMeta.size() != annotatedElemInfo.expectedSize()) { + failed = true; + System.err.printf("Bad number of elements; expected %d, got %d%n", + annotatedElemInfo.expectedSize(), resultsMeta.size()); + } else { + for(Element element : resultsMeta) { + String simpleName = element.getSimpleName().toString(); + if (!expectedNames.contains(simpleName) ) { + failed = true; + System.err.println("Name ``" + simpleName + "'' not expected."); } } } - resultsBase = computeResultsBase(roundEnvironment, annotatedElementInfo.annotationName()); + resultsBase = computeResultsBase(re, annotationName); + resultsBaseAny = computeResultsBaseAny(re, annotationName); + try { + Set> tmp = new HashSet<>(); + tmp.add(AnnotatedElementInfo.class); + tmp.add(Class.forName(annotationName).asSubclass(Annotation.class)); + resultsBaseAnyMulti = re.getElementsAnnotatedWithAny(tmp); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + if (!resultsBase.equals(resultsBaseAny)) { + failed = true; + System.err.printf("Inconsistent Base with vs withAny results"); + } if (!resultsMeta.equals(resultsBase)) { failed = true; @@ -121,29 +235,53 @@ public class TestElementsAnnotatedWith extends JavacTestingAbstractProcessor { "\nbase: " + resultsBase); } + if (!resultsMetaAnyMulti.equals(resultsMetaMulti)) { + failed = true; + System.err.println("MetaMultAny and MetaMulti sets unequal;\n meta: " + resultsMeta + + "\nbase: " + resultsBase); + } + + if (!resultsBaseAnyMulti.equals(resultsMetaAnyMulti)) { + failed = true; + System.err.println("BaseMulti and MetaMulti sets unequal;\n meta: " + resultsMeta + + "\nbase: " + resultsBase); + } + if (failed) { - System.err.println("AnnotatedElementInfo: " + annotatedElementInfo); + System.err.println("AnnotatedElementInfo: " + annotatedElemInfo); throw new RuntimeException(); } } else { // If processing is over without an error, the specified - // elements should be empty so an empty set should be returned. - resultsMeta = roundEnvironment.getElementsAnnotatedWith(annotatedElementInfoElement); - resultsBase = roundEnvironment.getElementsAnnotatedWith(AnnotatedElementInfo.class); - if (!resultsMeta.isEmpty()) - throw new RuntimeException("Nonempty resultsMeta: " + resultsMeta); - if (!resultsBase.isEmpty()) - throw new RuntimeException("Nonempty resultsBase: " + resultsBase); - + // elements should be empty so an empty set should be + // returned. + throwOnNonEmpty(re.getElementsAnnotatedWith(annotatedElemInfoElem), "resultsMeta"); + throwOnNonEmpty(re.getElementsAnnotatedWithAny(annotatedElemInfoElem), "resultsMetaAny"); + throwOnNonEmpty(re.getElementsAnnotatedWith(AnnotatedElementInfo.class), "resultsBase"); + throwOnNonEmpty(re.getElementsAnnotatedWithAny(Set.of(AnnotatedElementInfo.class)), "resultsBaseAny"); } - return true; } - private Set computeResultsBase(RoundEnvironment roundEnvironment, String name) { + private void throwOnNonEmpty(Set results, String message) { + if (!results.isEmpty()) { + throw new RuntimeException("Nonempty " + message + "\t" + results); + } + } + + private Set computeResultsBase(RoundEnvironment roundEnv, String name) { try { - return roundEnvironment. + return roundEnv. getElementsAnnotatedWith(Class.forName(name).asSubclass(Annotation.class)); - } catch(ClassNotFoundException cnfe) { + } catch (ClassNotFoundException cnfe) { + throw new RuntimeException(cnfe); + } + } + + private Set computeResultsBaseAny(RoundEnvironment roundEnv, String name) { + try { + return roundEnv. + getElementsAnnotatedWithAny(Set.of(Class.forName(name).asSubclass(Annotation.class))); + } catch (ClassNotFoundException cnfe) { throw new RuntimeException(cnfe); } } @@ -152,18 +290,28 @@ public class TestElementsAnnotatedWith extends JavacTestingAbstractProcessor { * Verify non-annotation types result in * IllegalArgumentExceptions. */ - private void testNonAnnotations(RoundEnvironment roundEnvironment) { + private void testNonAnnotations(RoundEnvironment roundEnv) { + Class objectClass = (Class)Object.class; + Set elements; try { - Set elements = roundEnvironment.getElementsAnnotatedWith((Class)Object.class ); + elements = roundEnv.getElementsAnnotatedWith(objectClass); throw new RuntimeException("Illegal argument exception not thrown"); - } catch(IllegalArgumentException iae) {} + } catch (IllegalArgumentException iae) {} try { - Set elements = - roundEnvironment.getElementsAnnotatedWith(processingEnv. - getElementUtils(). - getTypeElement("java.lang.Object") ); + elements = roundEnv.getElementsAnnotatedWithAny(Set.of(objectClass)); throw new RuntimeException("Illegal argument exception not thrown"); - } catch(IllegalArgumentException iae) {} + } catch (IllegalArgumentException iae) {} + + TypeElement objectElement = processingEnv.getElementUtils().getTypeElement("java.lang.Object"); + try { + elements = roundEnv.getElementsAnnotatedWith(objectElement); + throw new RuntimeException("Illegal argument exception not thrown"); + } catch (IllegalArgumentException iae) {} + + try { + elements = roundEnv.getElementsAnnotatedWithAny(objectElement); + throw new RuntimeException("Illegal argument exception not thrown"); + } catch (IllegalArgumentException iae) {} } } diff --git a/langtools/test/tools/javac/processing/model/TestSourceVersion.java b/langtools/test/tools/javac/processing/model/TestSourceVersion.java index 1a06c242db3..396fe10b1b9 100644 --- a/langtools/test/tools/javac/processing/model/TestSourceVersion.java +++ b/langtools/test/tools/javac/processing/model/TestSourceVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * 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,13 +23,14 @@ /* * @test - * @bug 7025809 8028543 - * @summary Test latest and latestSupported + * @bug 7025809 8028543 6415644 + * @summary Test latest, latestSupported, underscore as keyword, etc. * @author Joseph D. Darcy * @modules java.compiler * jdk.compiler */ +import java.util.*; import javax.lang.model.SourceVersion; import static javax.lang.model.SourceVersion.*; @@ -38,10 +39,45 @@ import static javax.lang.model.SourceVersion.*; */ public class TestSourceVersion { public static void main(String... args) { + testLatestSupported(); + testVersionVaryingKeywords(); + } + + private static void testLatestSupported() { if (SourceVersion.latest() != RELEASE_9 || SourceVersion.latestSupported() != RELEASE_9) throw new RuntimeException("Unexpected release value(s) found:\n" + "latest:\t" + SourceVersion.latest() + "\n" + "latestSupported:\t" + SourceVersion.latestSupported()); } + + private static void testVersionVaryingKeywords() { + Map keyWordStart = + Map.of("strictfp", RELEASE_2, + "assert", RELEASE_4, + "enum", RELEASE_5, + "_", RELEASE_9); + + for (Map.Entry entry : keyWordStart.entrySet()) { + String key = entry.getKey(); + SourceVersion value = entry.getValue(); + + check(true, isKeyword(key), "keyword", latest()); + check(false, isName(key), "name", latest()); + + for(SourceVersion version : SourceVersion.values()) { + boolean isKeyword = version.compareTo(value) >= 0; + + check(isKeyword, isKeyword(key, version), "keyword", version); + check(!isKeyword, isName(key, version), "name", version); + } + } + } + + private static void check(boolean result, boolean expected, + String message, SourceVersion version) { + if (result != expected) { + throw new RuntimeException("Unexpected " + message + "-ness of _ on " + version); + } + } } diff --git a/langtools/test/tools/javac/unicode/Unmappable.java b/langtools/test/tools/javac/unicode/Unmappable.java index 7cd05017dac..9e4ad95eaaa 100644 --- a/langtools/test/tools/javac/unicode/Unmappable.java +++ b/langtools/test/tools/javac/unicode/Unmappable.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 4767128 5048557 5048773 + * @bug 4767128 5048557 5048773 8078559 * @summary diagnose encoding errors in Java source files * @author gafter * diff --git a/langtools/test/tools/javac/unicode/Unmappable.out b/langtools/test/tools/javac/unicode/Unmappable.out index e9766679407..71fff9ae219 100644 --- a/langtools/test/tools/javac/unicode/Unmappable.out +++ b/langtools/test/tools/javac/unicode/Unmappable.out @@ -1,2 +1,2 @@ -Unmappable.java:12:18: compiler.err.illegal.char.for.encoding: ascii +Unmappable.java:12:18: compiler.err.illegal.char.for.encoding: E4, ascii 1 error diff --git a/langtools/test/tools/javah/T6893943.java b/langtools/test/tools/javah/T6893943.java index 744122d430d..e3e4cbf7e68 100644 --- a/langtools/test/tools/javah/T6893943.java +++ b/langtools/test/tools/javah/T6893943.java @@ -32,8 +32,8 @@ import java.io.*; import java.util.*; public class T6893943 { - static final String[] NO_ARGS = { }; - static final String[] HELP = { "-help" }; + static final String[] NO_ARGS = { "-XDsuppress-tool-removal-message" }; + static final String[] SUPPRESS_WARNING_PLUS_HELP = { "-XDsuppress-tool-removal-message", "-help" }; static final String NEWLINE = System.getProperty("line.separator"); public static void main(String... args) throws Exception { @@ -42,9 +42,9 @@ public class T6893943 { void run() throws Exception { testSimpleAPI(NO_ARGS, 1); - testSimpleAPI(HELP, 0); + testSimpleAPI(SUPPRESS_WARNING_PLUS_HELP, 0); testCommand(NO_ARGS, 1); - testCommand(HELP, 0); + testCommand(SUPPRESS_WARNING_PLUS_HELP, 0); } void testSimpleAPI(String[] args, int expect_rc) throws Exception { @@ -81,11 +81,6 @@ public class T6893943 { if (out.isEmpty()) throw new Exception("No output from javah"); - if (!out.startsWith("Usage:")) { - System.err.println(out); - throw new Exception("Unexpected output from javah"); - } - if (actual_rc != expect_rc) throw new Exception(name + ": unexpected exit: " + actual_rc + ", expected: " + expect_rc); } diff --git a/langtools/test/tools/javah/VersionTest.java b/langtools/test/tools/javah/VersionTest.java index 47dee7b5673..3d5c8cb03e9 100644 --- a/langtools/test/tools/javah/VersionTest.java +++ b/langtools/test/tools/javah/VersionTest.java @@ -37,8 +37,8 @@ public class VersionTest { try { Locale.setDefault(Locale.ENGLISH); System.err.println(Locale.getDefault()); - test("-version", "\\S+ version \"\\S+\""); - test("-fullversion", "\\S+ full version \"\\S+\""); + test("-version -XDsuppress-tool-removal-message", "\\S+ version \"\\S+\""); + test("-fullversion -XDsuppress-tool-removal-message", "\\S+ full version \"\\S+\""); } finally { Locale.setDefault(prev); } @@ -47,7 +47,7 @@ public class VersionTest { static void test(String option, String regex) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - String[] args = { option }; + String[] args = option.split(" "); int rc = com.sun.tools.javah.Main.run(args, pw); pw.close(); if (rc != 0) diff --git a/langtools/test/tools/jdeps/APIDeps.java b/langtools/test/tools/jdeps/APIDeps.java index 0f2bf995ab7..66c2e651780 100644 --- a/langtools/test/tools/jdeps/APIDeps.java +++ b/langtools/test/tools/jdeps/APIDeps.java @@ -25,6 +25,7 @@ * @test * @bug 8015912 8029216 8048063 8050804 * @summary Test -apionly and -jdkinternals options + * @library lib * @modules java.base/sun.security.x509 * java.management * jdk.jdeps/com.sun.tools.classfile @@ -154,7 +155,8 @@ public class APIDeps { Map jdeps(String... args) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - System.err.println("jdeps " + Arrays.toString(args)); + System.err.println("jdeps " + Arrays.stream(args) + .collect(Collectors.joining(" "))); int rc = com.sun.tools.jdeps.Main.run(args, pw); pw.close(); String out = sw.toString(); diff --git a/langtools/test/tools/jdeps/Basic.java b/langtools/test/tools/jdeps/Basic.java index fac5493be9d..9834fef6489 100644 --- a/langtools/test/tools/jdeps/Basic.java +++ b/langtools/test/tools/jdeps/Basic.java @@ -39,6 +39,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.regex.*; +import java.util.stream.Collectors; + import static java.nio.file.StandardCopyOption.*; public class Basic { @@ -157,7 +159,7 @@ public class Basic { Map jdeps(String... args) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - System.err.println("jdeps " + Arrays.toString(args)); + System.err.println("jdeps " + Arrays.stream(args).collect(Collectors.joining(" "))); int rc = com.sun.tools.jdeps.Main.run(args, pw); pw.close(); String out = sw.toString(); diff --git a/langtools/test/tools/jdeps/DotFileTest.java b/langtools/test/tools/jdeps/DotFileTest.java index d560ce69e38..0dd4296776c 100644 --- a/langtools/test/tools/jdeps/DotFileTest.java +++ b/langtools/test/tools/jdeps/DotFileTest.java @@ -41,6 +41,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.regex.*; +import java.util.stream.Collectors; public class DotFileTest { public static void main(String... args) throws Exception { @@ -182,7 +183,7 @@ public class DotFileTest { // invoke jdeps StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - System.err.println("jdeps " + args); + System.err.println("jdeps " + args.stream().collect(Collectors.joining(" "))); int rc = com.sun.tools.jdeps.Main.run(args.toArray(new String[0]), pw); pw.close(); String out = sw.toString(); diff --git a/langtools/test/tools/jdeps/jdkinternals/RemovedJDKInternals.java b/langtools/test/tools/jdeps/jdkinternals/RemovedJDKInternals.java new file mode 100644 index 00000000000..9bfda2a5fa6 --- /dev/null +++ b/langtools/test/tools/jdeps/jdkinternals/RemovedJDKInternals.java @@ -0,0 +1,148 @@ +/* + * 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 8153042 + * @summary Tests JDK internal APIs that have been removed. + * @library ../lib + * @build CompilerUtils JdepsUtil ModuleMetaData + * @modules jdk.jdeps/com.sun.tools.jdeps + * @run testng RemovedJDKInternals + */ + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; + +import com.sun.tools.jdeps.DepsAnalyzer; +import com.sun.tools.jdeps.Graph; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +public class RemovedJDKInternals { + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path CLASSES_DIR = Paths.get("classes"); + private static final Path PATCHES_DIR = Paths.get("patches"); + + private static final String JDK_UNSUPPORTED = "jdk.unsupported"; + /** + * Compiles classes used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + CompilerUtils.cleanDir(PATCHES_DIR); + CompilerUtils.cleanDir(CLASSES_DIR); + + // compile sun.misc types + Path sunMiscSrc = Paths.get(TEST_SRC, "patches", JDK_UNSUPPORTED); + Path patchDir = PATCHES_DIR.resolve(JDK_UNSUPPORTED); + assertTrue(CompilerUtils.compile(sunMiscSrc, patchDir, + "-Xmodule:" + JDK_UNSUPPORTED)); + + // compile com.sun.image.codec.jpeg types + Path codecSrc = Paths.get(TEST_SRC, "patches", "java.desktop"); + Path codecDest = PATCHES_DIR; + assertTrue(CompilerUtils.compile(codecSrc, codecDest)); + + // patch jdk.unsupported and set -cp to codec types + assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src"), + CLASSES_DIR, + "-Xpatch:jdk.unsupported=" + patchDir, + "-cp", codecDest.toString())); + } + + @DataProvider(name = "deps") + public Object[][] deps() { + return new Object[][] { + { "classes", new ModuleMetaData("classes", false) + .reference("p.Main", "java.lang.Class", "java.base") + .reference("p.Main", "java.lang.Object", "java.base") + .reference("p.Main", "java.util.Iterator", "java.base") + .reference("p.S", "java.lang.Object", "java.base") + .jdkInternal("p.Main", "sun.reflect.Reflection", "jdk.unsupported") + .removedJdkInternal("p.Main", "com.sun.image.codec.jpeg.JPEGCodec") + .removedJdkInternal("p.Main", "sun.misc.Service") + .removedJdkInternal("p.Main", "sun.misc.SoftCache") + }, + }; + } + + @Test(dataProvider = "deps") + public void runTest(String name, ModuleMetaData data) throws Exception { + String cmd = String.format("jdeps -verbose:class %s%n", CLASSES_DIR); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.verbose("-verbose:class") + .addRoot(CLASSES_DIR); + + DepsAnalyzer analyzer = jdeps.getDepsAnalyzer(); + assertTrue(analyzer.run()); + jdeps.dumpOutput(System.err); + + Graph g = analyzer.dependenceGraph(); + // there are two node with p.Main as origin + // one for exported API and one for removed JDK internal + g.nodes().stream() + .filter(u -> u.source.equals(data.moduleName)) + .forEach(u -> g.adjacentNodes(u).stream() + .forEach(v -> data.checkDependence(u.name, v.name, v.source, v.info))); + } + } + + private static final Map REPLACEMENTS = Map.of( + "com.sun.image.codec.jpeg.JPEGCodec", "Use javax.imageio @since 1.4", + "sun.misc.Service", "Use java.util.ServiceLoader @since 1.6", + "sun.misc.SoftCache", "Removed. See http://openjdk.java.net/jeps/260", + "sun.reflect.Reflection", "Use java.lang.StackWalker @since 9" + ); + + @Test + public void checkReplacement() { + String[] output = JdepsUtil.jdeps("-jdkinternals", CLASSES_DIR.toString()); + int i = 0; + while (!output[i].contains("Suggested Replacement")) { + i++; + } + + // must match the number of JDK internal APIs + int count = output.length-i-2; + assertEquals(count, REPLACEMENTS.size()); + + for (int j=i+2; j < output.length; j++) { + String line = output[j]; + int pos = line.indexOf("Use "); + if (pos < 0) + pos = line.indexOf("Removed. "); + + assertTrue(pos > 0); + String name = line.substring(0, pos).trim(); + String repl = line.substring(pos, line.length()).trim(); + assertEquals(REPLACEMENTS.get(name), repl); + } + } +} diff --git a/langtools/test/tools/jdeps/jdkinternals/patches/java.desktop/com/sun/image/codec/jpeg/JPEGCodec.java b/langtools/test/tools/jdeps/jdkinternals/patches/java.desktop/com/sun/image/codec/jpeg/JPEGCodec.java new file mode 100644 index 00000000000..49c9d709042 --- /dev/null +++ b/langtools/test/tools/jdeps/jdkinternals/patches/java.desktop/com/sun/image/codec/jpeg/JPEGCodec.java @@ -0,0 +1,30 @@ +/* + * 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.sun.image.codec.jpeg; + +/* + * JDK removed internal API + */ +public class JPEGCodec { +} diff --git a/langtools/test/tools/jdeps/jdkinternals/patches/jdk.unsupported/sun/misc/Service.java b/langtools/test/tools/jdeps/jdkinternals/patches/jdk.unsupported/sun/misc/Service.java new file mode 100644 index 00000000000..64aff170f0f --- /dev/null +++ b/langtools/test/tools/jdeps/jdkinternals/patches/jdk.unsupported/sun/misc/Service.java @@ -0,0 +1,35 @@ +/* + * 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 sun.misc; + +import java.util.Iterator; + +/* + * JDK removed internal API + */ +public final class Service { + public static Iterator providers(Class service) { + return null; + } +} diff --git a/langtools/test/tools/jdeps/jdkinternals/patches/jdk.unsupported/sun/misc/SoftCache.java b/langtools/test/tools/jdeps/jdkinternals/patches/jdk.unsupported/sun/misc/SoftCache.java new file mode 100644 index 00000000000..fca5c816ac3 --- /dev/null +++ b/langtools/test/tools/jdeps/jdkinternals/patches/jdk.unsupported/sun/misc/SoftCache.java @@ -0,0 +1,30 @@ +/* + * 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 sun.misc; + +/* + * JDK removed internal API + */ +public class SoftCache { +} diff --git a/langtools/test/tools/jdeps/jdkinternals/src/p/Main.java b/langtools/test/tools/jdeps/jdkinternals/src/p/Main.java new file mode 100644 index 00000000000..aaa30af8b39 --- /dev/null +++ b/langtools/test/tools/jdeps/jdkinternals/src/p/Main.java @@ -0,0 +1,45 @@ +/* + * 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 com.sun.image.codec.jpeg.JPEGCodec; +import sun.misc.Service; +import sun.misc.SoftCache; +import sun.reflect.Reflection; + +public class Main { + public static void main() { + // in jdk.unsupported + Class caller = Reflection.getCallerClass(2); + + // removed + JPEGCodec r = new JPEGCodec(); + + // removed + SoftCache s = new SoftCache(); + + // removed + Service.providers(S.class); + } +} diff --git a/langtools/test/tools/jdeps/jdkinternals/src/p/S.java b/langtools/test/tools/jdeps/jdkinternals/src/p/S.java new file mode 100644 index 00000000000..7f4dd00ec64 --- /dev/null +++ b/langtools/test/tools/jdeps/jdkinternals/src/p/S.java @@ -0,0 +1,27 @@ +/* + * 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; + +public interface S { +} diff --git a/langtools/test/tools/jdeps/CompilerUtils.java b/langtools/test/tools/jdeps/lib/CompilerUtils.java similarity index 100% rename from langtools/test/tools/jdeps/CompilerUtils.java rename to langtools/test/tools/jdeps/lib/CompilerUtils.java diff --git a/langtools/test/tools/jdeps/lib/JdepsUtil.java b/langtools/test/tools/jdeps/lib/JdepsUtil.java new file mode 100644 index 00000000000..3ec1ad75310 --- /dev/null +++ b/langtools/test/tools/jdeps/lib/JdepsUtil.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.jdeps.Analyzer; +import com.sun.tools.jdeps.DepsAnalyzer; +import com.sun.tools.jdeps.InverseDepsAnalyzer; +import com.sun.tools.jdeps.JdepsConfiguration; +import com.sun.tools.jdeps.JdepsFilter; +import com.sun.tools.jdeps.JdepsWriter; +import com.sun.tools.jdeps.ModuleAnalyzer; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.UncheckedIOException; +import java.lang.module.ModuleDescriptor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Utilities to run jdeps command + */ +public final class JdepsUtil { + /* + * Runs jdeps with the given arguments + */ + public static String[] jdeps(String... args) { + String lineSep = System.getProperty("line.separator"); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + System.err.println("jdeps " + Arrays.stream(args).collect(Collectors.joining(" "))); + int rc = com.sun.tools.jdeps.Main.run(args, pw); + pw.close(); + String out = sw.toString(); + if (!out.isEmpty()) + System.err.println(out); + if (rc != 0) + throw new Error("jdeps failed: rc=" + rc); + return out.split(lineSep); + } + + public static Command newCommand(String cmd) { + return new Command(cmd); + } + + public static class Command implements Closeable { + + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + final JdepsFilter.Builder filter = new JdepsFilter.Builder().filter(true, true); + final JdepsConfiguration.Builder builder = new JdepsConfiguration.Builder(); + final Set requires = new HashSet<>(); + + JdepsConfiguration configuration; + Analyzer.Type verbose = Analyzer.Type.PACKAGE; + boolean apiOnly = false; + + public Command(String cmd) { + System.err.println("============ "); + System.err.println(cmd); + } + + public Command verbose(String verbose) { + switch (verbose) { + case "-verbose": + this.verbose = Analyzer.Type.VERBOSE; + filter.filter(false, false); + break; + case "-verbose:package": + this.verbose = Analyzer.Type.PACKAGE; + break; + case "-verbose:class": + this.verbose = Analyzer.Type.CLASS; + break; + case "-summary": + this.verbose = Analyzer.Type.SUMMARY; + break; + default: + throw new IllegalArgumentException(verbose); + } + return this; + } + + public Command filter(String value) { + switch (value) { + case "-filter:package": + filter.filter(true, false); + break; + case "-filter:archive": + case "-filter:module": + filter.filter(false, true); + break; + default: + throw new IllegalArgumentException(value); + } + return this; + } + + public Command addClassPath(String classpath) { + builder.addClassPath(classpath); + return this; + } + + public Command addRoot(Path path) { + builder.addRoot(path); + return this; + } + + public Command appModulePath(String modulePath) { + builder.appModulePath(modulePath); + return this; + } + + public Command addmods(Set mods) { + builder.addmods(mods); + return this; + } + + public Command requires(Set mods) { + requires.addAll(mods); + return this; + } + + public Command matchPackages(Set pkgs) { + filter.packages(pkgs); + return this; + } + + public Command regex(String regex) { + filter.regex(Pattern.compile(regex)); + return this; + } + + public Command include(String regex) { + filter.includePattern(Pattern.compile(regex)); + return this; + } + + public Command includeSystemMoudles(String regex) { + filter.includeSystemModules(Pattern.compile(regex)); + return this; + } + + public Command apiOnly() { + this.apiOnly = true; + return this; + } + + public JdepsConfiguration configuration() throws IOException { + if (configuration == null) { + this.configuration = builder.build(); + requires.forEach(name -> { + ModuleDescriptor md = configuration.findModuleDescriptor(name).get(); + filter.requires(name, md.packages()); + }); + } + return configuration; + } + + private JdepsWriter writer() { + return JdepsWriter.newSimpleWriter(pw, verbose); + } + + public DepsAnalyzer getDepsAnalyzer() throws IOException { + return new DepsAnalyzer(configuration(), filter.build(), writer(), + verbose, apiOnly); + } + + public ModuleAnalyzer getModuleAnalyzer(Set mods) throws IOException { + // if -check is set, add to the root set and all modules are observable + addmods(mods); + builder.allModules(); + return new ModuleAnalyzer(configuration(), pw, mods); + } + + public InverseDepsAnalyzer getInverseDepsAnalyzer() throws IOException { + return new InverseDepsAnalyzer(configuration(), filter.build(), writer(), + verbose, false); + } + + public void dumpOutput(PrintStream out) { + out.println(sw.toString()); + } + + @Override + public void close() throws IOException { + configuration.close(); + } + } + + /** + * Create a jar file using the list of files provided. + */ + public static void createJar(Path jarfile, Path root, Stream files) + throws IOException { + Path dir = jarfile.getParent(); + if (dir != null && Files.notExists(dir)) { + Files.createDirectories(dir); + } + try (JarOutputStream target = new JarOutputStream( + Files.newOutputStream(jarfile))) { + files.forEach(file -> add(root.relativize(file), file, target)); + } + } + + private static void add(Path path, Path source, JarOutputStream target) { + try { + String name = path.toString().replace(File.separatorChar, '/'); + JarEntry entry = new JarEntry(name); + entry.setTime(source.toFile().lastModified()); + target.putNextEntry(entry); + Files.copy(source, target); + target.closeEntry(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/langtools/test/tools/jdeps/lib/ModuleMetaData.java b/langtools/test/tools/jdeps/lib/ModuleMetaData.java new file mode 100644 index 00000000000..f37c3a729ee --- /dev/null +++ b/langtools/test/tools/jdeps/lib/ModuleMetaData.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +import com.sun.tools.jdeps.DepsAnalyzer; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import static com.sun.tools.jdeps.DepsAnalyzer.Info.*; +import static java.lang.module.ModuleDescriptor.Requires.Modifier.*; +import static java.lang.module.ModuleDescriptor.*; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + + +public class ModuleMetaData { + public static final String JAVA_BASE = "java.base"; + + static final String INTERNAL = "(internal)"; + static final String QUALIFIED = "(qualified)"; + static final String JDK_INTERNAL = "JDK internal API"; + static final String REMOVED_JDK_INTERNAL = "JDK removed internal API"; + + final String moduleName; + final boolean isNamed; + final Map requires = new LinkedHashMap<>(); + final Map references = new LinkedHashMap<>(); + final Map> exports = new LinkedHashMap<>(); + + ModuleMetaData(String name) { + this(name, true); + } + + ModuleMetaData(String name, boolean isNamed) { + this.moduleName = name; + this.isNamed = isNamed; + requires(JAVA_BASE); // implicit requires + } + + String name() { + return moduleName; + } + + ModuleMetaData requires(String name) { + requires.put(name, new ModuleRequires(name)); + return this; + } + + ModuleMetaData requiresPublic(String name) { + requires.put(name, new ModuleRequires(name, PUBLIC)); + return this; + } + + // for unnamed module + ModuleMetaData depends(String name) { + requires.put(name, new ModuleRequires(name)); + return this; + } + + ModuleMetaData reference(String origin, String target, String module) { + return dependence(origin, target, module, ""); + } + + ModuleMetaData internal(String origin, String target, String module) { + return dependence(origin, target, module, INTERNAL); + } + + ModuleMetaData qualified(String origin, String target, String module) { + return dependence(origin, target, module, QUALIFIED); + } + + ModuleMetaData jdkInternal(String origin, String target, String module) { + return dependence(origin, target, module, JDK_INTERNAL); + } + ModuleMetaData removedJdkInternal(String origin, String target) { + return dependence(origin, target, REMOVED_JDK_INTERNAL, REMOVED_JDK_INTERNAL); + } + + ModuleMetaData exports(String pn, Set targets) { + exports.put(pn, targets); + return this; + } + + private ModuleMetaData dependence(String origin, String target, String module, String access) { + references.put(key(origin, target), new Dependence(origin, target, module, access)); + return this; + } + + String key(String origin, String target) { + return origin + ":" + target; + } + + void checkRequires(String name, Set adjacentNodes) { + // System.err.format("%s: Expected %s Found %s %n", name, requires, adjacentNodes); + adjacentNodes.stream() + .forEach(v -> checkRequires(v.name)); + assertEquals(adjacentNodes.size(), requires.size()); + } + + void checkRequires(String name) { + ModuleRequires req = requires.get(name); + if (req == null) + System.err.println(moduleName + ": unexpected requires " + name); + assertTrue(requires.containsKey(name)); + } + + void checkRequires(Requires require) { + String name = require.name(); + if (name.equals(JAVA_BASE)) + return; + + ModuleRequires req = requires.get(name); + if (req == null) + System.err.format("%s: unexpected dependence %s%n", moduleName, name); + + assertTrue(requires.containsKey(name)); + + assertEquals(require.modifiers(), req.modifiers()); + } + + void checkDependences(String name, Set adjacentNodes) { + // System.err.format("%s: Expected %s Found %s %n", name, references, adjacentNodes); + + adjacentNodes.stream() + .forEach(v -> checkDependence(name, v.name, v.source, v.info)); + assertEquals(adjacentNodes.size(), references.size()); + } + + void checkDependence(String origin, String target, String module, DepsAnalyzer.Info info) { + String key = key(origin, target); + Dependence dep = references.get(key); + String access = ""; + if (info == QUALIFIED_EXPORTED_API) + access = QUALIFIED; + else if (info == JDK_INTERNAL_API) + access = JDK_INTERNAL; + else if (info == JDK_REMOVED_INTERNAL_API) + access = REMOVED_JDK_INTERNAL; + else if (info == INTERNAL_API) + access = INTERNAL; + + assertTrue(references.containsKey(key)); + + assertEquals(dep.access, access); + assertEquals(dep.module, module); + } + + + public static class ModuleRequires { + final String name; + final Requires.Modifier mod; + + ModuleRequires(String name) { + this.name = name; + this.mod = null; + } + + ModuleRequires(String name, Requires.Modifier mod) { + this.name = name; + this.mod = mod; + } + + Set modifiers() { + return mod != null ? Set.of(mod) : Collections.emptySet(); + } + + @Override + public String toString() { + return name; + } + } + + public static class Dependence { + final String origin; + final String target; + final String module; + final String access; + + Dependence(String origin, String target, String module, String access) { + this.origin = origin; + this.target = target; + this.module = module; + this.access = access; + } + + @Override + public String toString() { + return String.format("%s -> %s (%s) %s", origin, target, module, access); + } + } +} diff --git a/langtools/test/tools/jdeps/m/Foo.java b/langtools/test/tools/jdeps/m/Foo.java index 67b7578ee29..991c847be7f 100644 --- a/langtools/test/tools/jdeps/m/Foo.java +++ b/langtools/test/tools/jdeps/m/Foo.java @@ -30,4 +30,3 @@ public class Foo extends Bar implements c.I { setF(new f.F()); } } - diff --git a/langtools/test/tools/jdeps/modules/CheckModuleTest.java b/langtools/test/tools/jdeps/modules/CheckModuleTest.java new file mode 100644 index 00000000000..79fe8172d6e --- /dev/null +++ b/langtools/test/tools/jdeps/modules/CheckModuleTest.java @@ -0,0 +1,163 @@ +/* + * 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 + * @summary Tests split packages + * @library ../lib + * @build CompilerUtils JdepsUtil + * @modules jdk.jdeps/com.sun.tools.jdeps + * @run testng CheckModuleTest + */ + +import java.lang.module.ModuleDescriptor; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; +import java.util.Set; + +import com.sun.tools.jdeps.ModuleAnalyzer; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertEquals; + + +public class CheckModuleTest { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final String TEST_CLASSES = System.getProperty("test.classes"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // m4 and m5 are analyzed. Others are compiled to make sure they are present + // on the module path for analysis + private static final Set modules = Set.of("unsafe", "m4", "m5", "m6", "m7", "m8"); + + private static final String JAVA_BASE = "java.base"; + + /** + * Compiles classes used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + CompilerUtils.cleanDir(MODS_DIR); + modules.forEach(mn -> + assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn))); + } + + @DataProvider(name = "javaBase") + public Object[][] base() { + return new Object[][] { + { JAVA_BASE, new ModuleMetaData(JAVA_BASE) + }, + }; + }; + + @Test(dataProvider = "javaBase") + public void testJavaBase(String name, ModuleMetaData data) throws Exception { + String cmd = String.format("jdeps -check %s -mp %s%n", name, MODS_DIR); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.appModulePath(MODS_DIR.toString()); + + ModuleAnalyzer analyzer = jdeps.getModuleAnalyzer(Set.of(name)); + assertTrue(analyzer.run()); + jdeps.dumpOutput(System.err); + + ModuleDescriptor[] descriptors = analyzer.descriptors(name); + for (int i = 0; i < 3; i++) { + descriptors[i].requires().stream() + .forEach(req -> data.checkRequires(req)); + } + } + } + + @DataProvider(name = "modules") + public Object[][] unnamed() { + return new Object[][]{ + { "m4", new ModuleMetaData[] { + // original + new ModuleMetaData("m4") + .requiresPublic("java.compiler") + .requires("java.logging") + // unnused exports + .exports("p4.internal", Set.of("m6", "m7")), + // suggested version + new ModuleMetaData("m4") + .requires("java.compiler"), + // reduced version + new ModuleMetaData("m4") + .requires("java.compiler") + } + }, + { "m5", new ModuleMetaData[] { + // original + new ModuleMetaData("m5") + .requiresPublic("java.compiler") + .requiresPublic("java.logging") + .requires("java.sql") + .requiresPublic("m4"), + // suggested version + new ModuleMetaData("m5") + .requiresPublic("java.compiler") + .requires("java.logging") + .requiresPublic("java.sql") + .requiresPublic("m4"), + // reduced version + new ModuleMetaData("m5") + .requiresPublic("java.compiler") + .requiresPublic("java.sql") + .requiresPublic("m4"), + } + }, + }; + } + + @Test(dataProvider = "modules") + public void modularTest(String name, ModuleMetaData[] data) throws Exception { + String cmd = String.format("jdeps -check %s -mp %s%n", name, MODS_DIR); + + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.appModulePath(MODS_DIR.toString()); + + ModuleAnalyzer analyzer = jdeps.getModuleAnalyzer(Set.of(name)); + assertTrue(analyzer.run()); + jdeps.dumpOutput(System.err); + + // compare the module descriptors and the suggested versions + ModuleDescriptor[] descriptors = analyzer.descriptors(name); + for (int i = 0; i < 3; i++) { + ModuleMetaData metaData = data[i]; + descriptors[i].requires().stream() + .forEach(req -> metaData.checkRequires(req)); + } + + Map> unused = analyzer.unusedQualifiedExports(name); + // verify unuused qualified exports + assertEquals(unused, data[0].exports); + } + } + +} diff --git a/langtools/test/tools/jdeps/modules/GenModuleInfo.java b/langtools/test/tools/jdeps/modules/GenModuleInfo.java index fcdcabb502d..dc79bec8d27 100644 --- a/langtools/test/tools/jdeps/modules/GenModuleInfo.java +++ b/langtools/test/tools/jdeps/modules/GenModuleInfo.java @@ -24,8 +24,8 @@ /* * @test * @summary Tests jdeps -genmoduleinfo option - * @library .. - * @build CompilerUtils + * @library ../lib + * @build CompilerUtils JdepsUtil * @modules jdk.jdeps/com.sun.tools.jdeps * @run testng GenModuleInfo */ @@ -39,16 +39,12 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.testng.annotations.DataProvider; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; - import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -86,12 +82,13 @@ public class GenModuleInfo { for (String mn : modules) { Path root = MODS_DIR.resolve(mn); - createJar(LIBS_DIR.resolve(mn + ".jar"), root, - Files.walk(root, Integer.MAX_VALUE) - .filter(f -> { - String fn = f.getFileName().toString(); - return fn.endsWith(".class") && !fn.equals("module-info.class"); - })); + try (Stream stream = Files.walk(root, Integer.MAX_VALUE)) { + Stream entries = stream.filter(f -> { + String fn = f.getFileName().toString(); + return fn.endsWith(".class") && !fn.equals("module-info.class"); + }); + JdepsUtil.createJar(LIBS_DIR.resolve(mn + ".jar"), root, entries); + } } } @@ -100,7 +97,7 @@ public class GenModuleInfo { Stream files = Arrays.stream(modules) .map(mn -> LIBS_DIR.resolve(mn + ".jar")) .map(Path::toString); - jdeps(Stream.concat(Stream.of("-cp"), files).toArray(String[]::new)); + JdepsUtil.jdeps(Stream.concat(Stream.of("-cp"), files).toArray(String[]::new)); } @Test @@ -109,9 +106,8 @@ public class GenModuleInfo { .map(mn -> LIBS_DIR.resolve(mn + ".jar")) .map(Path::toString); - jdeps(Stream.concat(Stream.of("-genmoduleinfo", DEST_DIR.toString()), - files) - .toArray(String[]::new)); + JdepsUtil.jdeps(Stream.concat(Stream.of("-genmoduleinfo", DEST_DIR.toString()), + files).toArray(String[]::new)); // check file exists Arrays.stream(modules) @@ -119,19 +115,20 @@ public class GenModuleInfo { .forEach(f -> assertTrue(Files.exists(f))); // copy classes except the original module-info.class - Files.walk(MODS_DIR, Integer.MAX_VALUE) - .filter(path -> !path.getFileName().toString().equals(MODULE_INFO) && - path.getFileName().toString().endsWith(".class")) - .map(path -> MODS_DIR.relativize(path)) - .forEach(path -> { - try { - Path newFile = NEW_MODS_DIR.resolve(path); - Files.createDirectories(newFile.getParent()); - Files.copy(MODS_DIR.resolve(path), newFile); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }); + try (Stream stream = Files.walk(MODS_DIR, Integer.MAX_VALUE)) { + stream.filter(path -> !path.getFileName().toString().equals(MODULE_INFO) && + path.getFileName().toString().endsWith(".class")) + .map(path -> MODS_DIR.relativize(path)) + .forEach(path -> { + try { + Path newFile = NEW_MODS_DIR.resolve(path); + Files.createDirectories(newFile.getParent()); + Files.copy(MODS_DIR.resolve(path), newFile); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } // compile new module-info.java assertTrue(CompilerUtils.compileModule(DEST_DIR, NEW_MODS_DIR, UNSUPPORTED, @@ -148,7 +145,7 @@ public class GenModuleInfo { try (InputStream in1 = Files.newInputStream(p1); InputStream in2 = Files.newInputStream(p2)) { verify(ModuleDescriptor.read(in1), - ModuleDescriptor.read(in2, () -> packages(MODS_DIR.resolve(mn)))); + ModuleDescriptor.read(in2, () -> packages(MODS_DIR.resolve(mn)))); } } } @@ -164,14 +161,13 @@ public class GenModuleInfo { } private Set packages(Path dir) { - try { - return Files.find(dir, Integer.MAX_VALUE, + try (Stream stream = Files.find(dir, Integer.MAX_VALUE, ((path, attrs) -> attrs.isRegularFile() && - path.toString().endsWith(".class"))) - .map(path -> toPackageName(dir.relativize(path))) - .filter(pkg -> pkg.length() > 0) // module-info - .distinct() - .collect(Collectors.toSet()); + path.toString().endsWith(".class")))) { + return stream.map(path -> toPackageName(dir.relativize(path))) + .filter(pkg -> pkg.length() > 0) // module-info + .distinct() + .collect(Collectors.toSet()); } catch (IOException x) { throw new UncheckedIOException(x); } @@ -188,46 +184,4 @@ public class GenModuleInfo { } } - /* - * Runs jdeps with the given arguments - */ - public static String[] jdeps(String... args) { - String lineSep = System.getProperty("line.separator"); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - System.err.println("jdeps " + Arrays.toString(args)); - int rc = com.sun.tools.jdeps.Main.run(args, pw); - pw.close(); - String out = sw.toString(); - if (!out.isEmpty()) - System.err.println(out); - if (rc != 0) - throw new Error("jdeps failed: rc=" + rc); - return out.split(lineSep); - } - - /** - * Create a jar file using the list of files provided. - */ - public static void createJar(Path jarfile, Path root, Stream files) - throws IOException { - try (JarOutputStream target = new JarOutputStream( - Files.newOutputStream(jarfile))) { - files.forEach(file -> add(root.relativize(file), file, target)); - } - } - - private static void add(Path path, Path source, JarOutputStream target) { - try { - String name = path.toString().replace(File.separatorChar, '/'); - JarEntry entry = new JarEntry(name); - entry.setTime(source.toFile().lastModified()); - target.putNextEntry(entry); - Files.copy(source, target); - target.closeEntry(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - } diff --git a/langtools/test/tools/jdeps/modules/InverseDeps.java b/langtools/test/tools/jdeps/modules/InverseDeps.java new file mode 100644 index 00000000000..df0b2ca668a --- /dev/null +++ b/langtools/test/tools/jdeps/modules/InverseDeps.java @@ -0,0 +1,299 @@ +/* + * 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 + * @summary Tests split packages + * @library ../lib + * @build CompilerUtils JdepsUtil + * @modules jdk.jdeps/com.sun.tools.jdeps + * @run testng InverseDeps + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.sun.tools.jdeps.Archive; +import com.sun.tools.jdeps.InverseDepsAnalyzer; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertEquals; + + +public class InverseDeps { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final String TEST_CLASSES = System.getProperty("test.classes"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + private static final Path LIBS_DIR = Paths.get("libs"); + + private static final Set modules = new LinkedHashSet( + List.of("unsafe", "m4", "m5", "m6", "m7") + ); + + /** + * Compiles classes used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + CompilerUtils.cleanDir(MODS_DIR); + + for (String mn : modules) { + // compile a module + assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)); + + // create JAR files with no module-info.class + Path root = MODS_DIR.resolve(mn); + + try (Stream stream = Files.walk(root, Integer.MAX_VALUE)) { + Stream entries = stream.filter(f -> { + String fn = f.getFileName().toString(); + return fn.endsWith(".class") && !fn.equals("module-info.class"); + }); + JdepsUtil.createJar(LIBS_DIR.resolve(mn + ".jar"), root, entries); + } + } + } + + @DataProvider(name = "testrequires") + public Object[][] expected1() { + return new Object[][] { + // -requires and result + { "java.sql", new String[][] { + new String[] { "java.sql", "m5" }, + } + }, + { "java.compiler", new String[][] { + new String[] { "java.compiler", "m5" }, + new String[] { "java.compiler", "m4", "m5" }, + } + }, + { "java.logging", new String[][]{ + new String[] {"java.logging", "m5"}, + new String[] {"java.logging", "m4", "m5"}, + new String[] {"java.logging", "java.sql", "m5"}, + } + }, + { "jdk.unsupported", new String[][] { + new String[] {"jdk.unsupported", "unsafe", "m6", "m7"}, + new String[] {"jdk.unsupported", "unsafe", "m7"} + } + }, + }; + } + + @Test(dataProvider = "testrequires") + public void testrequires(String name, String[][] expected) throws Exception { + String cmd1 = String.format("jdeps -inverse -modulepath %s -requires %s -addmods %s%n", + MODS_DIR, name, modules.stream().collect(Collectors.joining(","))); + + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd1)) { + jdeps.appModulePath(MODS_DIR.toString()) + .addmods(modules) + .requires(Set.of(name)); + + runJdeps(jdeps, expected); + } + + String cmd2 = String.format("jdeps -inverse -modulepath %s -requires %s" + + " -addmods ALL-MODULE-PATH%n", LIBS_DIR, name); + + // automatic module + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd2)) { + jdeps.appModulePath(MODS_DIR.toString()) + .addmods(Set.of("ALL-MODULE-PATH")) + .requires(Set.of(name)); + + runJdeps(jdeps, expected); + } + } + + @DataProvider(name = "testpackage") + public Object[][] expected2() { + return new Object[][] { + // -package and result + { "p4", new String[][] { + new String[] { "m4", "m5"}, + } + }, + { "javax.tools", new String[][] { + new String[] {"java.compiler", "m5"}, + new String[] {"java.compiler", "m4", "m5"}, + } + }, + { "sun.misc", new String[][] { + new String[] {"jdk.unsupported", "unsafe", "m6", "m7"}, + new String[] {"jdk.unsupported", "unsafe", "m7"} + } + } + }; + } + + @Test(dataProvider = "testpackage") + public void testpackage(String name, String[][] expected) throws Exception { + String cmd = String.format("jdeps -inverse -modulepath %s -package %s -addmods %s%n", + MODS_DIR, name, modules.stream().collect(Collectors.joining(","))); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.appModulePath(MODS_DIR.toString()) + .addmods(modules) + .matchPackages(Set.of(name)); + + runJdeps(jdeps, expected); + } + } + + @DataProvider(name = "testregex") + public Object[][] expected3() { + return new Object[][] { + // -regex and result + { "org.safe.Lib", new String[][] { + new String[] { "unsafe", "m7"}, + new String[] { "unsafe", "m6", "m7"}, + } + }, + { "java.util.logging.*|org.safe.Lib", new String[][] { + new String[] { "unsafe", "m7"}, + new String[] { "unsafe", "m6", "m7"}, + new String[] { "java.logging", "m5"}, + } + } + }; + } + + @Test(dataProvider = "testregex") + public void testregex(String name, String[][] expected) throws Exception { + String cmd = String.format("jdeps -inverse -modulepath %s -regex %s -addmods %s%n", + MODS_DIR, name, modules.stream().collect(Collectors.joining(","))); + + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.appModulePath(MODS_DIR.toString()) + .addmods(modules) + .regex(name); + + runJdeps(jdeps, expected); + } + } + + @DataProvider(name = "classpath") + public Object[][] expected4() { + return new Object[][] { + // -regex and result + { "sun.misc.Unsafe", new String[][] { + new String[] {"jdk.unsupported", "unsafe.jar", "m6.jar", "m7.jar"}, + new String[] {"jdk.unsupported", "unsafe.jar", "m7.jar"} + } + }, + { "org.safe.Lib", new String[][] { + new String[] { "unsafe.jar", "m7.jar"}, + new String[] { "unsafe.jar", "m6.jar", "m7.jar"}, + } + }, + { "java.util.logging.*|org.safe.Lib", new String[][] { + new String[] { "unsafe.jar", "m7.jar"}, + new String[] { "unsafe.jar", "m6.jar", "m7.jar"}, + new String[] { "java.logging", "m5.jar"}, + } + } + }; + } + + @Test(dataProvider = "classpath") + public void testClassPath(String name, String[][] expected) throws Exception { + // -classpath + String cpath = modules.stream() + .filter(mn -> !mn.equals("m7")) + .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString()) + .collect(Collectors.joining(File.pathSeparator)); + + Path jarfile = LIBS_DIR.resolve("m7.jar"); + + String cmd1 = String.format("jdeps -inverse -classpath %s -regex %s %s%n", + cpath, name, jarfile); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd1)) { + jdeps.verbose("-verbose:class") + .addClassPath(cpath) + .regex(name).addRoot(jarfile); + runJdeps(jdeps, expected); + } + + // all JAR files on the command-line arguments + Set paths = modules.stream() + .map(mn -> LIBS_DIR.resolve(mn + ".jar")) + .collect(Collectors.toSet()); + String cmd2 = String.format("jdeps -inverse -regex %s %s%n", name, paths); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd2)) { + jdeps.verbose("-verbose:class").regex(name); + paths.forEach(jdeps::addRoot); + runJdeps(jdeps, expected); + } + } + + private void runJdeps(JdepsUtil.Command jdeps, String[][] expected) throws Exception { + InverseDepsAnalyzer analyzer = jdeps.getInverseDepsAnalyzer(); + + assertTrue(analyzer.run()); + + // get the inverse transitive dependences + List paths = analyzer.inverseDependences().stream() + .map(deque -> deque.stream() + .map(Archive::getName) + .collect(Collectors.toList()).toArray(new String[0])) + .collect(Collectors.toList()); + + jdeps.dumpOutput(System.err); + paths.forEach(path -> System.err.println(Arrays.stream(path) + .collect(Collectors.joining(" <- ")))); + + // verify the dependences + assertEquals(paths.size(), expected.length); + + for (int i=0; i < paths.size(); i++) { + String[] path = paths.get(i); + boolean noneMatched = Arrays.stream(expected) + .filter(array -> array.length == path.length) + .noneMatch(array -> Arrays.equals(array, path)); + if (noneMatched) + System.err.format("Expected: %s found: %s%n", + Arrays.stream(expected) + .map(Arrays::toString) + .collect(Collectors.joining(", ")), + Arrays.toString(path)); + + assertFalse(noneMatched); + } + } + +} diff --git a/langtools/test/tools/jdeps/modules/ModuleTest.java b/langtools/test/tools/jdeps/modules/ModuleTest.java index f9e6dd0ddc5..f210dec8900 100644 --- a/langtools/test/tools/jdeps/modules/ModuleTest.java +++ b/langtools/test/tools/jdeps/modules/ModuleTest.java @@ -24,30 +24,28 @@ /* * @test * @summary Tests jdeps -m and -mp options on named modules and unnamed modules - * @library .. - * @build CompilerUtils + * @library ../lib + * @build CompilerUtils JdepsUtil * @modules jdk.jdeps/com.sun.tools.jdeps * @run testng ModuleTest */ -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.module.ModuleDescriptor; -import java.lang.module.ModuleDescriptor.Requires.Modifier; -import static java.lang.module.ModuleDescriptor.Requires.Modifier.*; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; - import java.util.stream.Collectors; + +import com.sun.tools.jdeps.DepsAnalyzer; +import com.sun.tools.jdeps.Graph; import org.testng.annotations.DataProvider; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; public class ModuleTest { @@ -56,6 +54,7 @@ public class ModuleTest { private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); private static final Path MODS_DIR = Paths.get("mods"); + private static final Path UNNAMED_DIR = Paths.get("unnamed"); // the names of the modules in this test private static final String UNSUPPORTED = "unsupported"; @@ -66,62 +65,68 @@ public class ModuleTest { @BeforeTest public void compileAll() throws Exception { CompilerUtils.cleanDir(MODS_DIR); + CompilerUtils.cleanDir(UNNAMED_DIR); + assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, UNSUPPORTED, "-XaddExports:java.base/jdk.internal.perf=" + UNSUPPORTED)); // m4 is not referenced Arrays.asList("m1", "m2", "m3", "m4") .forEach(mn -> assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn))); + + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("m3"), UNNAMED_DIR, "-mp", MODS_DIR.toString())); + Files.delete(UNNAMED_DIR.resolve("module-info.class")); } @DataProvider(name = "modules") public Object[][] expected() { return new Object[][]{ - { "m3", new Data("m3").requiresPublic("java.sql") - .requiresPublic("m2") - .requires("java.logging") - .requiresPublic("m1") - .reference("p3", "java.lang", "java.base") - .reference("p3", "java.sql", "java.sql") - .reference("p3", "java.util.logging", "java.logging") - .reference("p3", "p1", "m1") - .reference("p3", "p2", "m2") - .qualified("p3", "p2.internal", "m2") + { "m3", new ModuleMetaData("m3").requiresPublic("java.sql") + .requiresPublic("m2") + .requires("java.logging") + .requiresPublic("m1") + .reference("p3", "java.lang", "java.base") + .reference("p3", "java.sql", "java.sql") + .reference("p3", "java.util.logging", "java.logging") + .reference("p3", "p1", "m1") + .reference("p3", "p2", "m2") + .qualified("p3", "p2.internal", "m2") }, - { "m2", new Data("m2").requiresPublic("m1") - .reference("p2", "java.lang", "java.base") - .reference("p2", "p1", "m1") - .reference("p2.internal", "java.lang", "java.base") - .reference("p2.internal", "java.io", "java.base") + { "m2", new ModuleMetaData("m2").requiresPublic("m1") + .reference("p2", "java.lang", "java.base") + .reference("p2", "p1", "m1") + .reference("p2.internal", "java.lang", "java.base") + .reference("p2.internal", "java.io", "java.base") }, - { "m1", new Data("m1").requires("unsupported") - .reference("p1", "java.lang", "java.base") - .reference("p1.internal", "java.lang", "java.base") - .reference("p1.internal", "p1", "m1") - .reference("p1.internal", "q", "unsupported") + { "m1", new ModuleMetaData("m1").requires("unsupported") + .reference("p1", "java.lang", "java.base") + .reference("p1.internal", "java.lang", "java.base") + .reference("p1.internal", "p1", "m1") + .reference("p1.internal", "q", "unsupported") }, - { "unsupported", new Data("unsupported") - .reference("q", "java.lang", "java.base") - .jdkInternal("q", "jdk.internal.perf", "(java.base)") + { "unsupported", new ModuleMetaData("unsupported") + .reference("q", "java.lang", "java.base") + .jdkInternal("q", "jdk.internal.perf", "java.base") }, }; } @Test(dataProvider = "modules") - public void modularTest(String name, Data data) { - // print only the specified module - String excludes = Arrays.stream(modules) - .filter(mn -> !mn.endsWith(name)) - .collect(Collectors.joining(",")); - String[] result = jdeps("-exclude-modules", excludes, - "-mp", MODS_DIR.toString(), - "-m", name); - assertTrue(data.check(result)); + public void modularTest(String name, ModuleMetaData data) throws IOException { + // jdeps -modulepath mods -m + runTest(data, MODS_DIR.toString(), Set.of(name)); + + // jdeps -modulepath libs/m1.jar:.... -m + String mp = Arrays.stream(modules) + .filter(mn -> !mn.equals(name)) + .map(mn -> MODS_DIR.resolve(mn).toString()) + .collect(Collectors.joining(File.pathSeparator)); + runTest(data, mp, Collections.emptySet(), MODS_DIR.resolve(name)); } @DataProvider(name = "unnamed") public Object[][] unnamed() { return new Object[][]{ - { "m3", new Data("m3", false) + { "unnamed", new ModuleMetaData("unnamed", false) .depends("java.sql") .depends("java.logging") .depends("m1") @@ -133,178 +138,43 @@ public class ModuleTest { .reference("p3", "p2", "m2") .internal("p3", "p2.internal", "m2") }, - { "unsupported", new Data("unsupported", false) - .reference("q", "java.lang", "java.base") - .jdkInternal("q", "jdk.internal.perf", "(java.base)") - }, }; } @Test(dataProvider = "unnamed") - public void unnamedTest(String name, Data data) { - String[] result = jdeps("-mp", MODS_DIR.toString(), MODS_DIR.resolve(name).toString()); - assertTrue(data.check(result)); + public void unnamedTest(String name, ModuleMetaData data) throws IOException { + runTest(data, MODS_DIR.toString(), Set.of("m1", "m2"), UNNAMED_DIR); } - /* - * Runs jdeps with the given arguments - */ - public static String[] jdeps(String... args) { - String lineSep = System.getProperty("line.separator"); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - System.err.println("jdeps " + Arrays.toString(args)); - int rc = com.sun.tools.jdeps.Main.run(args, pw); - pw.close(); - String out = sw.toString(); - if (!out.isEmpty()) - System.err.println(out); - if (rc != 0) - throw new Error("jdeps failed: rc=" + rc); - return out.split(lineSep); - } + private void runTest(ModuleMetaData data, String modulepath, + Set roots, Path... paths) + throws IOException + { + // jdeps -modulepath -m root paths + String cmd = String.format("jdeps -modulepath %s -addmods %s %s%n", + MODS_DIR, roots.stream().collect(Collectors.joining(",")), paths); - static class Data { - static final String INTERNAL = "(internal)"; - static final String QUALIFIED = "(qualified)"; - static final String JDK_INTERNAL = "JDK internal API"; + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.appModulePath(modulepath) + .addmods(roots); + Arrays.stream(paths).forEach(jdeps::addRoot); - final String moduleName; - final boolean isNamed; - final Map requires = new LinkedHashMap<>(); - final Map references = new LinkedHashMap<>(); - Data(String name) { - this(name, true); - } - Data(String name, boolean isNamed) { - this.moduleName = name; - this.isNamed = isNamed; - requires("java.base"); // implicit requires - } + // run the analyzer + DepsAnalyzer analyzer = jdeps.getDepsAnalyzer(); + assertTrue(analyzer.run()); - Data requires(String name) { - requires.put(name, new ModuleRequires(name)); - return this; - } - Data requiresPublic(String name) { - requires.put(name, new ModuleRequires(name, PUBLIC)); - return this; - } - // for unnamed module - Data depends(String name) { - requires.put(name, new ModuleRequires(name)); - return this; - } - Data reference(String origin, String target, String module) { - return dependence(origin, target, module, ""); - } - Data internal(String origin, String target, String module) { - return dependence(origin, target, module, INTERNAL); - } - Data qualified(String origin, String target, String module) { - return dependence(origin, target, module, QUALIFIED); - } - Data jdkInternal(String origin, String target, String module) { - return dependence(origin, target, module, JDK_INTERNAL); - } - private Data dependence(String origin, String target, String module, String access) { - references.put(key(origin, target), new Dependence(origin, target, module, access)); - return this; - } + // analyze result + Graph g1 = analyzer.moduleGraph(); + g1.nodes().stream() + .filter(u -> u.name.equals(data.moduleName)) + .forEach(u -> data.checkRequires(u.name, g1.adjacentNodes(u))); - String key(String origin, String target) { - return origin+":"+target; - } - boolean check(String[] lines) { - System.out.format("verifying module %s%s%n", moduleName, isNamed ? "" : " (unnamed module)"); - for (String l : lines) { - String[] tokens = l.trim().split("\\s+"); - System.out.println(" " + Arrays.stream(tokens).collect(Collectors.joining(" "))); - switch (tokens[0]) { - case "module": - assertEquals(tokens.length, 2); - assertEquals(moduleName, tokens[1]); - break; - case "requires": - String name = tokens.length == 2 ? tokens[1] : tokens[2]; - Modifier modifier = null; - if (tokens.length == 3) { - assertEquals("public", tokens[1]); - modifier = PUBLIC; - } - checkRequires(name, modifier); - break; - default: - if (tokens.length == 3) { - // unnamed module requires - assertFalse(isNamed); - assertEquals(moduleName, tokens[0]); - String mn = tokens[2]; - checkRequires(mn, null); - } else { - checkDependence(tokens); - } - } - } - return true; - } + Graph g2 = analyzer.dependenceGraph(); + g2.nodes().stream() + .filter(u -> u.name.equals(data.moduleName)) + .forEach(u -> data.checkDependences(u.name, g2.adjacentNodes(u))); - private void checkRequires(String name, Modifier modifier) { - assertTrue(requires.containsKey(name)); - ModuleRequires req = requires.get(name); - assertEquals(req.mod, modifier); - } - - private void checkDependence(String[] tokens) { - assertTrue(tokens.length >= 4); - String origin = tokens[0]; - String target = tokens[2]; - String module = tokens[3]; - String key = key(origin, target); - assertTrue(references.containsKey(key)); - Dependence dep = references.get(key); - if (tokens.length == 4) { - assertEquals(dep.access, ""); - } else if (tokens.length == 5) { - assertEquals(dep.access, tokens[4]); - } else { - // JDK internal API - module = tokens[6]; - assertEquals(tokens.length, 7); - assertEquals(tokens[3], "JDK"); - assertEquals(tokens[4], "internal"); - assertEquals(tokens[5], "API"); - } - assertEquals(dep.module, module); - } - - public static class ModuleRequires { - final String name; - final ModuleDescriptor.Requires.Modifier mod; - - ModuleRequires(String name) { - this.name = name; - this.mod = null; - } - - ModuleRequires(String name, ModuleDescriptor.Requires.Modifier mod) { - this.name = name; - this.mod = mod; - } - } - - public static class Dependence { - final String origin; - final String target; - final String module; - final String access; - - Dependence(String origin, String target, String module, String access) { - this.origin = origin; - this.target = target; - this.module = module; - this.access = access; - } + jdeps.dumpOutput(System.err); } } } diff --git a/langtools/test/tools/jdeps/modules/SplitPackage.java b/langtools/test/tools/jdeps/modules/SplitPackage.java new file mode 100644 index 00000000000..b85aed96127 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/SplitPackage.java @@ -0,0 +1,104 @@ +/* + * 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 + * @summary Tests split packages + * @library ../lib + * @build CompilerUtils + * @modules jdk.jdeps/com.sun.tools.jdeps + * @run testng SplitPackage + */ + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import com.sun.tools.jdeps.DepsAnalyzer; +import com.sun.tools.jdeps.JdepsConfiguration; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +public class SplitPackage { + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path CLASSES_DIR = Paths.get("classes"); + + private static final String SPLIT_PKG_NAME = "javax.annotation"; + private static final String JAVA_ANNOTATIONS_COMMON = "java.annotations.common"; + /** + * Compiles classes used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + CompilerUtils.cleanDir(CLASSES_DIR); + assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "patches"), CLASSES_DIR)); + } + + @Test + public void runTest() throws Exception { + // Test jdeps classes + runTest(null); + // Test jdeps -addmods + runTest(JAVA_ANNOTATIONS_COMMON, SPLIT_PKG_NAME); + } + + private void runTest(String root, String... splitPackages) throws Exception { + String cmd = String.format("jdeps -verbose:class -addmods %s %s%n", + root, CLASSES_DIR); + + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.verbose("-verbose:class") + .addRoot(CLASSES_DIR); + if (root != null) + jdeps.addmods(Set.of(root)); + + JdepsConfiguration config = jdeps.configuration(); + Map> pkgs = config.splitPackages(); + + final Set expected; + if (splitPackages != null) { + expected = Arrays.stream(splitPackages).collect(Collectors.toSet()); + } else { + expected = Collections.emptySet(); + } + + if (!pkgs.keySet().equals(expected)) { + throw new RuntimeException(splitPackages.toString()); + } + + // java.annotations.common is not observable + DepsAnalyzer analyzer = jdeps.getDepsAnalyzer(); + + assertTrue(analyzer.run()); + + jdeps.dumpOutput(System.err); + } + } +} diff --git a/langtools/test/tools/jdeps/modules/TransitiveDeps.java b/langtools/test/tools/jdeps/modules/TransitiveDeps.java new file mode 100644 index 00000000000..99533849aa1 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/TransitiveDeps.java @@ -0,0 +1,327 @@ +/* + * 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 + * @summary Tests jdeps -m and -mp options on named modules and unnamed modules + * @library ../lib + * @build CompilerUtils JdepsUtil + * @modules jdk.jdeps/com.sun.tools.jdeps + * @run testng TransitiveDeps + */ + +import java.io.File; +import java.io.IOException; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +import com.sun.tools.jdeps.DepsAnalyzer; +import com.sun.tools.jdeps.Graph; +import org.testng.annotations.DataProvider; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +public class TransitiveDeps { + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + private static final Path LIBS_DIR = Paths.get("libs"); + + // the names of the modules in this test + private static String[] modules = new String[] {"unsafe", "m6", "m7"}; + /** + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + CompilerUtils.cleanDir(MODS_DIR); + CompilerUtils.cleanDir(LIBS_DIR); + + for (String mn : modules) { + // compile a module + assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)); + + // create JAR files with no module-info.class + Path root = MODS_DIR.resolve(mn); + try (Stream stream = Files.walk(root, Integer.MAX_VALUE)) { + Stream entries = stream.filter(f -> { + String fn = f.getFileName().toString(); + return fn.endsWith(".class") && !fn.equals("module-info.class"); + }); + JdepsUtil.createJar(LIBS_DIR.resolve(mn + ".jar"), root, entries); + } + } + } + + @DataProvider(name = "modules") + public Object[][] expected1() { + return new Object[][]{ + { "m7", + List.of(new ModuleMetaData("m7") + .requires("m6") + .requires("unsafe") + .reference("p7.Main", "java.lang.Object", "java.base") + .reference("p7.Main", "java.lang.String", "java.base") + .reference("p7.Main", "org.safe.Lib", "unsafe") + .reference("p7.Main", "p6.safe.Lib", "m6"), + new ModuleMetaData("m6") + .requires("unsafe") + .reference("p6.indirect.UnsafeRef", "java.lang.Object", "java.base") + .reference("p6.indirect.UnsafeRef", "org.unsafe.UseUnsafe ", "unsafe") + .reference("p6.safe.Lib", "java.io.PrintStream", "java.base") + .reference("p6.safe.Lib", "java.lang.Class", "java.base") + .reference("p6.safe.Lib", "java.lang.Object", "java.base") + .reference("p6.safe.Lib", "java.lang.String", "java.base") + .reference("p6.safe.Lib", "java.lang.System", "java.base") + .reference("p6.safe.Lib", "org.safe.Lib", "unsafe"), + new ModuleMetaData("unsafe") + .requires("jdk.unsupported") + .reference("org.indirect.UnsafeRef", "java.lang.Object", "java.base") + .reference("org.safe.Lib", "java.io.PrintStream", "java.base") + .reference("org.safe.Lib", "java.lang.Class", "java.base") + .reference("org.safe.Lib", "java.lang.Object", "java.base") + .reference("org.safe.Lib", "java.lang.String", "java.base") + .reference("org.safe.Lib", "java.lang.System", "java.base") + .reference("org.unsafe.UseUnsafe", "java.lang.Object", "java.base") + .jdkInternal("org.unsafe.UseUnsafe", "sun.misc.Unsafe", "java.base") + ) + }, + }; + } + + @Test(dataProvider = "modules") + public void testModulePath(String name, List data) throws IOException { + Set roots = Set.of("m6", "unsafe"); + + String cmd1 = String.format("jdeps -modulepath %s -addmods %s -m %s%n", MODS_DIR, + roots.stream().collect(Collectors.joining(",")), name); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd1)) { + jdeps.verbose("-verbose:class") + .appModulePath(MODS_DIR.toString()) + .addmods(roots) + .addmods(Set.of(name)); + + runJdeps(jdeps, data); + } + // run automatic modules + roots = Set.of("ALL-MODULE-PATH", "jdk.unsupported"); + + String cmd2 = String.format("jdeps -modulepath %s -addmods %s -m %s%n", LIBS_DIR, + roots.stream().collect(Collectors.joining(",")), name); + + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd2)) { + jdeps.verbose("-verbose:class") + .appModulePath(LIBS_DIR.toString()) + .addmods(roots) + .addmods(Set.of(name)); + + runJdeps(jdeps, data); + } + } + + @DataProvider(name = "jars") + public Object[][] expected2() { + return new Object[][]{ + { "m7", List.of(new ModuleMetaData("m7.jar") + .requires("m6.jar") + .requires("unsafe.jar") + .reference("p7.Main", "java.lang.Object", "java.base") + .reference("p7.Main", "java.lang.String", "java.base") + .reference("p7.Main", "org.safe.Lib", "unsafe.jar") + .reference("p7.Main", "p6.safe.Lib", "m6.jar")) + }, + }; + } + + @Test(dataProvider = "jars") + public void testClassPath(String name, List data) throws IOException { + String cpath = Arrays.stream(modules) + .filter(mn -> !mn.equals(name)) + .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString()) + .collect(Collectors.joining(File.pathSeparator)); + + Path jarfile = LIBS_DIR.resolve(name + ".jar"); + + String cmd = String.format("jdeps -classpath %s %s%n", cpath, jarfile); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.verbose("-verbose:class") + .addClassPath(cpath) + .addRoot(jarfile); + + runJdeps(jdeps, data); + } + } + + @DataProvider(name = "compileTimeView") + public Object[][] expected3() { + return new Object[][] { + {"m7", + List.of(new ModuleMetaData("m7.jar") + .requires("m6.jar") + .requires("unsafe.jar") + .reference("p7.Main", "java.lang.Object", "java.base") + .reference("p7.Main", "java.lang.String", "java.base") + .reference("p7.Main", "org.safe.Lib", "unsafe.jar") + .reference("p7.Main", "p6.safe.Lib", "m6.jar"), + new ModuleMetaData("m6.jar") + .requires("unsafe.jar") + .reference("p6.indirect.UnsafeRef", "java.lang.Object", "java.base") + .reference("p6.indirect.UnsafeRef", "org.unsafe.UseUnsafe ", "unsafe.jar") + .reference("p6.safe.Lib", "java.io.PrintStream", "java.base") + .reference("p6.safe.Lib", "java.lang.Class", "java.base") + .reference("p6.safe.Lib", "java.lang.Object", "java.base") + .reference("p6.safe.Lib", "java.lang.String", "java.base") + .reference("p6.safe.Lib", "java.lang.System", "java.base") + .reference("p6.safe.Lib", "org.safe.Lib", "unsafe.jar"), + new ModuleMetaData("unsafe.jar") + .requires("jdk.unsupported") + .reference("org.indirect.UnsafeRef", "java.lang.Object", "java.base") + .reference("org.safe.Lib", "java.io.PrintStream", "java.base") + .reference("org.safe.Lib", "java.lang.Class", "java.base") + .reference("org.safe.Lib", "java.lang.Object", "java.base") + .reference("org.safe.Lib", "java.lang.String", "java.base") + .reference("org.safe.Lib", "java.lang.System", "java.base") + .reference("org.unsafe.UseUnsafe", "java.lang.Object", "java.base") + .jdkInternal("org.unsafe.UseUnsafe", "sun.misc.Unsafe", "java.base") + ) + }, + }; + } + + @Test(dataProvider = "compileTimeView") + public void compileTimeView(String name, List data) throws IOException { + String cpath = Arrays.stream(modules) + .filter(mn -> !mn.equals(name)) + .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString()) + .collect(Collectors.joining(File.pathSeparator)); + + Path jarfile = LIBS_DIR.resolve(name + ".jar"); + + String cmd = String.format("jdeps -ct -classpath %s %s%n", cpath, jarfile); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.verbose("-verbose:class") + .addClassPath(cpath) + .addRoot(jarfile); + + runJdeps(jdeps, data, true, 0 /* -recursive */); + } + } + + @DataProvider(name = "recursiveDeps") + public Object[][] expected4() { + return new Object[][] { + {"m7", + List.of(new ModuleMetaData("m7.jar") + .requires("m6.jar") + .requires("unsafe.jar") + .reference("p7.Main", "java.lang.Object", "java.base") + .reference("p7.Main", "java.lang.String", "java.base") + .reference("p7.Main", "org.safe.Lib", "unsafe.jar") + .reference("p7.Main", "p6.safe.Lib", "m6.jar"), + new ModuleMetaData("m6.jar") + .requires("unsafe.jar") + .reference("p6.safe.Lib", "java.io.PrintStream", "java.base") + .reference("p6.safe.Lib", "java.lang.Class", "java.base") + .reference("p6.safe.Lib", "java.lang.Object", "java.base") + .reference("p6.safe.Lib", "java.lang.String", "java.base") + .reference("p6.safe.Lib", "java.lang.System", "java.base") + .reference("p6.safe.Lib", "org.safe.Lib", "unsafe.jar"), + new ModuleMetaData("unsafe.jar") + .requires("jdk.unsupported") + .reference("org.indirect.UnsafeRef", "java.lang.Object", "java.base") + .reference("org.safe.Lib", "java.io.PrintStream", "java.base") + .reference("org.safe.Lib", "java.lang.Class", "java.base") + .reference("org.safe.Lib", "java.lang.Object", "java.base") + .reference("org.safe.Lib", "java.lang.String", "java.base") + .reference("org.safe.Lib", "java.lang.System", "java.base") + ) + }, + }; + } + @Test(dataProvider = "recursiveDeps") + public void recursiveDeps(String name, List data) throws IOException { + String cpath = Arrays.stream(modules) + .filter(mn -> !mn.equals(name)) + .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString()) + .collect(Collectors.joining(File.pathSeparator)); + + Path jarfile = LIBS_DIR.resolve(name + ".jar"); + + String cmd = String.format("jdeps -R -classpath %s %s%n", cpath, jarfile); + try (JdepsUtil.Command jdeps = JdepsUtil.newCommand(cmd)) { + jdeps.verbose("-verbose:class").filter("-filter:archive") + .addClassPath(cpath) + .addRoot(jarfile); + + runJdeps(jdeps, data, true, 0 /* -recursive */); + } + } + + private void runJdeps(JdepsUtil.Command jdeps, List data) + throws IOException + { + runJdeps(jdeps, data, false, 1 /* depth */); + } + + private void runJdeps(JdepsUtil.Command jdeps, List data, + boolean compileTimeView, int depth) + throws IOException + { + // run the analyzer + DepsAnalyzer analyzer = jdeps.getDepsAnalyzer(); + assertTrue(analyzer.run(compileTimeView, depth)); + jdeps.dumpOutput(System.err); + + // analyze result + Graph g1 = analyzer.moduleGraph(); + Map dataMap = data.stream() + .collect(Collectors.toMap(ModuleMetaData::name, Function.identity())); + + // the returned graph contains all nodes such as java.base and jdk.unsupported + g1.nodes().stream() + .filter(u -> dataMap.containsKey(u.name)) + .forEach(u -> { + ModuleMetaData md = dataMap.get(u.name); + md.checkRequires(u.name, g1.adjacentNodes(u)); + }); + + Graph g2 = analyzer.dependenceGraph(); + + g2.nodes().stream() + .filter(u -> dataMap.containsKey(u.name)) + .forEach(u -> { + ModuleMetaData md = dataMap.get(u.name); + md.checkDependences(u.name, g2.adjacentNodes(u)); + }); + } +} diff --git a/langtools/test/tools/jdeps/modules/patches/javax/annotation/NonNull.java b/langtools/test/tools/jdeps/modules/patches/javax/annotation/NonNull.java new file mode 100644 index 00000000000..4aab38a5b0f --- /dev/null +++ b/langtools/test/tools/jdeps/modules/patches/javax/annotation/NonNull.java @@ -0,0 +1,37 @@ +/* + * 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 javax.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; + +@Documented +@Target({FIELD, LOCAL_VARIABLE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface NonNull { +} diff --git a/langtools/test/tools/jdeps/modules/src/m4/module-info.java b/langtools/test/tools/jdeps/modules/src/m4/module-info.java index ddca4f59763..d49490919a4 100644 --- a/langtools/test/tools/jdeps/modules/src/m4/module-info.java +++ b/langtools/test/tools/jdeps/modules/src/m4/module-info.java @@ -22,8 +22,14 @@ */ module m4 { + // not used in signature requires public java.compiler; + + // unused dependence requires java.logging; + exports p4; - exports p4.internal to m1,m2,m3; + + // unuused qualified exports + exports p4.internal to m6,m7; } diff --git a/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java b/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java index ea2c5486d99..34bdab498e1 100644 --- a/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java +++ b/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java @@ -23,9 +23,14 @@ package p4.internal; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; public class Impl { + private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + public String name() { return Impl.class.getName(); } + } diff --git a/langtools/test/tools/jdeps/modules/src/m5/module-info.java b/langtools/test/tools/jdeps/modules/src/m5/module-info.java new file mode 100644 index 00000000000..2affe5a3125 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m5/module-info.java @@ -0,0 +1,39 @@ +/* + * 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 m5 { + // m4 requires public java.compilerr + requires public m4; + requires public java.compiler; + + // java.sql should be requires public + requires java.sql; + + // java.logging is used for implementation only + requires public java.logging; + + exports p5; + + // m8 is not in the resolved graph but used by m8 + exports p5.internal to m8; +} diff --git a/langtools/test/tools/jdeps/modules/src/m5/p5/Main.java b/langtools/test/tools/jdeps/modules/src/m5/p5/Main.java new file mode 100644 index 00000000000..c0a86835e12 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m5/p5/Main.java @@ -0,0 +1,44 @@ +/* + * 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 p5; + +import java.sql.Driver; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; + +public class Main { + public void run(Driver driver) throws Exception { + driver.getParentLogger().config("test"); + + } + + public p4.Lib getLib() { + return new p4.Lib(); + } + + public JavaCompiler getCompiler() { + return ToolProvider.getSystemJavaCompiler(); + } + +} diff --git a/langtools/test/tools/jdeps/modules/src/m5/p5/internal/T.java b/langtools/test/tools/jdeps/modules/src/m5/p5/internal/T.java new file mode 100644 index 00000000000..8eaac303560 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m5/p5/internal/T.java @@ -0,0 +1,27 @@ +/* + * 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 p5.internal; + +public class T { +} diff --git a/langtools/test/tools/jdeps/modules/src/m6/module-info.java b/langtools/test/tools/jdeps/modules/src/m6/module-info.java new file mode 100644 index 00000000000..374fbfa1c6b --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m6/module-info.java @@ -0,0 +1,33 @@ +/* + * 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 m6 { + requires unsafe; + + // no dependency on sun.misc.Unsafe directly or indirectly + exports p6.safe; + + // direct dependency on org.unsafe + // hence indirect dependency on sun.misc.Unsafe + exports p6.indirect; +} diff --git a/langtools/test/tools/jdeps/modules/src/m6/p6/indirect/UnsafeRef.java b/langtools/test/tools/jdeps/modules/src/m6/p6/indirect/UnsafeRef.java new file mode 100644 index 00000000000..28ba63df16e --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m6/p6/indirect/UnsafeRef.java @@ -0,0 +1,31 @@ +/* + * 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 p6.indirect; + +// indirectly depend on sun.misc.Unsafe +public class UnsafeRef { + public static org.unsafe.UseUnsafe get() { + return new org.unsafe.UseUnsafe(); + } +} diff --git a/langtools/test/tools/jdeps/modules/src/m6/p6/safe/Lib.java b/langtools/test/tools/jdeps/modules/src/m6/p6/safe/Lib.java new file mode 100644 index 00000000000..9a943bd4188 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m6/p6/safe/Lib.java @@ -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 p6.safe; + +// no direct or indirect dependency on sun.misc.Unsafe +public class Lib { + public static void doit() { + System.out.println(Lib.class.getName()); + org.safe.Lib.doit(); + } +} diff --git a/langtools/test/tools/jdeps/modules/src/m7/module-info.java b/langtools/test/tools/jdeps/modules/src/m7/module-info.java new file mode 100644 index 00000000000..408efc216d4 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m7/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 m7 { + // only use classes that have no direct or indirect dependency + // to sun.misc.Unsafe + requires unsafe; + requires m6; +} diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java new file mode 100644 index 00000000000..789cdb9a0a7 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java @@ -0,0 +1,33 @@ +/* + * 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 p7; + +// Only use classes in unsafe and m6 modules with no +// direct or indirect dependency on sun.misc.Unsafe +public class Main { + public static void main(String... args) { + p6.safe.Lib.doit(); + org.safe.Lib.doit(); + } +} diff --git a/langtools/test/tools/jdeps/modules/src/m8/module-info.java b/langtools/test/tools/jdeps/modules/src/m8/module-info.java new file mode 100644 index 00000000000..128025f352b --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m8/module-info.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 m8 { + requires m5; + + // use p5.internal +} diff --git a/langtools/test/tools/jdeps/modules/src/m8/p8/Main.java b/langtools/test/tools/jdeps/modules/src/m8/p8/Main.java new file mode 100644 index 00000000000..1fc8a107c53 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/m8/p8/Main.java @@ -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 p8; + +import p5.internal.T; + +public class Main { + public static void main() { + T t = new T(); + } +} diff --git a/langtools/test/tools/jdeps/modules/src/unsafe/module-info.java b/langtools/test/tools/jdeps/modules/src/unsafe/module-info.java new file mode 100644 index 00000000000..363bd50310c --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/unsafe/module-info.java @@ -0,0 +1,35 @@ +/* + * 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 unsafe { + requires jdk.unsupported; + + // direct dependency on sun.misc.Unsafe + exports org.unsafe; + + // no dependency on sun.misc.Unsafe directly or indirectly + exports org.safe; + + // indirect dependency on sun.misc.Unsafe + exports org.indirect; +} diff --git a/langtools/test/tools/jdeps/modules/src/unsafe/org/indirect/UnsafeRef.java b/langtools/test/tools/jdeps/modules/src/unsafe/org/indirect/UnsafeRef.java new file mode 100644 index 00000000000..acd3e9326ab --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/unsafe/org/indirect/UnsafeRef.java @@ -0,0 +1,31 @@ +/* + * 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 org.indirect; + +// indirectly depend on sun.misc.Unsafe +public class UnsafeRef { + public static org.unsafe.UseUnsafe get() { + return new org.unsafe.UseUnsafe(); + } +} diff --git a/langtools/test/tools/jdeps/modules/src/unsafe/org/safe/Lib.java b/langtools/test/tools/jdeps/modules/src/unsafe/org/safe/Lib.java new file mode 100644 index 00000000000..ad5769c7435 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/unsafe/org/safe/Lib.java @@ -0,0 +1,31 @@ +/* + * 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 org.safe; + +// no direct or indirect dependency on sun.misc.Unsafe +public class Lib { + public static void doit() { + System.out.println(Lib.class.getName()); + } +} diff --git a/langtools/test/tools/jdeps/modules/src/unsafe/org/unsafe/UseUnsafe.java b/langtools/test/tools/jdeps/modules/src/unsafe/org/unsafe/UseUnsafe.java new file mode 100644 index 00000000000..ec010c32537 --- /dev/null +++ b/langtools/test/tools/jdeps/modules/src/unsafe/org/unsafe/UseUnsafe.java @@ -0,0 +1,30 @@ +/* + * 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 org.unsafe; + +import sun.misc.Unsafe; + +public class UseUnsafe { + static Unsafe unsafe = Unsafe.getUnsafe(); +} diff --git a/langtools/test/tools/jdeps/unsupported/JDKUnsupportedTest.java b/langtools/test/tools/jdeps/unsupported/JDKUnsupportedTest.java index bf2c4c61ac0..3e2e195fa19 100644 --- a/langtools/test/tools/jdeps/unsupported/JDKUnsupportedTest.java +++ b/langtools/test/tools/jdeps/unsupported/JDKUnsupportedTest.java @@ -62,7 +62,7 @@ public class JDKUnsupportedTest { public void test(String filename, String[][] expected) { Path path = Paths.get(TEST_CLASSES, filename); - Map result = jdeps("-M", path.toString()); + Map result = jdeps(path.toString()); for (String[] e : expected) { String pn = e[0]; String module = e[1]; diff --git a/make/Bundles.gmk b/make/Bundles.gmk new file mode 100644 index 00000000000..140f31afcf2 --- /dev/null +++ b/make/Bundles.gmk @@ -0,0 +1,300 @@ +# +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk + +PRODUCT_TARGETS := +TEST_TARGETS := +DOCS_TARGETS := + +# On Windows tar frequently complains that "file changed as we read it" for +# some random source files. This seems to be cause by anti virus scanners and +# is most likely safe to ignore. When it happens, tar returns '1'. +ifeq ($(OPENJDK_BUILD_OS), windows) + TAR_IGNORE_EXIT_VALUE := || test "$$$$?" = "1" +endif + +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, , Bundles-pre.gmk)) +################################################################################ +# BUNDLE : Name of bundle to create +# FILES : Files in BASE_DIR to add to bundle +# SPECIAL_INCLUDES : List of directories inside BASE_DIR to look for additional +# files in. These files will not get proper dependency handling. Use when +# files or directories may contain spaces. +# BASE_DIR : Base directory for the root dir in the bundle. +# SUBDIR : Optional name of root dir in bundle. +SetupBundleFile = $(NamedParamsMacroTemplate) +define SetupBundleFileBody + + $1_RELATIVE_FILES := $$(patsubst $$($1_BASE_DIR)/%, ./%, $$($1_FILES)) + + ifneq ($$(filter %.tar.gz, $$($1_BUNDLE_NAME)), ) + $1_TYPE := tar.gz + else ifneq ($$(filter %.zip, $$($1_BUNDLE_NAME)), ) + $1_TYPE := zip + else + $$(error Unknown bundle type $$($1_BUNDLE_NAME)) + endif + + $$(call SetIfEmpty, $1_UNZIP_DEBUGINFO, false) + + $(BUNDLES_OUTPUTDIR)/$$($1_BUNDLE_NAME): $$($1_FILES) + $$(eval $$(call ListPathsSafely, \ + $1_RELATIVE_FILES, \ + $(SUPPORT_OUTPUTDIR)/bundles/_$1_files)) + $$(call MakeDir, $$(@D)) + ifneq ($$($1_SPECIAL_INCLUDES), ) + $$(foreach i, $$($1_SPECIAL_INCLUDES), \ + ($(CD) $$($1_BASE_DIR) && $(FIND) ./$$i \ + >> $(SUPPORT_OUTPUTDIR)/bundles/_$1_files ) ; ) + endif + ifneq ($$($1_SUBDIR), ) + ifeq ($$($1_TYPE)-$(TAR_SUPPORTS_TRANSFORM)-$$($1_UNZIP_DEBUGINFO), tar.gz-true-false) + $(CD) $$($1_BASE_DIR) \ + && ( $(TAR) cf - -$(TAR_INCLUDE_PARAM) $(SUPPORT_OUTPUTDIR)/bundles/_$1_files \ + --transform 's|^|$$($1_SUBDIR)/|' $(TAR_IGNORE_EXIT_VALUE) ) \ + | $(GZIP) > $$@ + else + # If a subdir has been specified, copy all files into a temporary + # location with this subdir before creating the tar file + $(RM) -r $(SUPPORT_OUTPUTDIR)/bundles/$1/$$($1_SUBDIR) + $(MKDIR) -p $(SUPPORT_OUTPUTDIR)/bundles/$1/$$($1_SUBDIR) + ( $(CD) $$($1_BASE_DIR) \ + && $(TAR) cf - -$(TAR_INCLUDE_PARAM) $(SUPPORT_OUTPUTDIR)/bundles/_$1_files \ + $(TAR_IGNORE_EXIT_VALUE) ) \ + | ( $(CD) $(SUPPORT_OUTPUTDIR)/bundles/$1/$$($1_SUBDIR) && $(TAR) xf - ) + # Unzip any zipped debuginfo files + ifeq ($$($1_UNZIP_DEBUGINFO), true) + for f in `$(FIND) $(SUPPORT_OUTPUTDIR)/bundles/$1/$$($1_SUBDIR) -name "*.diz"`; do \ + $(CD) $$$${f%/*} && $(UNZIP) -q $$$${f} && $(RM) $$$${f}; \ + done + endif + ifeq ($$($1_TYPE), tar.gz) + $(CD) $(SUPPORT_OUTPUTDIR)/bundles/$1 && \ + ( $(TAR) cf - $$($1_SUBDIR) $(TAR_IGNORE_EXIT_VALUE) ) | $(GZIP) > $$@ + else ifeq ($$($1_TYPE), zip) + $(CD) $(SUPPORT_OUTPUTDIR)/bundles/$1 && $(ZIP) -qr $$@ . + endif + endif + else + ifeq ($$($1_TYPE), tar.gz) + $(CD) $$($1_BASE_DIR) \ + && ( $(TAR) cf - -$(TAR_INCLUDE_PARAM) $(SUPPORT_OUTPUTDIR)/bundles/_$1_files \ + $(TAR_IGNORE_EXIT_VALUE) ) \ + | $(GZIP) > $$@ + else ifeq ($$($1_TYPE), zip) + $(CD) $$($1_BASE_DIR) \ + && $(ZIP) -qr $$@ . -i@$(SUPPORT_OUTPUTDIR)/bundles/_$1_files + endif + endif + + $1 += $(BUNDLES_OUTPUTDIR)/$$($1_BUNDLE_NAME) + +endef + +################################################################################ + +# On Macosx, we bundle up the macosx specific images which already have the +# correct base directories. +ifeq ($(OPENJDK_TARGET_OS)-$(DEBUG_LEVEL), macosx-release) + JDK_IMAGE_DIR := $(JDK_MACOSX_BUNDLE_DIR) + JRE_IMAGE_DIR := $(JRE_MACOSX_BUNDLE_DIR) + JDK_IMAGE_HOMEDIR := $(JDK_MACOSX_CONTENTS_DIR)/Home + JRE_IMAGE_HOMEDIR := $(JRE_MACOSX_CONTENTS_DIR)/Home + JDK_BUNDLE_SUBDIR := + JRE_BUNDLE_SUBDIR := +else + JDK_IMAGE_HOMEDIR := $(JDK_IMAGE_DIR) + JRE_IMAGE_HOMEDIR := $(JRE_IMAGE_DIR) + JDK_BUNDLE_SUBDIR := jdk-$(VERSION_NUMBER) + JRE_BUNDLE_SUBDIR := jre-$(VERSION_NUMBER) + ifneq ($(DEBUG_LEVEL), release) + JDK_BUNDLE_SUBDIR := $(JDK_BUNDLE_SUBDIR)/$(DEBUG_LEVEL) + JRE_BUNDLE_SUBDIR := $(JRE_BUNDLE_SUBDIR)/$(DEBUG_LEVEL) + endif +endif + +################################################################################ + +ifneq ($(filter product-bundles, $(MAKECMDGOALS)), ) + $(eval $(call FillCacheFind, $(IMAGES_OUTPUTDIR))) + + SYMBOLS_EXCLUDE_PATTERN := %.debuginfo %.diz %.pdb %.map + + ALL_JDK_FILES := $(call CacheFind, $(JDK_IMAGE_DIR)) + + # Create special filter rules when dealing with unzipped .dSYM directories on + # macosx + ifeq ($(OPENJDK_TARGET_OS), macosx) + ifeq ($(ZIP_DEBUGINFO_FILES), false) + JDK_SYMBOLS_EXCLUDE_PATTERN := $(addprefix %, \ + $(call containing, .dSYM/, $(patsubst $(JDK_IMAGE_DIR)/%, %, $(ALL_JDK_FILES)))) + endif + endif + + JDK_BUNDLE_FILES := \ + $(filter-out \ + $(JDK_SYMBOLS_EXCLUDE_PATTERN) \ + $(JDK_EXTRA_EXCLUDES) \ + $(SYMBOLS_EXCLUDE_PATTERN) \ + $(JDK_IMAGE_HOMEDIR)/demo/% $(JDK_IMAGE_HOMEDIR)/sample/% \ + , \ + $(ALL_JDK_FILES) \ + ) + DEMOS_BUNDLE_FILES := \ + $(filter-out \ + $(JDK_SYMBOLS_EXCLUDE_PATTERN) \ + $(SYMBOLS_EXCLUDE_PATTERN) \ + , \ + $(filter \ + $(JDK_IMAGE_HOMEDIR)/demo/% $(JDK_IMAGE_HOMEDIR)/sample/% \ + $(JDK_IMAGE_HOMEDIR)/release \ + , \ + $(ALL_JDK_FILES) \ + ) \ + ) + JDK_SYMBOLS_BUNDLE_FILES := \ + $(filter \ + $(JDK_SYMBOLS_EXCLUDE_PATTERN) \ + $(SYMBOLS_EXCLUDE_PATTERN) \ + , \ + $(ALL_JDK_FILES) \ + ) \ + $(call CacheFind, $(SYMBOLS_IMAGE_DIR)) + + ALL_JRE_FILES := $(call CacheFind, $(JRE_IMAGE_DIR)) + + # Create special filter rules when dealing with unzipped .dSYM directories on + # macosx + ifeq ($(OPENJDK_TARGET_OS), macosx) + ifeq ($(ZIP_DEBUGINFO_FILES), false) + JRE_SYMBOLS_EXCLUDE_PATTERN := $(addprefix %, \ + $(call containing, .dSYM/, $(patsubst $(JRE_IMAGE_DIR)/%, %, $(ALL_JRE_FILES)))) + endif + endif + + JRE_BUNDLE_FILES := $(filter-out \ + $(JRE_SYMBOLS_EXCLUDE_PATTERN) \ + $(SYMBOLS_EXCLUDE_PATTERN), \ + $(ALL_JRE_FILES)) + JRE_SYMBOLS_BUNDLE_FILES := $(filter \ + $(JRE_SYMBOLS_EXCLUDE_PATTERN) \ + $(SYMBOLS_EXCLUDE_PATTERN), \ + $(ALL_JRE_FILES)) + + $(eval $(call SetupBundleFile, BUILD_JDK_BUNDLE, \ + BUNDLE_NAME := $(JDK_BUNDLE_NAME), \ + FILES := $(JDK_BUNDLE_FILES), \ + SPECIAL_INCLUDES := $(JDK_SPECIAL_INCLUDES), \ + BASE_DIR := $(JDK_IMAGE_DIR), \ + SUBDIR := $(JDK_BUNDLE_SUBDIR), \ + )) + + PRODUCT_TARGETS += $(BUILD_JDK_BUNDLE) + + $(eval $(call SetupBundleFile, BUILD_JRE_BUNDLE, \ + BUNDLE_NAME := $(JRE_BUNDLE_NAME), \ + FILES := $(JRE_BUNDLE_FILES), \ + BASE_DIR := $(JRE_IMAGE_DIR), \ + SUBDIR := $(JRE_BUNDLE_SUBDIR), \ + )) + + PRODUCT_TARGETS += $(BUILD_JRE_BUNDLE) + + $(eval $(call SetupBundleFile, BUILD_JDK_SYMBOLS_BUNDLE, \ + BUNDLE_NAME := $(JDK_SYMBOLS_BUNDLE_NAME), \ + FILES := $(JDK_SYMBOLS_BUNDLE_FILES), \ + BASE_DIR := $(JDK_IMAGE_DIR), \ + SUBDIR := $(JDK_BUNDLE_SUBDIR), \ + UNZIP_DEBUGINFO := true, \ + )) + + PRODUCT_TARGETS += $(BUILD_JDK_SYMBOLS_BUNDLE) + + $(eval $(call SetupBundleFile, BUILD_JRE_SYMBOLS_BUNDLE, \ + BUNDLE_NAME := $(JRE_SYMBOLS_BUNDLE_NAME), \ + FILES := $(JRE_SYMBOLS_BUNDLE_FILES), \ + BASE_DIR := $(JRE_IMAGE_DIR), \ + SUBDIR := $(JRE_BUNDLE_SUBDIR), \ + UNZIP_DEBUGINFO := true, \ + )) + + PRODUCT_TARGETS += $(BUILD_JRE_SYMBOLS_BUNDLE) + + $(eval $(call SetupBundleFile, BUILD_DEMOS_BUNDLE, \ + BUNDLE_NAME := $(DEMOS_BUNDLE_NAME), \ + FILES := $(call DoubleDollar, $(DEMOS_BUNDLE_FILES)), \ + BASE_DIR := $(JDK_IMAGE_DIR), \ + SUBDIR := $(JDK_BUNDLE_SUBDIR), \ + )) + + PRODUCT_TARGETS += $(BUILD_DEMOS_BUNDLE) +endif + +################################################################################ + +ifneq ($(filter test-bundles, $(MAKECMDGOALS)), ) + TEST_BUNDLE_FILES := $(call CacheFind, $(TEST_IMAGE_DIR)) + + $(eval $(call SetupBundleFile, BUILD_TEST_BUNDLE, \ + BUNDLE_NAME := $(TEST_BUNDLE_NAME), \ + FILES := $(call DoubleDollar, $(TEST_BUNDLE_FILES)), \ + BASE_DIR := $(TEST_IMAGE_DIR), \ + )) + + TEST_TARGETS += $(BUILD_TEST_BUNDLE) +endif + +################################################################################ + +ifneq ($(filter docs-bundles, $(MAKECMDGOALS)), ) + DOCS_BUNDLE_FILES := $(call CacheFind, $(DOCS_IMAGE_DIR)) + + $(eval $(call SetupBundleFile, BUILD_DOCS_BUNDLE, \ + BUNDLE_NAME := $(DOCS_BUNDLE_NAME), \ + FILES := $(DOCS_BUNDLE_FILES), \ + BASE_DIR := $(DOCS_IMAGE_DIR), \ + SUBDIR := docs, \ + )) + + DOCS_TARGETS += $(BUILD_DOCS_BUNDLE) +endif + +################################################################################ + +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, , Bundles.gmk)) + +################################################################################ + +product-bundles: $(PRODUCT_TARGETS) +test-bundles: $(TEST_TARGETS) +docs-bundles: $(DOCS_TARGETS) + +.PHONY: all default product-bundles test-bundles docs-bundles diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk index 394888c4970..40900ff91a9 100644 --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -69,21 +69,13 @@ endif # 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, $(call FindAllModules))) + $(filter-out java.base $(ALL_UPGRADEABLE_MODULES), $(call FindAllModules))) - # TODO: find modules that directly and indirectly depend on upgradeable - # modules - EXCLUDE_HASH_MODULES := $(UPGRADEABLE_MODULES) \ - java.se.ee \ - jdk.rmic \ - jdk.xml.bind \ - jdk.xml.ws \ - # - - EXCLUDE_PATTERN := $(strip $(subst $(SPACE),|,$(strip $(EXCLUDE_HASH_MODULES)))) + EXCLUDE_PATTERN := $(strip $(subst $(SPACE),|,$(strip $(ALL_UPGRADEABLE_MODULES)))) JMOD_FLAGS += --modulepath $(JMODS_DIR) \ --hash-modules '^(?!$(EXCLUDE_PATTERN))' diff --git a/make/GensrcModuleInfo.gmk b/make/GensrcModuleInfo.gmk index 2fbcdc6ab24..f3487b4339d 100644 --- a/make/GensrcModuleInfo.gmk +++ b/make/GensrcModuleInfo.gmk @@ -85,21 +85,41 @@ ifneq ($(MOD_FILES), ) MODS_REST := $(filter-out $(MODS_QUALIFIED_EXPORTS), $(MOD_FILE_CONTENTS)) # Filter the contents for modules that are actually being built - MODULES_FILTER := $(addprefix %/, $(addsuffix ;, $(ALL_MODULES))) - MODIFICATIONS := $(filter $(MODULES_FILTER), $(MODS_QUALIFIED_EXPORTS)) \ + ALL_MODULES_FILTER := $(addprefix %/, $(addsuffix ;, $(ALL_MODULES))) + MODIFICATIONS := $(filter $(ALL_MODULES_FILTER), $(MODS_QUALIFIED_EXPORTS)) \ $(MODS_REST) + # Returns non empty if the package exists in the current module + # Param 1 - Name of package with dots + PackageExists = \ + $(strip $(wildcard $(addsuffix $(subst .,/,/$(strip $1)), \ + $(MODULE_CLASSES_DIRS) \ + $(addsuffix /$(MODULE), $(IMPORT_MODULES_CLASSES)) \ + ))) + # Convert the modification lines into arguments for the modification tool. # Filter out modifications for non existing to-modules. $(foreach line, $(MODIFICATIONS), \ $(eval split_line := $(subst /,$(SPACE),$(line))) \ $(eval command := $(word 1, $(split_line))) \ - $(eval package := $(patsubst %;,%,$(word 2, $(split_line)))) \ - $(eval to_module := $(patsubst %;,%,$(word 4, $(split_line)))) \ - $(if $(to_module), \ - $(eval ARGS += -$(command) $(package)/$(to_module)) \ + $(if $(filter $(command), exports), \ + $(eval package := $(patsubst %;,%,$(word 2, $(split_line)))) \ + $(if $(call PackageExists, $(package)), \ + $(eval to_module := $(patsubst %;,%,$(word 4, $(split_line)))) \ + $(if $(to_module), \ + $(eval ARGS += -$(command) $(package)/$(to_module)) \ + , \ + $(eval ARGS += -$(command) $(package)) \ + ) \ + ) \ , \ - $(eval ARGS += -$(command) $(package)) \ + $(if $(filter $(command), provides), \ + $(eval provider := $(patsubst %;,%,$(word 2, $(split_line)))) \ + $(eval class := $(patsubst %;,%,$(word 4, $(split_line)))) \ + $(eval ARGS += -$(command) $(provider)/$(class)) \ + , \ + $(error A module-info.extra in $(MODULE) contains invalid command $(command)) \ + ) \ ) \ ) diff --git a/make/HotspotWrapper.gmk b/make/HotspotWrapper.gmk deleted file mode 100644 index 663215525a3..00000000000 --- a/make/HotspotWrapper.gmk +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute 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 the legacy hotspot-spec.gmk (which in turns includes spec.gmk) -BASE_SPEC:=$(SPEC) -# Assign to HOTSPOT_SPEC so that the variable HOTSPOT_SPEC can be -# overridden when building the buildjdk. -HOTSPOT_SPEC := $(dir $(SPEC))hotspot-spec.gmk -include $(HOTSPOT_SPEC) -include MakeBase.gmk - -# Inclusion of this pseudo-target will cause make to execute this file -# serially, regardless of -j. Recursively called makefiles will not be -# affected, however. This is required for correct dependency management. -.NOTPARALLEL: - -default: all - -# Get all files in src, make or agent subdirs in hotspot directory and -# filter out .hg. This skips the test directory. -HOTSPOT_FILES := $(shell $(FIND) -L \ - $(HOTSPOT_TOPDIR)/src $(HOTSPOT_TOPDIR)/make \ - -name ".hg" -prune -o -print) - -# The old build creates hotspot output dir before calling hotspot and -# not doing it breaks builds on msys. -$(HOTSPOT_OUTPUTDIR)/_hotspot.timestamp: $(HOTSPOT_FILES) - @$(MKDIR) -p $(HOTSPOT_OUTPUTDIR) - ($(CD) $(HOTSPOT_TOPDIR)/make && $(MAKE) $(HOTSPOT_MAKE_ARGS) \ - LOG_LEVEL=$(LOG_LEVEL) SPEC=$(HOTSPOT_SPEC) BASE_SPEC=$(BASE_SPEC)) - $(TOUCH) $@ - -hotspot: $(HOTSPOT_OUTPUTDIR)/_hotspot.timestamp - -all: hotspot - -.PHONY: default all hotspot diff --git a/make/Images.gmk b/make/Images.gmk index 564f2b27ddb..c3e93a47a97 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -43,8 +43,9 @@ ALL_MODULES := $(call FindAllModules) $(eval $(call ReadImportMetaData)) -JRE_MODULES += $(filter-out $(MODULES_FILTER), $(BOOT_MODULES) $(PLATFORM_MODULES) $(JRE_TOOL_MODULES)) -JDK_MODULES += $(filter-out $(MODULES_FILTER), $(ALL_MODULES)) +JRE_MODULES += $(filter $(ALL_MODULES), $(BOOT_MODULES) \ + $(PLATFORM_MODULES) $(JRE_TOOL_MODULES)) +JDK_MODULES += $(ALL_MODULES) # Compact builds have additional modules COMPACT1_EXTRA_MODULES := jdk.localedata jdk.crypto.pkcs11 jdk.crypto.ec @@ -114,9 +115,12 @@ JMODS := $(wildcard $(IMAGES_OUTPUTDIR)/jmods/*.jmod) # Use this file inside the image as target for make rule JIMAGE_TARGET_FILE := bin/java$(EXE_SUFFIX) -JLINK_ORDER_RESOURCES := \ - *module-info.class* \ - @$(SUPPORT_OUTPUTDIR)/classlist/classlist,/java.base/java/* \ +JLINK_ORDER_RESOURCES := *module-info.class* +ifeq ($(ENABLE_GENERATE_CLASSLIST), true) + JLINK_ORDER_RESOURCES += @$(SUPPORT_OUTPUTDIR)/classlist/classlist +endif +JLINK_ORDER_RESOURCES += \ + /java.base/java/* \ /java.base/jdk/* \ /java.base/sun/* \ /java.base/com/* \ @@ -124,9 +128,10 @@ JLINK_ORDER_RESOURCES := \ # JLINK_TOOL := $(JLINK) --modulepath $(IMAGES_OUTPUTDIR)/jmods \ - --endian $(OPENJDK_BUILD_CPU_ENDIAN) \ - --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \ - --release-info $(BASE_RELEASE_FILE) + --endian $(OPENJDK_BUILD_CPU_ENDIAN) \ + --release-info $(BASE_RELEASE_FILE) \ + --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \ + # ifeq ($(JLINK_KEEP_PACKAGED_MODULES), true) JLINK_EXTRA_OPTS := --keep-packaged-modules $(JDK_IMAGE_DIR)/jmods @@ -368,19 +373,21 @@ JDK_TARGETS += $(JDK_IMAGE_DIR)/src.zip ################################################################################ # classlist -$(eval $(call SetupCopyFiles, JDK_COPY_CLASSLIST, \ - FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ - DEST := $(JDK_IMAGE_DIR)/lib, \ -)) +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) + JDK_TARGETS += $(JDK_COPY_CLASSLIST) -$(eval $(call SetupCopyFiles, JRE_COPY_CLASSLIST, \ - FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ - DEST := $(JRE_IMAGE_DIR)/lib, \ -)) + $(eval $(call SetupCopyFiles, JRE_COPY_CLASSLIST, \ + FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \ + DEST := $(JRE_IMAGE_DIR)/lib, \ + )) -JRE_TARGETS += $(JRE_COPY_CLASSLIST) + JRE_TARGETS += $(JRE_COPY_CLASSLIST) +endif ################################################################################ # /demo dir diff --git a/make/Javadoc.gmk b/make/Javadoc.gmk index d1e85b4b746..d27caaf85f1 100644 --- a/make/Javadoc.gmk +++ b/make/Javadoc.gmk @@ -44,7 +44,7 @@ include NON_CORE_PKGS.gmk # Definitions for directories # -DOCSDIR := $(IMAGES_OUTPUTDIR)/docs +DOCSDIR := $(DOCS_IMAGE_DIR) DOCSTMPDIR = $(SUPPORT_OUTPUTDIR)/docs HOTSPOT_DOCS_IMPORT_PATH=$(HOTSPOT_OUTPUTDIR)/docs @@ -1437,7 +1437,6 @@ $(DYNALINKAPI_OPTIONS_FILE): $(call OptionPair,-windowtitle,$(DYNALINKAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \ $(call OptionPair,-header,$(DYNALINKAPI_HEADER)$(DRAFT_HEADER)) ; \ $(call OptionPair,-bottom,$(DYNALINKAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \ - $(call OptionTrip,-group,$(DYNALINKAPI_GROUPNAME),$(DYNALINKAPI_REGEXP)); \ $(call OptionTrip,-linkoffline,$(DYNALINKAPI2COREAPI),$(COREAPI_DOCSDIR)/); \ ) >> $@ @@ -1634,9 +1633,7 @@ JLINK_PLUGIN_DOCTITLE := JLink Plugin API - EXPERIMENTAL JLINK_PLUGIN_WINDOWTITLE := JLink Plugin API - EXPERIMENTAL JLINK_PLUGIN_HEADER := JLink Plugin API - EXPERIMENTAL JLINK_PLUGIN_BOTTOM := $(call CommonBottom,$(JLINK_PLUGIN_FIRST_COPYRIGHT_YEAR)) -JLINK_PLUGIN_PKGS = jdk.tools.jlink \ - jdk.tools.jlink.builder \ - jdk.tools.jlink.plugin +JLINK_PLUGIN_PKGS = jdk.tools.jlink.plugin JLINK_PLUGIN_INDEX_HTML = $(JLINK_PLUGIN_DOCDIR)/index.html JLINK_PLUGIN_OPTIONS_FILE = $(DOCSTMPDIR)/jlinkplugins.options diff --git a/make/Jprt.gmk b/make/Jprt.gmk index e82b84d5e11..09d6dc7ef7b 100644 --- a/make/Jprt.gmk +++ b/make/Jprt.gmk @@ -32,14 +32,6 @@ ifneq ($(CYGPATH), ) ifdef JPRT_ARCHIVE_BUNDLE override JPRT_ARCHIVE_BUNDLE := $(shell $(CYGPATH) -u $(JPRT_ARCHIVE_BUNDLE)) endif - ifdef JPRT_ARCHIVE_INSTALL_BUNDLE - override JPRT_ARCHIVE_INSTALL_BUNDLE := \ - $(shell $(CYGPATH) -u $(JPRT_ARCHIVE_INSTALL_BUNDLE)) - endif - ifdef JPRT_ARCHIVE_MODULES_BUNDLE - override JPRT_ARCHIVE_MODULES_BUNDLE := \ - $(shell $(CYGPATH) -u $(JPRT_ARCHIVE_MODULES_BUNDLE)) - endif ifdef JPRT_ARCHIVE_TEST_BUNDLE override JPRT_ARCHIVE_TEST_BUNDLE := \ $(shell $(CYGPATH) -u $(JPRT_ARCHIVE_TEST_BUNDLE)) @@ -55,12 +47,6 @@ endif ifndef JPRT_ARCHIVE_BUNDLE JPRT_ARCHIVE_BUNDLE=/tmp/jprt_bundles/jdk-image.zip endif -ifndef JPRT_ARCHIVE_INSTALL_BUNDLE - JPRT_ARCHIVE_INSTALL_BUNDLE=/tmp/jprt_bundles/product-install.zip -endif -ifndef JPRT_ARCHIVE_MODULES_BUNDLE - JPRT_ARCHIVE_MODULES_BUNDLE=/tmp/jprt_bundles/modules.zip -endif ifndef JPRT_ARCHIVE_TEST_BUNDLE JPRT_ARCHIVE_TEST_BUNDLE=/tmp/jprt_bundles/test-image.zip endif @@ -72,94 +58,51 @@ ifeq ($(SKIP_BOOT_CYCLE), false) jprt_bundle: bootcycle-images endif -# This target must be called in the context of a SPEC file -jprt_bundle: $(JPRT_ARCHIVE_BUNDLE) $(JPRT_ARCHIVE_TEST_BUNDLE) \ - $(JPRT_ARCHIVE_MODULES_BUNDLE) +################################################################################ +# JPRT specific bundling targets +JPRT_TARGET ?= $(DEFAULT_MAKE_TARGET) +ifeq ($(JPRT_TARGET), $(DEFAULT_MAKE_TARGET)) + jprt_bundle: $(DEFAULT_MAKE_TARGET) $(JPRT_ARCHIVE_BUNDLE) \ + $(JPRT_ARCHIVE_TEST_BUNDLE) -ifeq ($(GCOV_ENABLED), true) - jprt_bundle: $(JPRT_ARCHIVE_SYMBOLS_BUNDLE) -endif + SRC_JDK_IMAGE_DIR := $(JDK_IMAGE_DIR) + SRC_TEST_IMAGE_DIR := $(TEST_IMAGE_DIR) -# This target must be called in the context of a SPEC file -$(JPRT_ARCHIVE_BUNDLE): bundles - $(MKDIR) -p $(@D) - $(RM) $@ - $(CP) $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip $@ + # This target must be called in the context of a SPEC file + $(JPRT_ARCHIVE_BUNDLE): product-images + $(call MakeDir, $(@D)) + $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -y -q -r $@ . -$(JPRT_ARCHIVE_MODULES_BUNDLE): bundles - $(MKDIR) -p $(@D) - $(RM) $@ - $(CP) $(BUILD_OUTPUT)/bundles/modules.zip $@ + $(JPRT_ARCHIVE_TEST_BUNDLE): test-image + $(call MakeDir, $(@D)) + $(CD) $(SRC_TEST_IMAGE_DIR) && $(ZIP) -y -q -r $@ . -$(JPRT_ARCHIVE_TEST_BUNDLE): bundles - $(MKDIR) -p $(@D) - $(RM) $@ - $(CP) $(BUILD_OUTPUT)/bundles/$(TEST_IMAGE_SUBDIR).zip $@ + ############################################################################## + # Optional symbols bundle + ifeq ($(GCOV_ENABLED), true) + jprt_bundle: $(JPRT_ARCHIVE_SYMBOLS_BUNDLE) + zip-bundles: $(SYMBOLS_ZIP_BUNDLE) -$(JPRT_ARCHIVE_SYMBOLS_BUNDLE): bundles - $(MKDIR) -p $(@D) - $(RM) $@ - $(CP) $(BUILD_OUTPUT)/bundles/$(SYMBOLS_IMAGE_SUBDIR).zip $@ + $(JPRT_ARCHIVE_SYMBOLS_BUNDLE): product-images + $(call MakeDir, $(@D)) + $(CD) $(SYMBOLS_IMAGE_DIR) && $(ZIP) -y -q -r $@ . -SRC_JDK_IMAGE_DIR := $(JDK_IMAGE_DIR) -SRC_JRE_IMAGE_DIR := $(JRE_IMAGE_DIR) -SRC_TEST_IMAGE_DIR := $(TEST_IMAGE_DIR) -SRC_JDK_MACOSX_BUNDLE_DIR := $(JDK_MACOSX_BUNDLE_DIR) -SRC_JRE_MACOSX_BUNDLE_DIR := $(JRE_MACOSX_BUNDLE_DIR) + endif + + ############################################################################## -# Bundle up the images -JPRT_TARGET ?= default -ifeq ($(JPRT_TARGET), default) - bundles: $(JPRT_TARGET) - @$(call TargetEnter) - $(MKDIR) -p $(BUILD_OUTPUT)/bundles - $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip . - $(CD) $(SRC_JRE_IMAGE_DIR) && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip . - $(CD) $(SRC_TEST_IMAGE_DIR) && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/$(TEST_IMAGE_SUBDIR).zip . - $(CD) $(IMAGES_OUTPUTDIR)/jmods && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/modules.zip . - if [ -d $(BUILD_OUTPUT)/install/bundles ] ; then \ - $(CD) $(BUILD_OUTPUT)/install/bundles && $(ZIP) -y -q -r \ - $(JPRT_ARCHIVE_INSTALL_BUNDLE) . ; \ - fi - if [ -d $(SYMBOLS_IMAGE_DIR) ] ; then \ - $(CD) $(SYMBOLS_IMAGE_DIR) && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/$(SYMBOLS_IMAGE_SUBDIR).zip . ; \ - fi - @$(call TargetExit) else - # Just fake the bundles - bundles: $(JPRT_TARGET) + # Just fake the main bundle to satisfy JPRT + jprt_bundle: $(JPRT_TARGET) @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles - $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip README - $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip README - $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/$(TEST_IMAGE_SUBDIR).zip README - $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ - $(BUILD_OUTPUT)/bundles/modules.zip README + $(CD) $(TOPDIR) && $(TAR) cf - README | $(GZIP) > \ + $(JPRT_ARCHIVE_BUNDLE) @$(call TargetExit) endif -# Copy images to one unified location regardless of platform etc. -final-images: $(JPRT_TARGET) - @$(call TargetEnter) - $(RM) -r $(BUILD_OUTPUT)/final-images - $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR) - $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JRE_IMAGE_SUBDIR) - $(CP) -R -P $(SRC_JDK_IMAGE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR)/ - $(CP) -R -P $(SRC_JRE_IMAGE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JRE_IMAGE_SUBDIR)/ - ifeq ($(OPENJDK_TARGET_OS),macosx) - $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_MACOSX_BUNDLE_SUBDIR) - $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JRE_MACOSX_BUNDLE_SUBDIR) - $(CP) -R -P $(SRC_JDK_MACOSX_BUNDLE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JDK_MACOSX_BUNDLE_SUBDIR)/ - $(CP) -R -P $(SRC_JRE_MACOSX_BUNDLE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JRE_MACOSX_BUNDLE_SUBDIR)/ - endif - @$(call TargetExit) +ALL_TARGETS += jprt_bundle -ALL_TARGETS += jprt_bundle bundles final-images +################################################################################ + +$(eval $(call IncludeCustomExtension, , Jprt.gmk)) diff --git a/make/MacBundles.gmk b/make/MacBundles.gmk index ea8913eded5..f860e5e074a 100644 --- a/make/MacBundles.gmk +++ b/make/MacBundles.gmk @@ -34,7 +34,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) bundles: jre-bundle jdk-bundle - # JDK_MACOSX_BUNDLE_DIR and JRE_MACOSX_BUNDLE_DIR are defined in SPEC. + # JDK_MACOSX_CONTENTS_DIR and JRE_MACOSX_CONTENTS_DIR are defined in SPEC. MACOSX_PLIST_SRC := $(JDK_TOPDIR)/make/data/bundle @@ -52,27 +52,27 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) JDK_FILE_LIST := $(shell $(FIND) $(JDK_IMAGE_DIR)) JRE_FILE_LIST := $(shell $(FIND) $(JRE_IMAGE_DIR)) - JDK_TARGET_LIST := $(subst $(JDK_IMAGE_DIR)/,$(JDK_MACOSX_BUNDLE_DIR)/Home/,$(JDK_FILE_LIST)) - JRE_TARGET_LIST := $(subst $(JRE_IMAGE_DIR)/,$(JRE_MACOSX_BUNDLE_DIR)/Home/,$(JRE_FILE_LIST)) + JDK_TARGET_LIST := $(subst $(JDK_IMAGE_DIR)/,$(JDK_MACOSX_CONTENTS_DIR)/Home/,$(JDK_FILE_LIST)) + JRE_TARGET_LIST := $(subst $(JRE_IMAGE_DIR)/,$(JRE_MACOSX_CONTENTS_DIR)/Home/,$(JRE_FILE_LIST)) # Copy empty directories (jre/lib/applet). - $(JDK_MACOSX_BUNDLE_DIR)/Home/%: $(JDK_IMAGE_DIR)/% + $(JDK_MACOSX_CONTENTS_DIR)/Home/%: $(JDK_IMAGE_DIR)/% $(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@)) $(MKDIR) -p $(@D) if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -P '$<' '$@'; fi - $(JRE_MACOSX_BUNDLE_DIR)/Home/%: $(JRE_IMAGE_DIR)/% + $(JRE_MACOSX_CONTENTS_DIR)/Home/%: $(JRE_IMAGE_DIR)/% $(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@)) $(MKDIR) -p $(@D) if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -P '$<' '$@'; fi - $(JDK_MACOSX_BUNDLE_DIR)/MacOS/libjli.dylib: + $(JDK_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib: $(call LogInfo, Creating link $(patsubst $(OUTPUT_ROOT)/%,%,$@)) $(MKDIR) -p $(@D) $(RM) $@ $(LN) -s ../Home/lib/jli/libjli.dylib $@ - $(JRE_MACOSX_BUNDLE_DIR)/MacOS/libjli.dylib: + $(JRE_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib: $(call LogInfo, Creating link $(patsubst $(OUTPUT_ROOT)/%,%,$@)) $(MKDIR) -p $(@D) $(RM) $@ @@ -80,7 +80,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) $(eval $(call SetupTextFileProcessing, BUILD_JDK_PLIST, \ SOURCE_FILES := $(MACOSX_PLIST_SRC)/JDK-Info.plist, \ - OUTPUT_FILE := $(JDK_MACOSX_BUNDLE_DIR)/Info.plist, \ + OUTPUT_FILE := $(JDK_MACOSX_CONTENTS_DIR)/Info.plist, \ REPLACEMENTS := \ @@ID@@ => $(BUNDLE_ID).jdk ; \ @@NAME@@ => $(BUNDLE_NAME) ; \ @@ -92,7 +92,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) $(eval $(call SetupTextFileProcessing, BUILD_JRE_PLIST, \ SOURCE_FILES := $(MACOSX_PLIST_SRC)/JRE-Info.plist, \ - OUTPUT_FILE := $(JRE_MACOSX_BUNDLE_DIR)/Info.plist, \ + OUTPUT_FILE := $(JRE_MACOSX_CONTENTS_DIR)/Info.plist, \ REPLACEMENTS := \ @@ID@@ => $(BUNDLE_ID).jre ; \ @@NAME@@ => $(BUNDLE_NAME) ; \ @@ -102,13 +102,13 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) @@VENDOR@@ => $(BUNDLE_VENDOR) , \ )) - jdk-bundle: $(JDK_TARGET_LIST) $(JDK_MACOSX_BUNDLE_DIR)/MacOS/libjli.dylib \ + jdk-bundle: $(JDK_TARGET_LIST) $(JDK_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib \ $(BUILD_JDK_PLIST) - $(SETFILE) -a B $(dir $(JDK_MACOSX_BUNDLE_DIR)) + $(SETFILE) -a B $(dir $(JDK_MACOSX_CONTENTS_DIR)) - jre-bundle: $(JRE_TARGET_LIST) $(JRE_MACOSX_BUNDLE_DIR)/MacOS/libjli.dylib \ + jre-bundle: $(JRE_TARGET_LIST) $(JRE_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib \ $(BUILD_JRE_PLIST) - $(SETFILE) -a B $(dir $(JRE_MACOSX_BUNDLE_DIR)) + $(SETFILE) -a B $(dir $(JRE_MACOSX_CONTENTS_DIR)) else # Not macosx diff --git a/make/Main.gmk b/make/Main.gmk index b1700f367ea..d703a266fa1 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -228,16 +228,12 @@ ALL_TARGETS += $(LAUNCHER_TARGETS) # Build hotspot target ifeq ($(BUILD_HOTSPOT),true) - hotspot: - ifeq ($(USE_NEW_HOTSPOT_BUILD), true) - +($(CD) $(HOTSPOT_TOPDIR)/makefiles && $(MAKE) $(MAKE_ARGS) -f BuildHotspot.gmk) - else - +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk) - endif +hotspot: + +($(CD) $(HOTSPOT_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f BuildHotspot.gmk) endif hotspot-ide-project: - +($(CD) $(HOTSPOT_TOPDIR)/makefiles && $(MAKE) $(MAKE_ARGS) -f ide/CreateVSProject.gmk) + +($(CD) $(HOTSPOT_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f ide/CreateVSProject.gmk) ALL_TARGETS += hotspot hotspot-ide-project @@ -306,9 +302,13 @@ $(SUPPORT_OUTPUTDIR)/source_tips: FRC BOOTCYCLE_TARGET := product-images bootcycle-images: - @$(ECHO) Boot cycle build step 2: Building a new JDK image using previously built image - +$(MAKE) -f $(SRC_ROOT)/make/Init.gmk PARALLEL_TARGETS=$(BOOTCYCLE_TARGET) \ - JOBS= SPEC=$(dir $(SPEC))bootcycle-spec.gmk main + ifneq ($(COMPILE_TYPE), cross) + $(call LogWarn, Boot cycle build step 2: Building a new JDK image using previously built image) + +$(MAKE) -f $(SRC_ROOT)/make/Init.gmk PARALLEL_TARGETS=$(BOOTCYCLE_TARGET) \ + JOBS= SPEC=$(dir $(SPEC))bootcycle-spec.gmk main + else + $(call LogWarn, Boot cycle build disabled when cross compiling) + endif zip-security: +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f ZipSecurity.gmk) @@ -373,8 +373,10 @@ ALL_TARGETS += create-buildjdk-copy create-buildjdk-interim-image interim-image: +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f InterimImage.gmk) -generate-classlist: +ifeq ($(ENABLE_GENERATE_CLASSLIST), true) + generate-classlist: +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f GenerateClasslist.gmk) +endif ALL_TARGETS += interim-image generate-classlist @@ -402,6 +404,11 @@ test-image-jdk-jtreg-native: +($(CD) $(JDK_TOPDIR)/make/test && $(MAKE) $(MAKE_ARGS) -f JtregNative.gmk \ test-image-jdk-jtreg-native) +ifeq ($(BUILD_GTEST), true) + test-image-hotspot-gtest: + +($(CD) $(HOTSPOT_TOPDIR)/make/test && $(MAKE) $(MAKE_ARGS) -f GtestImage.gmk) +endif + build-test-lib: +($(CD) $(TOPDIR)/make/test && $(MAKE) $(MAKE_ARGS) -f BuildTestLib.gmk) @@ -425,32 +432,49 @@ endif ALL_TARGETS += prepare-test-image build-test-hotspot-jtreg-native \ test-image-hotspot-jtreg-native build-test-jdk-jtreg-native \ test-image-jdk-jtreg-native build-test-lib build-test-failure-handler \ - test-failure-handler test-image-failure-handler + test-failure-handler test-image-failure-handler test-image-hotspot-gtest ################################################################################ # Run tests # Run tests specified by $(TEST), or the default test set. test: - $(call RunTests, $(TEST)) + $(call RunTests, $(TEST), $(JDK_IMAGE_DIR)) test-hotspot-jtreg: - $(call RunTests, "hotspot_all") + $(call RunTests, "hotspot_all", $(JDK_IMAGE_DIR)) test-hotspot-jtreg-native: - $(call RunTests, "hotspot_native_sanity") + $(call RunTests, "hotspot_native_sanity", $(JDK_IMAGE_DIR)) test-hotspot-internal: - $(call RunTests, "hotspot_internal") + $(call RunTests, "hotspot_internal", $(JDK_OUTPUTDIR)) + +test-hotspot-gtest: + $(call RunTests, "hotspot_gtest", $(JDK_OUTPUTDIR)) test-jdk-jtreg-native: - $(call RunTests, "jdk_native_sanity") + $(call RunTests, "jdk_native_sanity", $(JDK_IMAGE_DIR)) test-make: ($(CD) $(SRC_ROOT)/test/make && $(MAKE) $(MAKE_ARGS) -f TestMake.gmk $(TEST_TARGET)) ALL_TARGETS += test test-hotspot-jtreg test-hotspot-jtreg-native \ - test-hotspot-internal test-jdk-jtreg-native test-make + test-hotspot-internal test-hotspot-gtest test-jdk-jtreg-native test-make + +################################################################################ +# Bundles + +product-bundles: + +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Bundles.gmk product-bundles) + +test-bundles: + +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Bundles.gmk test-bundles) + +docs-bundles: + +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Bundles.gmk docs-bundles) + +ALL_TARGETS += product-bundles test-bundles docs-bundles ################################################################################ # Install targets @@ -578,7 +602,8 @@ else # When creating a BUILDJDK, we don't need to add hashes to java.base, thus # we don't need to depend on all other jmods ifneq ($(CREATING_BUILDJDK), true) - java.base-jmod: $(filter-out java.base-jmod, $(JMOD_TARGETS)) + java.base-jmod: $(filter-out java.base-jmod \ + $(addsuffix -jmod, $(call FindAllUpgradeableModules)), $(JMOD_TARGETS)) endif # Declare dependencies from -jmod to all other module targets @@ -617,18 +642,22 @@ else jrtfs-jar: interim-langtools - ifeq ($(CREATE_BUILDJDK), true) - # If creating a buildjdk, the interim image needs to be based on that. - generate-classlist: 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 - endif - generate-classlist: buildtools-jdk + 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 + 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 + endif + generate-classlist: buildtools-jdk - jimages: jmods zip-source source-tips demos samples jrtfs-jar generate-classlist + jimages: generate-classlist + endif + + jimages: jmods zip-source source-tips demos samples jrtfs-jar profiles: jmods zip-source source-tips jrtfs-jar @@ -669,12 +698,22 @@ else test-image-jdk-jtreg-native: build-test-jdk-jtreg-native + test-image-hotspot-gtest: hotspot + test-hotspot-internal: exploded-image test-hotspot-jtreg: jimages test-image + test-hotspot-gtest: exploded-image test-image-hotspot-gtest + install: product-images + product-bundles: product-images + + test-bundles: test-image + + docs-bundles: docs-image + generate-summary: jmods endif @@ -753,14 +792,18 @@ docs-image: docs-javadoc docs-jvmtidoc # This target builds the test image test-image: prepare-test-image test-image-hotspot-jtreg-native \ - test-image-jdk-jtreg-native test-image-failure-handler + test-image-jdk-jtreg-native test-image-failure-handler test-image-hotspot-gtest -# all-images is the top-most target, it builds all our deliverables ("images"). +# all-images builds all our deliverables as images. all-images: product-images test-image docs-image +# all-bundles packages all our deliverables as tar.gz bundles. +all-bundles: product-bundles test-bundles docs-bundles + ALL_TARGETS += buildtools gensrc gendata copy java rmic libs launchers jmods \ jdk.jdwp.agent-gensrc $(ALL_MODULES) demos samples exploded-image \ - create-buildjdk mac-bundles product-images docs-image test-image all-images + create-buildjdk mac-bundles product-images docs-image test-image all-images \ + all-bundles ################################################################################ @@ -771,9 +814,10 @@ default: $(DEFAULT_MAKE_TARGET) jdk: exploded-image images: product-images docs: docs-image +bundles: all-bundles all: all-images -ALL_TARGETS += default jdk images docs all +ALL_TARGETS += default jdk images docs bundles all ################################################################################ ################################################################################ diff --git a/make/MainSupport.gmk b/make/MainSupport.gmk index d09331a0962..7683cfeb2af 100644 --- a/make/MainSupport.gmk +++ b/make/MainSupport.gmk @@ -30,10 +30,10 @@ ifndef _MAINSUPPORT_GMK _MAINSUPPORT_GMK := 1 -# Run the tests specified by $1. +# Run the tests specified by $1, with PRODUCT_HOME specified by $2 define RunTests ($(CD) $(SRC_ROOT)/test && $(MAKE) $(MAKE_ARGS) -j1 -k MAKEFLAGS= \ - JT_HOME=$(JT_HOME) PRODUCT_HOME=$(JDK_IMAGE_DIR) \ + JT_HOME=$(JT_HOME) PRODUCT_HOME=$(strip $2) \ TEST_IMAGE_DIR=$(TEST_IMAGE_DIR) \ ALT_OUTPUTDIR=$(OUTPUT_ROOT) TEST_JOBS=$(TEST_JOBS) \ JOBS=$(JOBS) $1) || true diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 1a33d69f3bb..3665297d036 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -145,7 +145,7 @@ ifeq ($(HAS_FILE_FUNCTION), true) $$(strip $2),$$(subst $$(SPACE),$$(NEWLINE),$$(strip $$($$(strip $1))))) endef -else # HAS_FILE_FUNCTION +else # HAS_FILE_FUNCTION = false $(eval compress_paths = \ $(strip $(shell $(CAT) $(SRC_ROOT)/make/common/support/ListPathsSafely-pre-compress.incl))) @@ -172,8 +172,8 @@ else # HAS_FILE_FUNCTION # Param 2 - File to print to # Param 3 - Set to true to append to file instead of overwriting define ListPathsSafely - ifneq (,$$(word 10001,$$($1))) - $$(error Cannot list safely more than 10000 paths. $1 has $$(words $$($1)) paths!) + ifneq (,$$(word 30001,$$($$(strip $1)))) + $$(error Cannot list safely more than 30000 paths. $1 has $$(words $$($$(strip $1))) paths!) endif $$(call MakeDir, $$(dir $2)) ifneq ($$(strip $3), true) @@ -229,6 +229,106 @@ else # HAS_FILE_FUNCTION $$(call ListPathsSafely_IfPrintf,$1,$2,9251,9500) $$(call ListPathsSafely_IfPrintf,$1,$2,9501,9750) $$(call ListPathsSafely_IfPrintf,$1,$2,9751,10000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,10001,10250) + $$(call ListPathsSafely_IfPrintf,$1,$2,10251,10500) + $$(call ListPathsSafely_IfPrintf,$1,$2,10501,10750) + $$(call ListPathsSafely_IfPrintf,$1,$2,10751,11000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,11001,11250) + $$(call ListPathsSafely_IfPrintf,$1,$2,11251,11500) + $$(call ListPathsSafely_IfPrintf,$1,$2,11501,11750) + $$(call ListPathsSafely_IfPrintf,$1,$2,11751,12000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,12001,12250) + $$(call ListPathsSafely_IfPrintf,$1,$2,12251,12500) + $$(call ListPathsSafely_IfPrintf,$1,$2,12501,12750) + $$(call ListPathsSafely_IfPrintf,$1,$2,12751,13000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,13001,13250) + $$(call ListPathsSafely_IfPrintf,$1,$2,13251,13500) + $$(call ListPathsSafely_IfPrintf,$1,$2,13501,13750) + $$(call ListPathsSafely_IfPrintf,$1,$2,13751,14000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,14001,14250) + $$(call ListPathsSafely_IfPrintf,$1,$2,14251,14500) + $$(call ListPathsSafely_IfPrintf,$1,$2,14501,14750) + $$(call ListPathsSafely_IfPrintf,$1,$2,14751,15000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,15001,15250) + $$(call ListPathsSafely_IfPrintf,$1,$2,15251,15500) + $$(call ListPathsSafely_IfPrintf,$1,$2,15501,15750) + $$(call ListPathsSafely_IfPrintf,$1,$2,15751,16000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,16001,16250) + $$(call ListPathsSafely_IfPrintf,$1,$2,16251,16500) + $$(call ListPathsSafely_IfPrintf,$1,$2,16501,16750) + $$(call ListPathsSafely_IfPrintf,$1,$2,16751,17000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,17001,17250) + $$(call ListPathsSafely_IfPrintf,$1,$2,17251,17500) + $$(call ListPathsSafely_IfPrintf,$1,$2,17501,17750) + $$(call ListPathsSafely_IfPrintf,$1,$2,17751,18000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,18001,18250) + $$(call ListPathsSafely_IfPrintf,$1,$2,18251,18500) + $$(call ListPathsSafely_IfPrintf,$1,$2,18501,18750) + $$(call ListPathsSafely_IfPrintf,$1,$2,18751,19000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,19001,19250) + $$(call ListPathsSafely_IfPrintf,$1,$2,19251,19500) + $$(call ListPathsSafely_IfPrintf,$1,$2,19501,19750) + $$(call ListPathsSafely_IfPrintf,$1,$2,19751,20000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,20001,20250) + $$(call ListPathsSafely_IfPrintf,$1,$2,20251,20500) + $$(call ListPathsSafely_IfPrintf,$1,$2,20501,20750) + $$(call ListPathsSafely_IfPrintf,$1,$2,20751,21000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,21001,21250) + $$(call ListPathsSafely_IfPrintf,$1,$2,21251,21500) + $$(call ListPathsSafely_IfPrintf,$1,$2,21501,21750) + $$(call ListPathsSafely_IfPrintf,$1,$2,21751,22000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,22001,22250) + $$(call ListPathsSafely_IfPrintf,$1,$2,22251,22500) + $$(call ListPathsSafely_IfPrintf,$1,$2,22501,22750) + $$(call ListPathsSafely_IfPrintf,$1,$2,22751,23000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,23001,23250) + $$(call ListPathsSafely_IfPrintf,$1,$2,23251,23500) + $$(call ListPathsSafely_IfPrintf,$1,$2,23501,23750) + $$(call ListPathsSafely_IfPrintf,$1,$2,23751,24000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,24001,24250) + $$(call ListPathsSafely_IfPrintf,$1,$2,24251,24500) + $$(call ListPathsSafely_IfPrintf,$1,$2,24501,24750) + $$(call ListPathsSafely_IfPrintf,$1,$2,24751,25000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,25001,25250) + $$(call ListPathsSafely_IfPrintf,$1,$2,25251,25500) + $$(call ListPathsSafely_IfPrintf,$1,$2,25501,25750) + $$(call ListPathsSafely_IfPrintf,$1,$2,25751,26000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,26001,26250) + $$(call ListPathsSafely_IfPrintf,$1,$2,26251,26500) + $$(call ListPathsSafely_IfPrintf,$1,$2,26501,26750) + $$(call ListPathsSafely_IfPrintf,$1,$2,26751,27000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,27001,27250) + $$(call ListPathsSafely_IfPrintf,$1,$2,27251,27500) + $$(call ListPathsSafely_IfPrintf,$1,$2,27501,27750) + $$(call ListPathsSafely_IfPrintf,$1,$2,27751,28000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,28001,28250) + $$(call ListPathsSafely_IfPrintf,$1,$2,28251,28500) + $$(call ListPathsSafely_IfPrintf,$1,$2,28501,28750) + $$(call ListPathsSafely_IfPrintf,$1,$2,28751,29000) + + $$(call ListPathsSafely_IfPrintf,$1,$2,29001,29250) + $$(call ListPathsSafely_IfPrintf,$1,$2,29251,29500) + $$(call ListPathsSafely_IfPrintf,$1,$2,29501,29750) + $$(call ListPathsSafely_IfPrintf,$1,$2,29751,30000) endef endif # HAS_FILE_FUNCTION @@ -420,8 +520,12 @@ else ifeq ($(OPENJDK_TARGET_OS),macosx) # set. Some files get their write permissions removed after being copied to the # output dir. When these are copied again to images, xattr would fail. By only clearing # attributes when they are present, failing on this is avoided. + # + # If copying a soft link to a directory, need to delete the target first to avoid + # weird errors. define install-file $(MKDIR) -p '$(@D)' + $(RM) '$@' $(CP) -fRP '$<' '$@' if [ -n "`$(XATTR) -l '$@'`" ]; then $(XATTR) -c '$@'; fi endef diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index ba1f82e5d5b..90469d073fd 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -72,7 +72,6 @@ BOOT_MODULES += \ # to be deprivileged BOOT_MODULES += \ - java.scripting \ java.sql.rowset \ java.smartcardio \ jdk.naming.rmi \ @@ -87,6 +86,10 @@ UPGRADEABLE_MODULES += \ java.xml.ws \ # +# Modules explicitly declared as not being upgradeable even though they require +# an upgradeable module. +NON_UPGRADEABLE_MODULES += + AGGREGATOR_MODULES += \ java.compact1 \ java.compact2 \ @@ -102,6 +105,7 @@ PLATFORM_MODULES += \ PLATFORM_MODULES += \ java.compiler \ + java.scripting \ jdk.accessibility \ jdk.charsets \ jdk.crypto.ec \ @@ -245,6 +249,19 @@ FindTransitiveDepsForModule = \ $(foreach n, $(call FindDepsForModule, $m), \ $(call FindDepsForModule, $n)))) +# Upgradeable modules are those that are either defined as upgradeable or that +# require an upradeable module. +FindAllUpgradeableModules = \ + $(filter-out $(MODULES_FILTER) $(NON_UPGRADEABLE_MODULES), \ + $(sort $(UPGRADEABLE_MODULES) $(foreach m, \ + $(filter-out $(UPGRADEABLE_MODULES), $(call FindAllModules)), \ + $(if $(filter $(UPGRADEABLE_MODULES), \ + $(call FindTransitiveDepsForModule, $m)), \ + $m \ + ) \ + )) \ + ) + ################################################################################ # Param 1 - Name of module diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index db09eb5bbf3..cb2f96e0ddf 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -372,6 +372,9 @@ endef # toolchain when compiling C++ code # STRIP_SYMBOLS Set to true to strip the final binary if the toolchain allows for it # DEBUG_SYMBOLS Set to false to disable generation of debug symbols +# COPY_DEBUG_SYMBOLS Set to false to override global setting of debug symbol copying +# ZIP_EXTERNAL_DEBUG_SYMBOLS Set to false to override global setting of debug symbol +# zipping # CFLAGS_DEBUG_SYMBOLS Overrides the default cflags for enabling debug symbols # CXXFLAGS_DEBUG_SYMBOLS Overrides the default cxxflags for enabling debug symbols # STRIPFLAGS Optionally change the flags given to the strip command @@ -814,7 +817,15 @@ define SetupNativeCompilationBody # Need to make sure TARGET is first on list $1 := $$($1_TARGET) - ifeq ($(COPY_DEBUG_SYMBOLS), true) + ifneq ($$($1_COPY_DEBUG_SYMBOLS), false) + $1_COPY_DEBUG_SYMBOLS := $(COPY_DEBUG_SYMBOLS) + endif + + ifneq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), false) + $1_ZIP_EXTERNAL_DEBUG_SYMBOLS := $(ZIP_EXTERNAL_DEBUG_SYMBOLS) + endif + + ifeq ($$($1_COPY_DEBUG_SYMBOLS), true) ifneq ($$($1_DEBUG_SYMBOLS), false) # Only copy debug symbols for dynamic libraries and programs. ifeq ($$($1_STATIC_LIBRARY), ) @@ -861,7 +872,7 @@ define SetupNativeCompilationBody $$($1_TARGET): $$($1_DEBUGINFO_FILES) $$($1_DEBUGINFO_FILES): $$($1_ALL_OBJS) - ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true) + ifeq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), true) $1_DEBUGINFO_ZIP := $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).diz $1 += $$(subst $$($1_OBJECT_DIR),$$($1_OUTPUT_DIR),$$($1_DEBUGINFO_ZIP)) diff --git a/make/idea/idea.gmk b/make/idea/idea.gmk index 329c01cd5ea..299ffe805bc 100644 --- a/make/idea/idea.gmk +++ b/make/idea/idea.gmk @@ -35,5 +35,6 @@ else #with SPEC $(ECHO) "BOOT_JDK=\"$(BOOT_JDK)\"" >> $(OUT) $(ECHO) "CYGPATH=\"$(CYGPATH)\"" >> $(OUT) $(ECHO) "SPEC=\"$(SPEC)\"" >> $(OUT) + $(ECHO) "JT_HOME=\"$(JT_HOME)\"" >> $(OUT) endif diff --git a/make/idea/template/ant.xml b/make/idea/template/ant.xml index 6e72e478cbc..f5274deb5bb 100644 --- a/make/idea/template/ant.xml +++ b/make/idea/template/ant.xml @@ -5,9 +5,8 @@ - + - diff --git a/make/idea/template/build.xml b/make/idea/template/build.xml index ed62f296726..b10490f77f1 100644 --- a/make/idea/template/build.xml +++ b/make/idea/template/build.xml @@ -16,6 +16,10 @@ + + + + @@ -29,26 +33,6 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/make/idea/template/src/idea/JdkIdeaAntLogger.java b/make/idea/template/src/idea/JdkIdeaAntLogger.java index 9913499e7a0..22d42a93805 100644 --- a/make/idea/template/src/idea/JdkIdeaAntLogger.java +++ b/make/idea/template/src/idea/JdkIdeaAntLogger.java @@ -99,7 +99,9 @@ public final class JdkIdeaAntLogger extends DefaultLogger { /** jtreg test failure */ JTREG_TEST_FAILED(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "FAILED: "), /** jtreg test error */ - JTREG_TEST_ERROR(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "Error: "); + JTREG_TEST_ERROR(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "Error: "), + /** jtreg report */ + JTREG_TEST_REPORT(StringBinaryPredicate.STARTS_WITH, MSG_INFO, "Report written"); StringBinaryPredicate sbp; int priority; @@ -132,7 +134,7 @@ public final class JdkIdeaAntLogger extends DefaultLogger { MAKE("exec", MessageKind.MAKE_ERROR, MessageKind.MAKE_WARNING, MessageKind.MAKE_NOTE, MessageKind.MAKE_OTHER, MessageKind.JAVAC_CRASH), /** jtreg task - invoked during test execution */ - JTREG("jtreg", MessageKind.JTREG_TEST_PASSED, MessageKind.JTREG_TEST_FAILED, MessageKind.JTREG_TEST_ERROR), + JTREG("jtreg", MessageKind.JTREG_TEST_PASSED, MessageKind.JTREG_TEST_FAILED, MessageKind.JTREG_TEST_ERROR, MessageKind.JTREG_TEST_REPORT), /** initial synthetic task when the logger is created */ ROOT("") { @Override diff --git a/make/idea/template/workspace.xml b/make/idea/template/workspace.xml index 2423c3d41fb..e6377dd53a2 100644 --- a/make/idea/template/workspace.xml +++ b/make/idea/template/workspace.xml @@ -8,6 +8,14 @@ + + + + + + +