diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml index 0b2888ca6e0..f8e7306a8c0 100644 --- a/.github/workflows/build-cross-compile.yml +++ b/.github/workflows/build-cross-compile.yml @@ -60,33 +60,33 @@ jobs: gnu-arch: aarch64 debian-arch: arm64 debian-repository: https://httpredir.debian.org/debian/ - debian-version: bookworm + debian-version: trixie tolerate-sysroot-errors: false - target-cpu: arm gnu-arch: arm debian-arch: armhf debian-repository: https://httpredir.debian.org/debian/ - debian-version: bookworm + debian-version: trixie tolerate-sysroot-errors: false gnu-abi: eabihf - target-cpu: s390x gnu-arch: s390x debian-arch: s390x debian-repository: https://httpredir.debian.org/debian/ - debian-version: bookworm + debian-version: trixie tolerate-sysroot-errors: false - target-cpu: ppc64le gnu-arch: powerpc64le debian-arch: ppc64el debian-repository: https://httpredir.debian.org/debian/ - debian-version: bookworm + debian-version: trixie tolerate-sysroot-errors: false - target-cpu: riscv64 gnu-arch: riscv64 debian-arch: riscv64 debian-repository: https://httpredir.debian.org/debian/ - debian-version: sid - tolerate-sysroot-errors: true + debian-version: trixie + tolerate-sysroot-errors: false steps: - name: 'Checkout the JDK source' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 14de10b1031..f2d1d01f905 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -237,8 +237,8 @@ jobs: uses: ./.github/workflows/build-macos.yml with: platform: macos-x64 - runs-on: 'macos-13' - xcode-toolset-version: '14.3.1' + runs-on: 'macos-15-intel' + xcode-toolset-version: '16.4' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} if: needs.prepare.outputs.macos-x64 == 'true' @@ -249,8 +249,8 @@ jobs: uses: ./.github/workflows/build-macos.yml with: platform: macos-aarch64 - runs-on: 'macos-14' - xcode-toolset-version: '15.4' + runs-on: 'macos-15' + xcode-toolset-version: '16.4' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} if: needs.prepare.outputs.macos-aarch64 == 'true' @@ -311,17 +311,6 @@ jobs: bootjdk-platform: linux-x64 runs-on: ubuntu-22.04 - test-macos-x64: - name: macos-x64 - needs: - - build-macos-x64 - uses: ./.github/workflows/test.yml - with: - platform: macos-x64 - bootjdk-platform: macos-x64 - runs-on: macos-13 - xcode-toolset-version: '14.3.1' - test-macos-aarch64: name: macos-aarch64 needs: @@ -330,8 +319,8 @@ jobs: with: platform: macos-aarch64 bootjdk-platform: macos-aarch64 - runs-on: macos-14 - xcode-toolset-version: '15.4' + runs-on: macos-15 + xcode-toolset-version: '16.4' test-windows-x64: name: windows-x64 diff --git a/.jcheck/conf b/.jcheck/conf index 35de7d4d946..d89c28169f4 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=21.0.9 +version=21.0.10 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff --git a/doc/building.html b/doc/building.html index 5295c0e6451..26720dd5b39 100644 --- a/doc/building.html +++ b/doc/building.html @@ -476,7 +476,7 @@

Linux

The basic tooling is provided as part of the core operating system, but you will most likely need to install developer packages.

For apt-based distributions (Debian, Ubuntu, etc), try this:

-
sudo apt-get install build-essential
+
sudo apt-get install build-essential autoconf

For rpm-based distributions (Fedora, Red Hat, etc), try this:

sudo yum groupinstall "Development Tools"

For Alpine Linux, aside from basic tooling, install the GNU versions @@ -539,7 +539,7 @@

Native Compiler Linux -gcc 11.2.0 +gcc 13.2.0 macOS @@ -560,7 +560,7 @@

gcc

generate a warning by configure and are unlikely to work.

The JDK is currently known to be able to compile with at least -version 11.2 of gcc.

+version 13.2 of gcc.

In general, any version between these two should be usable.

clang

The minimum accepted version of clang is 3.5. Older versions will not diff --git a/doc/building.md b/doc/building.md index 36bf32945a8..addc74aae51 100644 --- a/doc/building.md +++ b/doc/building.md @@ -289,7 +289,7 @@ will most likely need to install developer packages. For apt-based distributions (Debian, Ubuntu, etc), try this: ``` -sudo apt-get install build-essential +sudo apt-get install build-essential autoconf ``` For rpm-based distributions (Fedora, Red Hat, etc), try this: @@ -336,7 +336,7 @@ issues. | Operating system | Toolchain version | | ------------------ | ------------------------------------------ | -| Linux | gcc 11.2.0 | +| Linux | gcc 13.2.0 | | macOS | Apple Xcode 10.1 (using clang 10.0.0) | | Windows | Microsoft Visual Studio 2022 update 17.1.0 | @@ -350,7 +350,7 @@ features that it does support. The minimum accepted version of gcc is 5.0. Older versions will generate a warning by `configure` and are unlikely to work. -The JDK is currently known to be able to compile with at least version 11.2 of +The JDK is currently known to be able to compile with at least version 13.2 of gcc. In general, any version between these two should be usable. diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 8c6e0f1924f..b490f9f7748 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -1077,7 +1077,7 @@ UseSpecialTestHandler = \ # Now process each test to run and setup a proper make rule $(foreach test, $(TESTS_TO_RUN), \ $(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \ - $(TR) -cs '[a-z][A-Z][0-9]\n' '[_*1000]')) \ + $(TR) -cs '[a-z][A-Z][0-9]\n' '_')) \ $(eval ALL_TEST_IDS += $(TEST_ID)) \ $(if $(call UseCustomTestHandler, $(test)), \ $(eval $(call SetupRunCustomTest, $(TEST_ID), \ @@ -1157,9 +1157,9 @@ run-test-report: post-run-test TEST TOTAL PASS FAIL ERROR " " $(foreach test, $(TESTS_TO_RUN), \ $(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \ - $(TR) -cs '[a-z][A-Z][0-9]\n' '[_*1000]')) \ + $(TR) -cs '[a-z][A-Z][0-9]\n' '_')) \ $(ECHO) >> $(TEST_LAST_IDS) $(TEST_ID) $(NEWLINE) \ - $(eval NAME_PATTERN := $(shell $(ECHO) $(test) | $(TR) -c '\n' '[_*1000]')) \ + $(eval NAME_PATTERN := $(shell $(ECHO) $(test) | $(TR) -c '\n' '_')) \ $(if $(filter __________________________________________________%, $(NAME_PATTERN)), \ $(eval TEST_NAME := ) \ $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s\n" " " "$(test)" $(NEWLINE) \ diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index f7e9844a643..44f0c15f15d 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -223,6 +223,9 @@ JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER # LeakSanitizer JDKOPT_SETUP_LEAK_SANITIZER +# Setup static analyzer +JDKOPT_SETUP_STATIC_ANALYZER + # Fallback linker # This needs to go before 'LIB_DETERMINE_DEPENDENCIES' JDKOPT_SETUP_FALLBACK_LINKER diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 9b022792e15..ab8c48e16d4 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -625,8 +625,8 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], TOOLCHAIN_CFLAGS_JVM="-qtbtable=full -qtune=balanced -fno-exceptions \ -qalias=noansi -qstrict -qtls=default -qnortti -qnoeh -qignerrno -qstackprotect" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - TOOLCHAIN_CFLAGS_JVM="-nologo -MD -Zc:preprocessor -Zc:strictStrings -MP" - TOOLCHAIN_CFLAGS_JDK="-nologo -MD -Zc:preprocessor -Zc:strictStrings -Zc:wchar_t-" + TOOLCHAIN_CFLAGS_JVM="-nologo -MD -Zc:preprocessor -Zc:throwingNew -permissive- -MP" + TOOLCHAIN_CFLAGS_JDK="-nologo -MD -Zc:preprocessor -Zc:throwingNew -permissive- -Zc:wchar_t-" fi # CFLAGS C language level for JDK sources (hotspot only uses C++) diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index a9863c501a0..77cba5f2ac5 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -462,6 +462,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER], ############################################################################### # +# Static analyzer +# +AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_ANALYZER], +[ + UTIL_ARG_ENABLE(NAME: static-analyzer, DEFAULT: false, RESULT: STATIC_ANALYZER_ENABLED, + DESC: [enable the GCC static analyzer], + CHECK_AVAILABLE: [ + AC_MSG_CHECKING([if static analyzer is available]) + if test "x$TOOLCHAIN_TYPE" = "xgcc"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AVAILABLE=false + fi + ], + IF_ENABLED: [ + STATIC_ANALYZER_CFLAGS="-fanalyzer -Wno-analyzer-fd-leak" + CFLAGS_JDKLIB="$CFLAGS_JDKLIB $STATIC_ANALYZER_CFLAGS" + CFLAGS_JDKEXE="$CFLAGS_JDKEXE $STATIC_ANALYZER_CFLAGS" + ]) + AC_SUBST(STATIC_ANALYZER_ENABLED) +]) + +################################################################################ +# # LeakSanitizer # AC_DEFUN_ONCE([JDKOPT_SETUP_LEAK_SANITIZER], diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 91ed780e555..886b6ce0418 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1080,10 +1080,10 @@ var getJibProfilesProfiles = function (input, common, data) { var getJibProfilesDependencies = function (input, common) { var devkit_platform_revisions = { - linux_x64: "gcc11.2.0-OL6.4+1.0", + linux_x64: "gcc13.2.0-OL6.4+1.0", macosx: "Xcode12.4+1.1", windows_x64: "VS2022-17.1.0+1.1", - linux_aarch64: input.build_cpu == "x64" ? "gcc11.2.0-OL7.6+1.1" : "gcc11.2.0-OL7.6+1.0", + linux_aarch64: "gcc13.2.0-OL7.6+1.0", linux_arm: "gcc8.2.0-Fedora27+1.0", linux_ppc64le: "gcc8.2.0-Fedora27+1.0", linux_s390x: "gcc8.2.0-Fedora27+1.0", diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 107d9b9b6b4..4bfa1e358d3 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -28,15 +28,15 @@ DEFAULT_VERSION_FEATURE=21 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=9 +DEFAULT_VERSION_UPDATE=10 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2025-10-21 +DEFAULT_VERSION_DATE=2026-01-20 DEFAULT_VERSION_CLASSFILE_MAJOR=65 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="20 21" DEFAULT_JDK_SOURCE_TARGET_VERSION=21 -DEFAULT_PROMOTED_VERSION_PRE= +DEFAULT_PROMOTED_VERSION_PRE=ea diff --git a/make/data/asan/asan_default_options.c b/make/data/asan/asan_default_options.c index 9e0887c5f67..70821045176 100644 --- a/make/data/asan/asan_default_options.c +++ b/make/data/asan/asan_default_options.c @@ -67,6 +67,8 @@ ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* CDECL __asan_default_opt #endif "print_suppressions=0," "handle_segv=0," + // A lot of libjsig related tests fail because of the link order check; so better avoid it + "verify_asan_link_order=0," // See https://github.com/google/sanitizers/issues/1322. Hopefully this is resolved // at some point and we can remove this option. "intercept_tls_get_addr=0"; diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index 187320ca26e..5c29ee4db75 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -55,11 +55,11 @@ KERNEL_HEADERS_RPM := kernel-headers ifeq ($(BASE_OS), OL) ifeq ($(ARCH), aarch64) - BASE_URL := http://yum.oracle.com/repo/OracleLinux/OL7/6/base/$(ARCH)/ + BASE_URL := https://yum.oracle.com/repo/OracleLinux/OL7/6/base/$(ARCH)/ LINUX_VERSION := OL7.6 KERNEL_HEADERS_RPM := kernel-uek-headers else - BASE_URL := http://yum.oracle.com/repo/OracleLinux/OL6/4/base/$(ARCH)/ + BASE_URL := https://yum.oracle.com/repo/OracleLinux/OL6/4/base/$(ARCH)/ LINUX_VERSION := OL6.4 endif else ifeq ($(BASE_OS), Fedora) @@ -96,8 +96,17 @@ endif # Define external dependencies # Latest that could be made to work. -GCC_VER := 11.3.0 -ifeq ($(GCC_VER), 11.3.0) +GCC_VER := 13.2.0 +ifeq ($(GCC_VER), 13.2.0) + gcc_ver := gcc-13.2.0 + binutils_ver := binutils-2.41 + ccache_ver := ccache-3.7.12 + mpfr_ver := mpfr-4.2.0 + gmp_ver := gmp-6.3.0 + mpc_ver := mpc-1.3.1 + gdb_ver := gdb-13.2 + REQUIRED_MIN_MAKE_MAJOR_VERSION := 4 +else ifeq ($(GCC_VER), 11.3.0) gcc_ver := gcc-11.3.0 binutils_ver := binutils-2.39 ccache_ver := ccache-3.7.12 @@ -671,7 +680,11 @@ $(PREFIX)/Tools.gmk: ./Tools.gmk rm -rf $@ cp $< $@ -THESE_MAKEFILES := $(PREFIX)/Makefile $(PREFIX)/Tools.gmk +$(PREFIX)/Tars.gmk: ./Tars.gmk + rm -rf $@ + cp $< $@ + +THESE_MAKEFILES := $(PREFIX)/Makefile $(PREFIX)/Tools.gmk $(PREFIX)/Tars.gmk ########################################################################################## diff --git a/make/ide/netbeans/langtools/build.xml b/make/ide/netbeans/langtools/build.xml index b23614649b8..f417b256eb6 100644 --- a/make/ide/netbeans/langtools/build.xml +++ b/make/ide/netbeans/langtools/build.xml @@ -1,6 +1,6 @@ - - - - High resolution custom cursor test, bug ID 8028212 - - - -

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

- - diff --git a/test/jdk/java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.java b/test/jdk/java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.java deleted file mode 100644 index 6821f9c55e6..00000000000 --- a/test/jdk/java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Dialog; -import java.awt.Frame; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Label; -import java.awt.Point; -import java.awt.TextArea; -import java.awt.Toolkit; -import java.awt.image.BaseMultiResolutionImage; -import java.awt.image.BufferedImage; -import javax.swing.JApplet; - -import jdk.test.lib.Platform; - -/** - * @test - * @bug 8028212 - * @summary [macosx] Custom Cursor HiDPI support - * @author Alexander Scherbatiy - * @library /test/lib - * @modules java.desktop/sun.awt.image - * @build jdk.test.lib.Platform - * @run applet/manual=yesno MultiResolutionCursorTest.html - */ -public class MultiResolutionCursorTest extends JApplet { - //Declare things used in the test, like buttons and labels here - - static final int sizes[] = {8, 16, 32, 128}; - static final Color colors[] = {Color.WHITE, Color.RED, Color.GREEN, Color.BLUE}; - - public void init() { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - this.setLayout(new BorderLayout()); - - if (Platform.isOSX()) { - String[] instructions = { - "Verify that high resolution custom cursor is used" - + " on HiDPI displays.", - "1) Run the test on Retina display or enable the Quartz Debug" - + " and select the screen resolution with (HiDPI) label", - "2) Move the cursor to the Test Frame", - "3) Check that cursor has red, green or blue color", - "If so, press PASS, else press FAIL." - }; - Sysout.createDialogWithInstructions(instructions); - - } else { - String[] instructions = { - "This test is not applicable to the current platform. Press PASS." - }; - Sysout.createDialogWithInstructions(instructions); - } - }//End init() - - public void start() { - //Get things going. Request focus, set size, et cetera - setSize(200, 200); - setVisible(true); - validate(); - - final Image image = new BaseMultiResolutionImage( - createResolutionVariant(0), - createResolutionVariant(1), - createResolutionVariant(2), - createResolutionVariant(3) - ); - - int center = sizes[0] / 2; - Cursor cursor = Toolkit.getDefaultToolkit().createCustomCursor( - image, new Point(center, center), "multi-resolution cursor"); - - Frame frame = new Frame("Test Frame"); - frame.setSize(300, 300); - frame.setLocation(300, 50); - frame.add(new Label("Move cursor here")); - frame.setCursor(cursor); - frame.setVisible(true); - }// start() - - static BufferedImage createResolutionVariant(int i) { - BufferedImage resolutionVariant = new BufferedImage(sizes[i], sizes[i], - BufferedImage.TYPE_INT_RGB); - Graphics2D g2 = resolutionVariant.createGraphics(); - g2.setColor(colors[i]); - g2.fillRect(0, 0, sizes[i], sizes[i]); - g2.dispose(); - return resolutionVariant; - } -}// class BlockedWindowTest - -/* 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. - */ -class Sysout { - - private static TestDialog dialog; - - 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."); - } - - 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."); - } - - public static void printInstructions(String[] instructions) { - dialog.printInstructions(instructions); - } - - public static void println(String messageIn) { - dialog.displayMessage(messageIn); - } -}// Sysout class - -/** - * This is part of the standard test machinery. It provides a place for the test - * instructions to be displayed, and a place for interactive messages to the - * user to be displayed. To have the test instructions displayed, see Sysout. To - * have a message to the user be displayed, see Sysout. Do not call anything in - * this dialog directly. - */ -class TestDialog extends Dialog { - - 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); - } -}// Te diff --git a/test/jdk/java/awt/DesktopProperties/FontSmoothing.java b/test/jdk/java/awt/DesktopProperties/FontSmoothing.java new file mode 100644 index 00000000000..d3879d4893f --- /dev/null +++ b/test/jdk/java/awt/DesktopProperties/FontSmoothing.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Frame; +import java.awt.Toolkit; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/* + * @test + * @bug 4808569 + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary add desktop property for the Windows XP or later font smoothing settings + * @run main/manual FontSmoothing + */ + +public class FontSmoothing { + + private static final String PROP_NAME = "win.text.fontSmoothingType"; + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + This test should be run on Windows XP or later. + + On Windows 11: + 1. Open Run dialog by typing 'run' in search bar. + 2. Type 'cttune' and press Ok. + 3. Uncheck the "Turn On ClearType" checkbox and follow next instructions on screen. + 4. Repeat Step 1-2. + 5. Check the "Turn On ClearType" checkbox and follow next instructions on screen. + 6. Take a look at the output window to determine if the test passed or failed. + """; + + PassFailJFrame.builder() + .title("FontSmoothing Test Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(40) + .testTimeOut(5) + .testUI(FontSmoothing::createUI) + .logArea(8) + .build() + .awaitAndCheck(); + } + + private static Frame createUI() { + Frame f = new Frame("FontSmoothing Test"); + f.setSize(50, 50); + + Object value = Toolkit.getDefaultToolkit().getDesktopProperty(PROP_NAME); + PassFailJFrame.log("toolkit.getDesktopProperty: " + PROP_NAME + " = " + value + "\n"); + + Toolkit.getDefaultToolkit().addPropertyChangeListener(PROP_NAME, new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + PassFailJFrame.log("PropertyChangeEvent: " + e.getPropertyName() + + "\n old value=" + e.getOldValue() + + "\n new value=" + e.getNewValue()); + + Integer value = (Integer) Toolkit.getDefaultToolkit().getDesktopProperty(PROP_NAME); + PassFailJFrame.log("toolkit.getDesktopProperty:" + PROP_NAME + "=" + value); + + if (value.equals((Integer) e.getNewValue())) { + PassFailJFrame.log("test PASSED"); + } else { + PassFailJFrame.log("test FAILED"); + } + } + }); + return f; + } +} diff --git a/test/jdk/java/awt/DesktopProperties/ThreeDBackgroundColor.java b/test/jdk/java/awt/DesktopProperties/ThreeDBackgroundColor.java new file mode 100644 index 00000000000..26792e79a92 --- /dev/null +++ b/test/jdk/java/awt/DesktopProperties/ThreeDBackgroundColor.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Frame; +import java.awt.Toolkit; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/* + * @test + * @bug 4368193 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @requires (os.family == "windows") + * @summary Toolkit's getDesktopProperty returns stale values on Microsoft Windows + * @run main/manual ThreeDBackgroundColor + */ + +public class ThreeDBackgroundColor { + + private static final String PROP_NAME = "win.3d.backgroundColor"; + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + On Windows 10: + 1. Open Windows Settings, in the search bar type + 'high contrast', in the list of suggestions choose option + 'Turn high contrast on or off' + 2. In the High contrast control panel click on the on/off switch + to initialize High contrast mode + 3. Wait for the High contrast mode to finish initialization + 4. Click on the same switch again to turn off High contrast mode + + On Windows 11: + 1. Open Windows settings, in the search bar type + 'Contrast Theme'. + 2. Select any value from 'Contrast themes' dropdown menu and press 'Apply'. + 3. Wait for the High contrast mode to finish initialization + 4. Select 'None' from 'Contrast themes' dropdown menu to revert the changes. + + Take a look at the output window to determine if the test passed or failed."""; + + PassFailJFrame.builder() + .title("ThreeDBackgroundColor Test Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(40) + .testTimeOut(5) + .testUI(ThreeDBackgroundColor::createUI) + .logArea(8) + .build() + .awaitAndCheck(); + } + + private static Frame createUI() { + Frame f = new Frame("ThreeDBackgroundColor Test"); + f.setSize(50, 50); + + Object value = Toolkit.getDefaultToolkit().getDesktopProperty(PROP_NAME); + PassFailJFrame.log("toolkit.getDesktopProperty:" + PROP_NAME + "=" + value); + + Toolkit.getDefaultToolkit().addPropertyChangeListener(PROP_NAME, new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + PassFailJFrame.log("PropertyChangeEvent: " + e.getPropertyName() + + "\n old value=" + e.getOldValue() + + "\n new value=" + e.getNewValue()); + + Color value = (Color) Toolkit.getDefaultToolkit().getDesktopProperty(PROP_NAME); + PassFailJFrame.log("toolkit.getDesktopProperty:" + PROP_NAME + "=" + value); + if (value.equals((Color) e.getNewValue())) { + PassFailJFrame.log("test PASSED"); + } else { + PassFailJFrame.log("test FAILED"); + } + } + }); + return f; + } +} diff --git a/test/jdk/java/awt/FileDialog/DoubleActionESC.java b/test/jdk/java/awt/FileDialog/DoubleActionESC.java index 748c3aeb5e4..e8bb4963aa0 100644 --- a/test/jdk/java/awt/FileDialog/DoubleActionESC.java +++ b/test/jdk/java/awt/FileDialog/DoubleActionESC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 @@ import java.awt.event.KeyEvent; import java.util.concurrent.CountDownLatch; +import static java.util.concurrent.TimeUnit.SECONDS; + /* * @test * @bug 5097243 * @summary Tests that FileDialog can be closed by ESC any time * @key headful * @run main DoubleActionESC + * @run main/othervm -Dsun.awt.disableGtkFileDialogs=true DoubleActionESC */ public class DoubleActionESC { @@ -49,47 +52,48 @@ public class DoubleActionESC { private static Robot robot; private static volatile Point p; private static volatile Dimension d; - private static volatile CountDownLatch latch; private static final int REPEAT_COUNT = 2; + private static final long LATCH_TIMEOUT = 10; - public static void main(String[] args) throws Exception { - latch = new CountDownLatch(1); + private static final CountDownLatch latch = new CountDownLatch(REPEAT_COUNT); + public static void main(String[] args) throws Exception { robot = new Robot(); - robot.setAutoDelay(100); + robot.setAutoDelay(50); try { EventQueue.invokeAndWait(() -> { createAndShowUI(); }); + robot.waitForIdle(); robot.delay(1000); + EventQueue.invokeAndWait(() -> { p = showBtn.getLocationOnScreen(); d = showBtn.getSize(); }); for (int i = 0; i < REPEAT_COUNT; ++i) { - Thread thread = new Thread(() -> { - robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - }); - thread.start(); - robot.delay(3000); + robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(1000); - Thread thread1 = new Thread(() -> { - robot.keyPress(KeyEvent.VK_ESCAPE); - robot.keyRelease(KeyEvent.VK_ESCAPE); - robot.waitForIdle(); - }); - thread1.start(); - robot.delay(3000); + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); + robot.delay(1000); } - latch.await(); - if (fd.isVisible()) { - throw new RuntimeException("File Dialog is not closed"); + if (!latch.await(LATCH_TIMEOUT, SECONDS)) { + throw new RuntimeException("Test failed: Latch timeout reached"); } + EventQueue.invokeAndWait(() -> { + if (fd.isVisible()) { + throw new RuntimeException("File Dialog is not closed"); + } + }); } finally { EventQueue.invokeAndWait(() -> { if (f != null) { diff --git a/test/jdk/java/awt/Focus/ComponentLostFocusTest.java b/test/jdk/java/awt/Focus/ComponentLostFocusTest.java index 6af8322b2cd..8045ace43d5 100644 --- a/test/jdk/java/awt/Focus/ComponentLostFocusTest.java +++ b/test/jdk/java/awt/Focus/ComponentLostFocusTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,13 +35,20 @@ import java.awt.Frame; import java.awt.KeyboardFocusManager; import java.awt.Point; +import java.awt.Rectangle; import java.awt.Robot; import java.awt.TextField; +import java.awt.Toolkit; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.InputEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.io.File; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.imageio.ImageIO; public class ComponentLostFocusTest { @@ -49,10 +56,10 @@ public class ComponentLostFocusTest { static TextField tf; static Robot r; static Dialog dialog = null; - static volatile boolean passed; static volatile Point loc; static volatile int width; static volatile int top; + static final CountDownLatch focusGainedLatch = new CountDownLatch(1); private static void createTestUI() { @@ -75,11 +82,7 @@ public void windowGainedFocus(WindowEvent e) { public static void doTest() { System.out.println("dialog.setVisible.... "); - new Thread(new Runnable() { - public void run() { - dialog.setVisible(true); - } - }).start(); + new Thread(() -> dialog.setVisible(true)).start(); // The bug is that this construction leads to the redundant xRequestFocus // By the way, the requestFocusInWindow() works fine before the fix @@ -98,7 +101,7 @@ public void run() { tf.addFocusListener(new FocusAdapter() { public void focusGained(FocusEvent e) { System.out.println("TextField gained focus: " + e); - passed = true; + focusGainedLatch.countDown(); } }); @@ -116,6 +119,17 @@ private static void doRequestFocusToTextField() { tf.requestFocus(); } + private static void captureScreen() { + try { + final Rectangle screenBounds = new Rectangle( + Toolkit.getDefaultToolkit().getScreenSize()); + ImageIO.write(r.createScreenCapture(screenBounds), + "png", new File("ComponentLostFocusTest.png")); + } catch (Exception e) { + e.printStackTrace(); + } + } + public static final void main(String args[]) throws Exception { r = new Robot(); r.setAutoDelay(100); @@ -138,9 +152,10 @@ public static final void main(String args[]) throws Exception { System.out.println("Focus owner: " + KeyboardFocusManager.getCurrentKeyboardFocusManager(). getFocusOwner()); - - if (!passed) { - throw new RuntimeException("TextField got no focus! Test failed."); + if (!focusGainedLatch.await(5, TimeUnit.SECONDS)) { + captureScreen(); + throw new RuntimeException("Waited too long, " + + "TextField got no focus! Test failed."); } } finally { EventQueue.invokeAndWait(() -> { @@ -151,4 +166,3 @@ public static final void main(String args[]) throws Exception { } } } - diff --git a/test/jdk/java/awt/Focus/MinimizeNonfocusableWindowTest.java b/test/jdk/java/awt/Focus/MinimizeNonfocusableWindowTest.java new file mode 100644 index 00000000000..3114850dc7a --- /dev/null +++ b/test/jdk/java/awt/Focus/MinimizeNonfocusableWindowTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 6399659 + * @summary When minimizing non-focusable window focus shouldn't jump out of the focused window. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MinimizeNonfocusableWindowTest +*/ + +import java.awt.Frame; +import java.awt.Window; +import java.util.List; + +public class MinimizeNonfocusableWindowTest { + + private static final String INSTRUCTIONS = """ + + You should see three frames: Frame-1, Frame-2 and Unfocusable. + + 1. Click Frame-1 to make it focused window, then click Frame-2. + Minimize Unfocusable frame with the mouse. If Frame-2 is still + the focused window continue testing, otherwise press FAIL. + + 2. Restore Unfocusable frame to normal state. Try to resize by dragging + its edge with left mouse button. It should be resizable. If not press + FAIL. Try the same with right mouse button. It shouldn't resize. + If it does, press FAIL, otherwise press PASS."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("MinimizeNonfocusableWindowTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 1) + .columns(40) + .testUI(MinimizeNonfocusableWindowTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static List createTestUI() { + Frame frame1 = new Frame("Frame-1"); + Frame frame2 = new Frame("Frame-2"); + Frame frame3 = new Frame("Unfocusable"); + frame1.setBounds(100, 0, 200, 100); + frame2.setBounds(100, 150, 200, 100); + frame3.setBounds(100, 300, 200, 100); + + frame3.setFocusableWindowState(false); + + return List.of(frame1, frame2, frame3); + } +} + diff --git a/test/jdk/java/awt/Focus/WindowDisposeFocusTest.java b/test/jdk/java/awt/Focus/WindowDisposeFocusTest.java new file mode 100644 index 00000000000..5e2e49147e5 --- /dev/null +++ b/test/jdk/java/awt/Focus/WindowDisposeFocusTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4257071 4228379 + * @summary Ensures that focus lost is delivered to a lightweight component + in a disposed window + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual WindowDisposeFocusTest +*/ + +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JPanel; + +public class WindowDisposeFocusTest { + + private static final String INSTRUCTIONS = """ + Click on "Second" + Click on close box + When dialog pops up, "Second" should no longer have focus."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("WindowDisposeFocusTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(WindowDisposeFocusTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Window createTestUI() { + return JFCFocusBug2.test(new String[]{}); + } +} + +class JFCFocusBug2 extends JPanel { + + static public Window test(String[] args) { + final JFrame frame = new JFrame("WindowDisposeFrame"); + frame.setSize(100, 100); + frame.setVisible(true); + + final JFCFocusBug2 bug = new JFCFocusBug2(); + final JDialog dialog = new JDialog(frame, false); + dialog.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + dialog.dispose(); + JDialog dialog2 = new JDialog(frame, false); + dialog2.setContentPane(bug); + dialog2.pack(); + dialog2.setVisible(true); + } + }); + dialog.setContentPane(bug); + dialog.pack(); + dialog.setVisible(true); + return frame; + } + + public JFCFocusBug2() { + _first = new JButton("First"); + _second = new JButton("Second"); + add(_first); + add(_second); + } + + private JButton _first; + private JButton _second; +} diff --git a/test/jdk/java/awt/Focus/bug6435715.java b/test/jdk/java/awt/Focus/bug6435715.java new file mode 100644 index 00000000000..f13f731169f --- /dev/null +++ b/test/jdk/java/awt/Focus/bug6435715.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 6435715 + * @summary JButton stops receiving the focusGained event and eventually focus is lost altogether + * @modules java.desktop/sun.awt + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6435715 + */ + +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +public class bug6435715 { + + private static final String INSTRUCTIONS = """ + 1. after test started you will see frame with three buttons. Notice that focus is on Button2. + 2. Click on Button 3. Focus goes to Button3. + 3. Click on Button1 and quickly switch to another window. Via either alt/tab or + clicking another window with the mouse. + 4. After a few seconds, come back to the frame. Notice that focus is around Button2 + 5. Click at Button3. If focus remains at Button2 test failed, if focus is on Button3 - test passed."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug6435715 Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 5) + .columns(35) + .testUI(bug6435715::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame fr = new JFrame("FocusIssue"); + sun.awt.SunToolkit.setLWRequestStatus(fr, true); + + JPanel panel = new JPanel(); + final JButton b1 = new JButton("Button 1"); + final JButton b2 = new JButton("Button 2"); + final JButton b3 = new JButton("Button 3"); + + panel.add(b1); + panel.add(b2); + panel.add(b3); + + b1.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent event) { + synchronized (this) { + try { + wait(1000); + } catch (Exception ex) { + ex.printStackTrace(); + } + b2.requestFocus(); + } + } + }); + fr.getContentPane().add(panel); + fr.pack(); + return fr; + } + +} diff --git a/test/jdk/java/awt/FontClass/FontTransformAttributeTest.java b/test/jdk/java/awt/FontClass/FontTransformAttributeTest.java new file mode 100644 index 00000000000..7bbf5d11d28 --- /dev/null +++ b/test/jdk/java/awt/FontClass/FontTransformAttributeTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.font.TextAttribute; +import java.awt.font.TransformAttribute; +import java.awt.geom.AffineTransform; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; + +import javax.swing.JPanel; + +/* + * @test + * @bug 4650042 + * @summary Draw text using a transform to simulate superscript, it should look like a superscript + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FontTransformAttributeTest + */ + +public class FontTransformAttributeTest extends JPanel { + AttributedCharacterIterator iter; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + This test should display a string ending with the superscripted number '11'. + Pass the test if you see the superscript."""; + + PassFailJFrame.builder() + .title("FontTransformAttributeTest Instruction") + .instructions(INSTRUCTIONS) + .columns(35) + .splitUI(FontTransformAttributeTest::new) + .build() + .awaitAndCheck(); + } + + FontTransformAttributeTest() { + AffineTransform superTransform = AffineTransform.getScaleInstance(0.65, 0.65); + superTransform.translate(0, -7); + TransformAttribute superAttribute = new TransformAttribute(superTransform); + String s = "a big number 7 11"; + AttributedString as = new AttributedString(s); + as.addAttribute(TextAttribute.TRANSFORM, superAttribute, 15, 17); + iter = as.getIterator(); + setBackground(Color.WHITE); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 100); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + Dimension d = getSize(); + g2.drawString(iter, 20, d.height / 2 + 8); + } +} diff --git a/test/jdk/java/awt/FontClass/FontUnderscoreTest.java b/test/jdk/java/awt/FontClass/FontUnderscoreTest.java new file mode 100644 index 00000000000..101a0b49088 --- /dev/null +++ b/test/jdk/java/awt/FontClass/FontUnderscoreTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Dimension; +import java.awt.Font; +import java.awt.Graphics; + +import javax.swing.JPanel; + +/* + * @test + * @bug 4248579 + * @summary Make sure the underscore glyph appears in the different strings + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FontUnderscoreTest + */ + +public class FontUnderscoreTest extends JPanel { + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + Make sure all 8 underscore characters appear in each + of the 3 strings. + + Press PASS if all 8 are there, else FAIL."""; + + PassFailJFrame.builder() + .title("FontUnderscoreTest Instruction") + .instructions(INSTRUCTIONS) + .columns(35) + .splitUI(FontUnderscoreTest::new) + .build() + .awaitAndCheck(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(550, 230); + } + + @Override + public void paint(Graphics g) { + Font f = new Font(Font.SANS_SERIF, Font.PLAIN, 24); + g.setFont(f); + g.drawString ("8 underscore characters appear in each string", 5, 200); + + g.drawString("J_A_V_A_2_j_a_v_a", 25, 50); + + f = new Font(Font.SERIF, Font.PLAIN, 24); + g.setFont(f); + g.drawString("J_A_V_A_2_j_a_v_a", 25, 100); + + f = new Font(Font.MONOSPACED, Font.PLAIN, 24); + g.setFont(f); + g.drawString("J_A_V_A_2_j_a_v_a", 25, 150); + } +} diff --git a/test/jdk/java/awt/Frame/ShownOnPack/ShownOnPack.html b/test/jdk/java/awt/Frame/ShownOnPack/ShownOnPack.html deleted file mode 100644 index 6dd732fcf6c..00000000000 --- a/test/jdk/java/awt/Frame/ShownOnPack/ShownOnPack.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - ShownOnPack - - - -

ShownOnPack
Bug ID: 6525850

- -

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

- - - - diff --git a/test/jdk/java/awt/Frame/ShownOnPack/ShownOnPack.java b/test/jdk/java/awt/Frame/ShownOnPack/ShownOnPack.java index a5763d0bed2..5e591bfe0a6 100644 --- a/test/jdk/java/awt/Frame/ShownOnPack/ShownOnPack.java +++ b/test/jdk/java/awt/Frame/ShownOnPack/ShownOnPack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * 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,208 +21,48 @@ * questions. */ +import java.awt.EventQueue; +import java.awt.Frame; + /* - test - @bug 6525850 - @summary Iconified frame gets shown after pack() - @author anthony.petrov@...: area=awt.toplevel - @run applet/manual=yesno ShownOnPack.html + * @test + * @bug 6525850 + * @summary Iconified frame gets shown after pack() + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ShownOnPack */ - -/** - * ShownOnPack.java - * - * summary: - */ - -import java.applet.Applet; -import java.awt.*; - -public class ShownOnPack extends Applet -{ - //Declare things used in the test, like buttons and labels here - Frame f; - - public void init() - { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - this.setLayout (new BorderLayout ()); - - String[] instructions = - { - "This test creates an invisible and iconified frame that should not become visible.", - "If you observe the window titled 'Should NOT BE SHOWN' in the taskbar, press FAIL,", - "else press PASS" - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - 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. - //Use Sysout.println for messages you want the tester to read. - f = new Frame("Should NOT BE SHOWN"); - f.setExtendedState(Frame.ICONIFIED); - f.pack(); - }// 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 ShownOnPack - -/* 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. - */ - -class Sysout -{ - private static TestDialog dialog; - - 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." ); - } - - 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." ); +public class ShownOnPack { + + private static final String INSTRUCTIONS = """ + This test creates an invisible and iconified frame that should not become visible. + + If you observe the window titled 'Should NOT BE SHOWN' in the taskbar, + press FAIL, otherwise press PASS + """; + + static Frame frame; + + public static void main(String[] args) throws Exception { + PassFailJFrame shownOnPackInstructions = PassFailJFrame + .builder() + .title("ShownOnPack Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(50) + .build(); + + EventQueue.invokeAndWait(() -> { + frame = new Frame("Should NOT BE SHOWN"); + frame.setExtendedState(Frame.ICONIFIED); + frame.pack(); + }); + + try { + shownOnPackInstructions.awaitAndCheck(); + } finally { + EventQueue.invokeAndWait(() -> frame.dispose()); + } } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - 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); - } - -}// TestDialog class +} diff --git a/test/jdk/java/awt/FullScreen/NonfocusableFrameFullScreenTest.java b/test/jdk/java/awt/FullScreen/NonfocusableFrameFullScreenTest.java new file mode 100644 index 00000000000..a273adff6cc --- /dev/null +++ b/test/jdk/java/awt/FullScreen/NonfocusableFrameFullScreenTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.BorderLayout; +import java.awt.Button; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GraphicsEnvironment; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JPanel; + +/* + * @test + * @bug 6225472 6682536 + * @requires (os.family != "linux") + * @summary Tests that non-focusable Frame in full-screen mode overlaps the task bar. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NonfocusableFrameFullScreenTest + */ + +public class NonfocusableFrameFullScreenTest extends JPanel { + boolean fullscreen = false; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + 1. Press "Show Frame" button to show a Frame with two buttons. + + 2. Press the button "To Full Screen" to bring the frame to + full-screen mode: + + The frame should overlap the taskbar + + 3. Press "To Windowed" button: + The frame should return to its original size. + The frame shouldn't be alwaysOnTop. + + 4. Press "Set Always On Top" button and make sure the frame + is alwaysOnTop, then press "To Full Screen" button + and then "To Windowed" button: + + The frame should return to its original size keeping alwaysOnTop + state on. + + Press Pass if everything is as expected."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(NonfocusableFrameFullScreenTest::new) + .build() + .awaitAndCheck(); + } + + private NonfocusableFrameFullScreenTest() { + Button b = new Button("Show Frame"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showFrame(); + } + }); + setLayout(new BorderLayout()); + add(b, BorderLayout.CENTER); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 100); + } + + public void showFrame() { + Frame frame = new Frame("Test Frame"); + + Button button = new Button("To Full Screen"); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (fullscreen) { + GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(). + setFullScreenWindow(null); + button.setLabel("To Full Screen"); + fullscreen = false; + } else { + GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(). + setFullScreenWindow(frame); + button.setLabel("To Windowed"); + fullscreen = true; + } + frame.validate(); + } + }); + + Button button2 = new Button("Set Always On Top"); + button2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (frame.isAlwaysOnTop()) { + button2.setLabel("Set Always On Top"); + frame.setAlwaysOnTop(false); + } else { + button2.setLabel("Set Not Always On Top"); + frame.setAlwaysOnTop(true); + } + frame.validate(); + } + }); + + frame.setLayout(new BorderLayout()); + frame.add(button, BorderLayout.WEST); + frame.add(button2, BorderLayout.EAST); + frame.setBounds(400, 200, 350, 100); + frame.setFocusableWindowState(false); + frame.setVisible(true); + } +} diff --git a/test/jdk/java/awt/Graphics/GDIResourceExhaustionTest.java b/test/jdk/java/awt/Graphics/GDIResourceExhaustionTest.java new file mode 100644 index 00000000000..b8ba155da60 --- /dev/null +++ b/test/jdk/java/awt/Graphics/GDIResourceExhaustionTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.imageio.ImageIO; +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +/* + * @test + * @bug 4191297 + * @summary Tests that unreferenced GDI resources are correctly + * destroyed when no longer needed. + * @key headful + * @run main GDIResourceExhaustionTest + */ + +public class GDIResourceExhaustionTest extends Frame { + public void initUI() { + setSize(200, 200); + setUndecorated(true); + setLocationRelativeTo(null); + Panel labelPanel = new Panel(); + Label label = new Label("Red label"); + label.setBackground(Color.red); + labelPanel.add(label); + labelPanel.setLocation(20, 50); + add(labelPanel); + setVisible(true); + } + + public void paint(Graphics graphics) { + super.paint(graphics); + for (int rgb = 0; rgb <= 0xfff; rgb++) { + graphics.setColor(new Color(rgb)); + graphics.fillRect(0, 0, 5, 5); + } + } + + public void requestCoordinates(Rectangle r) { + Insets insets = getInsets(); + Point location = getLocationOnScreen(); + Dimension size = getSize(); + r.x = location.x + insets.left; + r.y = location.y + insets.top; + r.width = size.width - (insets.left + insets.right); + r.height = size.height - (insets.top + insets.bottom); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException, IOException { + GDIResourceExhaustionTest test = new GDIResourceExhaustionTest(); + try { + EventQueue.invokeAndWait(test::initUI); + Robot robot = new Robot(); + robot.delay(2000); + Rectangle coords = new Rectangle(); + EventQueue.invokeAndWait(() -> { + test.requestCoordinates(coords); + }); + robot.mouseMove(coords.x - 50, coords.y - 50); + robot.waitForIdle(); + robot.delay(5000); + BufferedImage capture = robot.createScreenCapture(coords); + robot.delay(500); + boolean redFound = false; + int redRGB = Color.red.getRGB(); + for (int y = 0; y < capture.getHeight(); y++) { + for (int x = 0; x < capture.getWidth(); x++) { + if (capture.getRGB(x, y) == redRGB) { + redFound = true; + break; + } + if (redFound) { + break; + } + } + } + if (!redFound) { + File errorImage = new File("screenshot.png"); + ImageIO.write(capture, "png", errorImage); + throw new RuntimeException("Red label is not detected, possibly GDI resources exhausted"); + } + } finally { + EventQueue.invokeAndWait(test::dispose); + } + } +} diff --git a/test/jdk/java/awt/Graphics/RepeatedRepaintTest.java b/test/jdk/java/awt/Graphics/RepeatedRepaintTest.java new file mode 100644 index 00000000000..140cb48630d --- /dev/null +++ b/test/jdk/java/awt/Graphics/RepeatedRepaintTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; + +/* + * @test + * @bug 4081126 4129709 + * @summary Test for proper repainting on multiprocessor systems. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RepeatedRepaintTest + */ +public class RepeatedRepaintTest extends Frame { + private Font font = null; + private Image background; + + static String INSTRUCTIONS = """ + The frame next to this window called "AWT Draw Test" has + some elements drawn on it. Move this window partially outside of the + screen bounds and then drag it back. Repeat it couple of times. + Drag the instructions window over the frame partially obscuring it. + If after number of attempts the frame content stops repainting + press "Fail", otherwise press "Pass". + """; + + public RepeatedRepaintTest() { + setTitle("AWT Draw Test"); + setSize(300, 300); + background = new BufferedImage(300, 300, BufferedImage.TYPE_INT_ARGB); + Graphics g = background.getGraphics(); + g.setColor(Color.black); + g.fillRect(0, 0, 300, 300); + g.dispose(); + } + + public void paint(Graphics g) { + Dimension dim = this.getSize(); + super.paint(g); + g.drawImage(background, 0, 0, dim.width, dim.height, null); + g.setColor(Color.white); + if (font == null) { + font = new Font("SansSerif", Font.PLAIN, 24); + } + g.setFont(font); + FontMetrics metrics = g.getFontMetrics(); + String message = "Draw Test"; + g.drawString(message, (dim.width / 2) - (metrics.stringWidth(message) / 2), + (dim.height / 2) + (metrics.getHeight() / 2)); + + int counter = 50; + for (int i = 0; i < 50; i++) { + counter += 4; + g.drawOval(counter, 50, i, i); + } + + counter = 20; + for (int i = 0; i < 100; i++) { + counter += 4; + g.drawOval(counter, 150, i, i); + } + g.setColor(Color.black); + g.drawLine(0, dim.height - 25, dim.width, dim.height - 25); + g.setColor(Color.gray); + g.drawLine(0, dim.height - 24, dim.width, dim.height - 24); + g.setColor(Color.lightGray); + g.drawLine(0, dim.height - 23, dim.width, dim.height - 23); + g.fillRect(0, dim.height - 22, dim.width, dim.height); + + + g.setXORMode(Color.blue); + g.fillRect(0, 0, 25, dim.height - 26); + g.setColor(Color.red); + g.fillRect(0, 0, 25, dim.height - 26); + g.setColor(Color.green); + g.fillRect(0, 0, 25, dim.height - 26); + g.setPaintMode(); + + Image img = createImage(50, 50); + Graphics imgGraphics = img.getGraphics(); + imgGraphics.setColor(Color.magenta); + imgGraphics.fillRect(0, 0, 50, 50); + imgGraphics.setColor(Color.yellow); + imgGraphics.drawString("offscreen", 0, 20); + imgGraphics.drawString("image", 0, 30); + + g.drawImage(img, dim.width - 100, dim.height - 100, Color.blue, null); + + g.setXORMode(Color.white); + drawAt(g, 100, 100, 50, 50); + drawAt(g, 105, 105, 50, 50); + drawAt(g, 110, 110, 50, 50); + } + + public void drawAt(Graphics g, int x, int y, int width, int height) { + g.setColor(Color.magenta); + g.fillRect(x, y, width, height); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Repeated Repaint Test Instructions") + .instructions(INSTRUCTIONS) + .testUI(RepeatedRepaintTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/Graphics/SmallPrimitives.java b/test/jdk/java/awt/Graphics/SmallPrimitives.java new file mode 100644 index 00000000000..7eb267cf0b9 --- /dev/null +++ b/test/jdk/java/awt/Graphics/SmallPrimitives.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.Polygon; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.lang.reflect.InvocationTargetException; + +/* + * @test + * @bug 4411814 4298688 4205762 4524760 4067534 + * @summary Check that Graphics rendering primitives function + * correctly when fed small and degenerate shapes + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SmallPrimitives + */ + + +public class SmallPrimitives extends Panel { + + static String INSTRUCTIONS = """ + In the borderless frame next to this window there should be a + set of tiny narrow blue polygons painted next to the green rectangles. + If rectangle is vertical the corresponding polygon is painted to the right of it, + if rectangle is horizontal the polygon is painted below it. + The length of the polygon should be roughly the same as the length of the + green rectangle next to it. If size is significantly different or any of the + polygons is not painted press "Fail" otherwise press "Pass". + Note: one may consider using screen magnifier to compare sizes. + """; + + public void paint(Graphics g) { + Dimension d = getSize(); + Polygon p; + GeneralPath gp; + + g.setColor(Color.white); + g.fillRect(0, 0, d.width, d.height); + + // Reposition for horizontal tests (below) + g.translate(0, 20); + + // Reference shapes + g.setColor(Color.green); + g.fillRect(10, 7, 11, 1); + g.fillRect(10, 17, 11, 2); + g.fillRect(10, 27, 11, 1); + g.fillRect(10, 37, 11, 1); + g.fillRect(10, 47, 11, 2); + g.fillRect(10, 57, 11, 2); + g.fillRect(10, 67, 11, 1); + g.fillRect(10, 77, 11, 2); + g.fillRect(10, 87, 11, 1); + g.fillRect(10, 97, 11, 1); + g.fillRect(10, 107, 11, 1); + g.fillRect(10, 117, 6, 1); g.fillRect(20, 117, 6, 1); + + // Potentially problematic test shapes + g.setColor(Color.blue); + g.drawRect(10, 10, 10, 0); + g.drawRect(10, 20, 10, 1); + g.drawRoundRect(10, 30, 10, 0, 0, 0); + g.drawRoundRect(10, 40, 10, 0, 4, 4); + g.drawRoundRect(10, 50, 10, 1, 0, 0); + g.drawRoundRect(10, 60, 10, 1, 4, 4); + g.drawOval(10, 70, 10, 0); + g.drawOval(10, 80, 10, 1); + p = new Polygon(); + p.addPoint(10, 90); + p.addPoint(20, 90); + g.drawPolyline(p.xpoints, p.ypoints, p.npoints); + p = new Polygon(); + p.addPoint(10, 100); + p.addPoint(20, 100); + g.drawPolygon(p.xpoints, p.ypoints, p.npoints); + ((Graphics2D) g).draw(new Line2D.Double(10, 110, 20, 110)); + gp = new GeneralPath(); + gp.moveTo(10, 120); + gp.lineTo(15, 120); + gp.moveTo(20, 120); + gp.lineTo(25, 120); + ((Graphics2D) g).draw(gp); + + // Polygon limit tests + p = new Polygon(); + trypoly(g, p); + p.addPoint(10, 120); + trypoly(g, p); + + // Reposition for vertical tests (below) + g.translate(20, -20); + + // Reference shapes + g.setColor(Color.green); + g.fillRect(7, 10, 1, 11); + g.fillRect(17, 10, 2, 11); + g.fillRect(27, 10, 1, 11); + g.fillRect(37, 10, 1, 11); + g.fillRect(47, 10, 2, 11); + g.fillRect(57, 10, 2, 11); + g.fillRect(67, 10, 1, 11); + g.fillRect(77, 10, 2, 11); + g.fillRect(87, 10, 1, 11); + g.fillRect(97, 10, 1, 11); + g.fillRect(107, 10, 1, 11); + g.fillRect(117, 10, 1, 6); g.fillRect(117, 20, 1, 6); + + // Potentially problematic test shapes + g.setColor(Color.blue); + g.drawRect(10, 10, 0, 10); + g.drawRect(20, 10, 1, 10); + g.drawRoundRect(30, 10, 0, 10, 0, 0); + g.drawRoundRect(40, 10, 0, 10, 4, 4); + g.drawRoundRect(50, 10, 1, 10, 0, 0); + g.drawRoundRect(60, 10, 1, 10, 4, 4); + g.drawOval(70, 10, 0, 10); + g.drawOval(80, 10, 1, 10); + p = new Polygon(); + p.addPoint(90, 10); + p.addPoint(90, 20); + g.drawPolyline(p.xpoints, p.ypoints, p.npoints); + p = new Polygon(); + p.addPoint(100, 10); + p.addPoint(100, 20); + g.drawPolygon(p.xpoints, p.ypoints, p.npoints); + ((Graphics2D) g).draw(new Line2D.Double(110, 10, 110, 20)); + gp = new GeneralPath(); + gp.moveTo(120, 10); + gp.lineTo(120, 15); + gp.moveTo(120, 20); + gp.lineTo(120, 25); + ((Graphics2D) g).draw(gp); + + // Polygon limit tests + p = new Polygon(); + trypoly(g, p); + p.addPoint(110, 10); + trypoly(g, p); + + // Reposition for oval tests + g.translate(0, 20); + + for (int i = 0, xy = 8; i < 11; i++) { + g.setColor(Color.green); + g.fillRect(xy, 5, i, 1); + g.fillRect(5, xy, 1, i); + g.setColor(Color.blue); + g.fillOval(xy, 8, i, 1); + g.fillOval(8, xy, 1, i); + xy += i + 2; + } + + g.translate(10, 10); + for (int i = 0, xy = 9; i < 6; i++) { + g.setColor(Color.green); + g.fillRect(xy, 5, i, 2); + g.fillRect(5, xy, 2, i); + g.setColor(Color.blue); + g.fillOval(xy, 8, i, 2); + g.fillOval(8, xy, 2, i); + xy += i + 2; + } + } + + public static void trypoly(Graphics g, Polygon p) { + g.drawPolygon(p); + g.drawPolygon(p.xpoints, p.ypoints, p.npoints); + g.drawPolyline(p.xpoints, p.ypoints, p.npoints); + g.fillPolygon(p); + g.fillPolygon(p.xpoints, p.ypoints, p.npoints); + } + + public Dimension getPreferredSize() { + return new Dimension(150, 150); + } + + public static Frame createFrame() { + Frame f = new Frame(); + SmallPrimitives sp = new SmallPrimitives(); + sp.setLocation(0, 0); + f.add(sp); + f.setUndecorated(true); + f.pack(); + return f; + } + + public static void main(String argv[]) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Small Primitives Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(SmallPrimitives::createFrame) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/Graphics/TextAfterXor.java b/test/jdk/java/awt/Graphics/TextAfterXor.java new file mode 100644 index 00000000000..c9dc56d8b80 --- /dev/null +++ b/test/jdk/java/awt/Graphics/TextAfterXor.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.RenderingHints; +import java.awt.image.VolatileImage; +import java.lang.reflect.InvocationTargetException; + +/* + * @test + * @bug 4505650 + * @summary Check that you can render solid text after doing XOR mode + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TextAfterXor + */ + +public class TextAfterXor extends Panel { + public static final int TESTW = 300; + public static final int TESTH = 100; + static String INSTRUCTIONS = """ + In the window called "Text After XOR Test" there should be two + composite components, at the bottom of each component the green text + "Test passes if this is green!" should be visible. + + On the top component this text should be green on all platforms. + On the bottom component it is possible that on non-Windows + platforms text can be of other color or not visible at all. + That does not constitute a problem. + + So if platform is Windows and green text appears twice or on any + other platform green text appears at least once press "Pass", + otherwise press "Fail". + """; + + VolatileImage vimg; + + public void paint(Graphics g) { + render(g); + g.drawString("(Drawing to screen)", 10, 60); + if (vimg == null) { + vimg = createVolatileImage(TESTW, TESTH); + } + do { + vimg.validate(null); + Graphics g2 = vimg.getGraphics(); + render(g2); + String not = vimg.getCapabilities().isAccelerated() ? "" : "not "; + g2.drawString("Image was " + not + "accelerated", 10, 55); + g2.drawString("(only matters on Windows)", 10, 65); + g2.dispose(); + g.drawImage(vimg, 0, TESTH, null); + } while (vimg.contentsLost()); + } + + public void render(Graphics g) { + g.setColor(Color.black); + g.fillRect(0, 0, TESTW, TESTH); + g.setColor(Color.white); + g.fillRect(5, 5, TESTW-10, TESTH-10); + + g.setColor(Color.black); + g.drawString("Test only passes if green string appears", 10, 20); + + g.setColor(Color.white); + g.setXORMode(Color.blue); + g.drawRect(30, 30, 10, 10); + g.setPaintMode(); + g.setColor(Color.green); + + ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.drawString("Test passes if this is green!", 10, 80); + + g.setColor(Color.black); + } + + public Dimension getPreferredSize() { + return new Dimension(TESTW, TESTH*2); + } + + public static Frame createFrame() { + Frame f = new Frame("Text After XOR Test"); + f.add(new TextAfterXor()); + f.pack(); + return f; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Text After XOR Instructions") + .instructions(INSTRUCTIONS) + .testUI(TextAfterXor::createFrame) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/GridBagLayout/ComponentShortage.java b/test/jdk/java/awt/GridBagLayout/ComponentShortage.java new file mode 100644 index 00000000000..dd641bbf066 --- /dev/null +++ b/test/jdk/java/awt/GridBagLayout/ComponentShortage.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4238932 + * @summary JTextField in gridBagLayout does not properly set MinimumSize + * @key headful + * @run main ComponentShortage + */ + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JTextField; + +public class ComponentShortage { + static final int WIDTH_REDUCTION = 50; + static JFrame frame; + static JTextField jtf; + static volatile Dimension size; + static volatile Dimension fSize; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new JFrame(); + frame.setLayout(new GridBagLayout()); + GridBagConstraints gBC = new GridBagConstraints(); + + gBC.gridx = 1; + gBC.gridy = 0; + gBC.gridwidth = 1; + gBC.gridheight = 1; + gBC.weightx = 1.0; + gBC.weighty = 0.0; + gBC.fill = GridBagConstraints.NONE; + gBC.anchor = GridBagConstraints.NORTHWEST; + jtf = new JTextField(16); + frame.add(jtf, gBC); + frame.pack(); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + + EventQueue.invokeAndWait(() -> { + size = jtf.getSize(); + }); + System.out.println("TextField size before Frame's width reduction : " + size); + + EventQueue.invokeAndWait(() -> { + frame.setSize(frame.getSize().width - WIDTH_REDUCTION, frame.getSize().height); + }); + frame.repaint(); + + EventQueue.invokeAndWait(() -> { + size = jtf.getSize(); + fSize = frame.getSize(); + }); + System.out.println("TextField size after Frame's width reduction : " + size); + + if (size.width < fSize.width - WIDTH_REDUCTION) { + throw new RuntimeException("Width of JTextField is too small to be visible."); + } + System.out.println("Test passed."); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/Icon/ChildFrameIconTest.java b/test/jdk/java/awt/Icon/ChildFrameIconTest.java new file mode 100644 index 00000000000..6d83fa95acb --- /dev/null +++ b/test/jdk/java/awt/Icon/ChildFrameIconTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +/* + * @test + * @bug 4284610 + * @summary Tests that a child of the non-resizable dialog acquires valid icon. + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ChildFrameIconTest + */ + +public class ChildFrameIconTest { + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + Press "Show Dialog" button to open a dialog with this message: + Do you see a coffee cup icon in the upper left corner ? + + Look at the icon in the upper left corner of the message dialog. + + Press Pass if you see default coffee cup icon else press Fail."""; + + PassFailJFrame.builder() + .title("ChildFrameIconTest Instruction") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ChildFrameIconTest::createUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame f = new JFrame("ChildFrameIconTest UI"); + JButton b = new JButton("Show Dialog"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String msg = "Do you see a coffee cup icon in the upper left corner ?"; + JDialog dlg = new JDialog(f, "Non-resizable JDialog", false); + dlg.setResizable(false); + JOptionPane.showMessageDialog(dlg, msg); + } + }); + f.add(b); + f.setSize(250, 100); + return f; + } +} diff --git a/test/jdk/java/awt/InputMethods/DiacriticsTest/DiacriticsTest.html b/test/jdk/java/awt/InputMethods/DiacriticsTest/DiacriticsTest.html deleted file mode 100644 index 5cf5c91ea71..00000000000 --- a/test/jdk/java/awt/InputMethods/DiacriticsTest/DiacriticsTest.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - DiacriticsTest - - - - -Test run requires the following keyboard layouts to be installed: -Linux OS: English (US, alternative international) -Windows OS: Hungarian -A keyboard layout having compose function or compose-like key. Programmer -Dvorak (http://www.kaufmann.no/roland/dvorak/) is suggested to use. - -To test JDK-8000423 fix (Linux only!): -please switch to US alternative international layout and try to type diacritics -(using the following combinations: `+e; `+u; etc.) - -To test JDK-7197619 fix (Windows only!): -please switch to Hungarian keyboard layout and try to type diacritics -(Ctrl+Alt+2 e; Ctrl+Alt+2 E) - -To test JDK-8139189 fix: -please switch to Programmer Dvorak keyboard layout try to type diacritics -using compose combinations (Compose+z+d, Compose+z+Shift+d). The Compose key -in Programmer Dvorak layout is OEM102 the key which is located between -Left Shift and Z keys on the standard 102-key keyboard. - -If you can do that then the test is passed; otherwise failed. - - diff --git a/test/jdk/java/awt/InputMethods/DiacriticsTest/DiacriticsTest.java b/test/jdk/java/awt/InputMethods/DiacriticsTest/DiacriticsTest.java index 7c610e4791f..1481f7ec477 100644 --- a/test/jdk/java/awt/InputMethods/DiacriticsTest/DiacriticsTest.java +++ b/test/jdk/java/awt/InputMethods/DiacriticsTest/DiacriticsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * 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,30 +21,94 @@ * questions. */ +import jdk.test.lib.Platform; +import java.awt.GridLayout; +import java.awt.TextArea; +import java.awt.TextField; +import javax.swing.JPanel; /* - @test - @bug 8000423 7197619 8025649 - @summary Check if diacritical signs could be typed for TextArea and TextField - @run applet/manual=yesno DiacriticsTest.html -*/ + * @test + * @bug 8000423 7197619 8025649 + * @summary Check if diacritical signs could be typed for TextArea and TextField + * @requires (os.family == "windows" | os.family == "linux") + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jdk.test.lib.Platform + * @run main/manual DiacriticsTest + */ +public class DiacriticsTest { -import java.applet.Applet; -import java.awt.*; -import javax.swing.JPanel; + private static final String INSTRUCTIONS_WIN = """ + Test run requires the following keyboard layouts to be installed: + - Hungarian + - A keyboard layout having compose function or compose-like key. Programmer + Dvorak (http://www.kaufmann.no/roland/dvorak/) is suggested to use. + To the right are a text area and a text field, you should check the behavior + for both of them. -public class DiacriticsTest extends Applet { + To test the JDK-7197619 fix: + Please switch to Hungarian keyboard layout and try to type diacritics + (Ctrl+Alt+2 e; Ctrl+Alt+2 E) - public void init() { - this.setLayout(new BorderLayout()); - } + To test the JDK-8139189 fix: + Please switch to Programmer Dvorak keyboard layout try to type diacritics + using compose combinations (Compose+z+d, Compose+z+Shift+d). + + The Compose key in the Programmer Dvorak layout is OEM102, the key located + between the and Z keys on a standard 102-key keyboard. + If you do not have this key on your keyboard, you can skip this part of the test. + + If you can do that then the test is passed; otherwise failed. + """; + + private static final String INSTRUCTIONS_LIN = """ + Test run requires the following keyboard layouts to be installed: + - English (US, alternative international), aka English (US, alt. intl.) + - A keyboard layout having compose function or compose-like key. Programmer + Dvorak (http://www.kaufmann.no/roland/dvorak/) is suggested to use. + + To the right are a text area and a text field, you should check the behavior + for both of them. - public void start() { + To test the JDK-8000423 fix: + Please switch to US alternative international layout and try to type diacritics + (using the following combinations: `+e; `+u; etc.) - setSize(350, 200); + To test the JDK-8139189 fix: + Please switch to Programmer Dvorak keyboard layout try to type diacritics + using compose combinations (Compose+z+d, Compose+z+Shift+d).. + The Compose key in the Programmer Dvorak layout is OEM102, the key located + between the and Z keys on a standard 102-key keyboard. + + If the above key does not work in the Gnome shell, + it can be overridden in the system preferences: + System > Keyboard > Special character entry > Compose key + and set it to another key(e.g. menu key or scroll lock.) + + If you can do that then the test is passed; otherwise failed. + """; + + public static void main(String[] args) throws Exception { + String instructions = Platform.isWindows() + ? INSTRUCTIONS_WIN + : INSTRUCTIONS_LIN; + + PassFailJFrame + .builder() + .title("DiacriticsTest Instructions") + .instructions(instructions) + .splitUIRight(DiacriticsTest::createPanel) + .testTimeOut(10) + .rows((int) instructions.lines().count() + 2) + .columns(50) + .build() + .awaitAndCheck(); + } + + public static JPanel createPanel() { JPanel panel = new JPanel(); panel.setLayout(new GridLayout(2, 1)); @@ -54,10 +118,6 @@ public void start() { TextField txtField = new TextField(); panel.add(txtField); - add(panel, BorderLayout.CENTER); - - validate(); - setVisible(true); + return panel; } } - diff --git a/test/jdk/java/awt/List/ListEnterExitTest.java b/test/jdk/java/awt/List/ListEnterExitTest.java index 998b152a634..201a0e43c13 100644 --- a/test/jdk/java/awt/List/ListEnterExitTest.java +++ b/test/jdk/java/awt/List/ListEnterExitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,16 +36,24 @@ import java.awt.Point; import java.awt.Robot; -import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + public class ListEnterExitTest { final List list = new List(); - final MouseEnterExitListener mouseEnterExitListener = new MouseEnterExitListener(); Frame frame; volatile Point p; + private static final int X_OFFSET = 30; + private static final int Y_OFFSET = 40; + private static final int LATCH_TIMEOUT = 3; + + private final CountDownLatch mouseEnterLatch = new CountDownLatch(1); + private final CountDownLatch mouseExitLatch = new CountDownLatch(1); + public static void main(String[] args) throws Exception { ListEnterExitTest test = new ListEnterExitTest(); test.start(); @@ -57,7 +65,11 @@ public void start() throws Exception { frame = new Frame("ListEnterExitTest"); list.add("Item 1"); list.add("Item 2"); - list.addMouseListener(mouseEnterExitListener); + list.add("Item 3"); + list.add("Item 4"); + list.add("Item 5"); + list.add("Item 6"); + list.addMouseListener(new MouseEnterExitListener()); frame.add(list); frame.setLayout(new FlowLayout()); frame.setSize(300, 200); @@ -66,25 +78,28 @@ public void start() throws Exception { }); final Robot robot = new Robot(); - robot.delay(1000); + robot.setAutoDelay(100); robot.waitForIdle(); + robot.delay(1000); EventQueue.invokeAndWait(() -> { p = list.getLocationOnScreen(); }); - robot.mouseMove(p.x + 10, p.y + 10); - robot.delay(100); + robot.mouseMove(p.x + X_OFFSET, p.y + Y_OFFSET); robot.waitForIdle(); - robot.mouseMove(p.x - 10, p.y - 10); - robot.delay(100); + + robot.mouseMove(p.x - X_OFFSET, p.y + Y_OFFSET); robot.waitForIdle(); - robot.mouseMove(p.x + 10, p.y + 10); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mouseMove(p.x + X_OFFSET, p.y + Y_OFFSET); + robot.waitForIdle(); + + if (!mouseEnterLatch.await(LATCH_TIMEOUT, TimeUnit.SECONDS)) { + throw new RuntimeException("Mouse enter event timeout"); + } - synchronized (mouseEnterExitListener) { - mouseEnterExitListener.wait(2000); + if (!mouseExitLatch.await(LATCH_TIMEOUT, TimeUnit.SECONDS)) { + throw new RuntimeException("Mouse exit event timeout"); } } finally { EventQueue.invokeAndWait(() -> { @@ -93,35 +108,19 @@ public void start() throws Exception { } }); } - if (!mouseEnterExitListener.isPassed()) { - throw new RuntimeException("Haven't receive mouse enter/exit events"); - } - } -} - -class MouseEnterExitListener extends MouseAdapter { - - volatile boolean passed_1 = false; - volatile boolean passed_2 = false; - - public void mouseEntered(MouseEvent e) { - passed_1 = true; - } - - public void mouseExited(MouseEvent e) { - passed_2 = true; - } - - public void mousePressed(MouseEvent e) { - synchronized (this) { - System.out.println("mouse pressed"); - this.notifyAll(); + private class MouseEnterExitListener extends MouseAdapter { + @Override + public void mouseEntered(MouseEvent e) { + System.out.println("Mouse Entered Event"); + mouseEnterLatch.countDown(); } - } - public boolean isPassed() { - return passed_1 & passed_2; + @Override + public void mouseExited(MouseEvent e) { + System.out.println("Mouse Exited Event"); + mouseExitLatch.countDown(); + } } } diff --git a/test/jdk/java/awt/List/ListScrollbarCursorTest.java b/test/jdk/java/awt/List/ListScrollbarCursorTest.java new file mode 100644 index 00000000000..fc832029b13 --- /dev/null +++ b/test/jdk/java/awt/List/ListScrollbarCursorTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4290684 + * @summary Tests that cursor on the scrollbar of the list is set to default. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ListScrollbarCursorTest + */ + +import java.awt.Cursor; +import java.awt.Frame; +import java.awt.List; +import java.awt.Panel; + +public class ListScrollbarCursorTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. You see the list in the middle of the panel. + This list has two scrollbars. + 2. The cursor should have a shape of hand over the main area + and a shape of arrow over scrollbars. + 3. Move the mouse cursor to either horizontal or vertical scrollbar. + 4. Press PASS if you see the default arrow cursor else press FAIL. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ListScrollbarCursorTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame frame = new Frame("List Scrollbar Cursor Test"); + Panel panel = new Panel(); + List list = new List(3); + list.add("List item with a very long name" + + "(just to make the horizontal scrollbar visible)"); + list.add("Item 2"); + list.add("Item 3"); + list.setCursor(new Cursor(Cursor.HAND_CURSOR)); + panel.add(list); + frame.add(panel); + frame.setSize(200, 200); + return frame; + } +} diff --git a/test/jdk/java/awt/List/ListScrollbarTest.java b/test/jdk/java/awt/List/ListScrollbarTest.java new file mode 100644 index 00000000000..b676303b927 --- /dev/null +++ b/test/jdk/java/awt/List/ListScrollbarTest.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4096445 + * @summary Test to verify List Scollbar appears/disappears automatically + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ListScrollbarTest + */ + +import java.awt.Button; +import java.awt.Component; +import java.awt.Event; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.List; + +public class ListScrollbarTest extends Frame { + static final int ITEMS = 10; + List ltList; + List rtList; + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. There are two lists added to the Frame separated by + a column of buttons + 2. Double click on any item(s) on the left list, you would see + a '*' added at the end of the item + 3. Keep double clicking on the same item till the length of the + item exceeds the width of the list + 4. Now, if you don't get the horizontal scrollbar on + the left list click FAIL. + 5. If you get horizontal scrollbar, select the item + (that you double clicked) and press the '>' button + to move the item to the right list. + 6. If horizontal scroll bar appears on the right list + as well as disappears from the left list [only if both + happen] proceed with step 8 else click FAIL + 7. Now move the same item to the left list, by pressing + '<' button + 8. If the horizontal scrollbar appears on the left list + and disappears from the right list[only if both happen] + click PASS else click FAIL. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ListScrollbarTest::new) + .build() + .awaitAndCheck(); + } + + public ListScrollbarTest() { + super("List scroll bar test"); + GridBagLayout gbl = new GridBagLayout(); + ltList = new List(ITEMS, true); + rtList = new List(0, true); + setLayout(gbl); + add(ltList, 0, 0, 1, 5, 1.0, 1.0); + add(rtList, 2, 0, 1, 5, 1.0, 1.0); + add(new Button(">"), 1, 0, 1, 1, 0, 1.0); + add(new Button(">>"), 1, 1, 1, 1, 0, 1.0); + add(new Button("<"), 1, 2, 1, 1, 0, 1.0); + add(new Button("<<"), 1, 3, 1, 1, 0, 1.0); + add(new Button("!"), 1, 4, 1, 1, 0, 1.0); + + for (int i = 0; i < ITEMS; i++) { + ltList.addItem("item " + i); + } + setSize(220, 250); + } + + void add(Component comp, int x, int y, int w, int h, double weightx, double weighty) { + GridBagLayout gbl = (GridBagLayout) getLayout(); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.gridx = x; + c.gridy = y; + c.gridwidth = w; + c.gridheight = h; + c.weightx = weightx; + c.weighty = weighty; + add(comp); + gbl.setConstraints(comp, c); + } + + void reverseSelections(List l) { + for (int i = 0; i < l.countItems(); i++) { + if (l.isSelected(i)) { + l.deselect(i); + } else { + l.select(i); + } + } + } + + void deselectAll(List l) { + for (int i = 0; i < l.countItems(); i++) { + l.deselect(i); + } + } + + void replaceItem(List l, String item) { + for (int i = 0; i < l.countItems(); i++) { + if (l.getItem(i).equals(item)) { + l.replaceItem(item + "*", i); + } + } + } + + void move(List l1, List l2, boolean all) { + + // if all the items are to be moved + if (all) { + for (int i = 0; i < l1.countItems(); i++) { + l2.addItem(l1.getItem(i)); + } + l1.delItems(0, l1.countItems() - 1); + } else { // else move the selected items + String[] items = l1.getSelectedItems(); + int[] itemIndexes = l1.getSelectedIndexes(); + + deselectAll(l2); + for (int i = 0; i < items.length; i++) { + l2.addItem(items[i]); + l2.select(l2.countItems() - 1); + if (i == 0) { + l2.makeVisible(l2.countItems() - 1); + } + } + for (int i = itemIndexes.length - 1; i >= 0; i--) { + l1.delItem(itemIndexes[i]); + } + } + } + + @Override + public boolean action(Event evt, Object arg) { + if (">".equals(arg)) { + move(ltList, rtList, false); + } else if (">>".equals(arg)) { + move(ltList, rtList, true); + } else if ("<".equals(arg)) { + move(rtList, ltList, false); + } else if ("<<".equals(arg)) { + move(rtList, ltList, true); + } else if ("!".equals(arg)) { + if (ltList.getSelectedItems().length > 0) { + reverseSelections(ltList); + } else if (rtList.getSelectedItems().length > 0) { + reverseSelections(rtList); + } + } else if (evt.target == rtList || evt.target == ltList) { + replaceItem((List) evt.target, (String) arg); + } else { + return false; + } + return true; + } + + @Override + public boolean handleEvent(Event evt) { + if (evt.id == Event.LIST_SELECT + || evt.id == Event.LIST_DESELECT) { + if (evt.target == ltList) { + deselectAll(rtList); + } else if (evt.target == rtList) { + deselectAll(ltList); + } + return true; + } + return super.handleEvent(evt); + } +} diff --git a/test/jdk/java/awt/Menu/MenuActionEventTest.java b/test/jdk/java/awt/Menu/MenuActionEventTest.java new file mode 100644 index 00000000000..70fcc81ac86 --- /dev/null +++ b/test/jdk/java/awt/Menu/MenuActionEventTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4094620 + * @summary MenuItem.enableEvents does not work + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MenuActionEventTest + */ + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.event.ActionEvent; + +public class MenuActionEventTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Click on the Menu and then on Menuitem on the frame. + 2. If you find the following message being printed in + the test log area:, + _MenuItem: action event", + click PASS, else click FAIL" + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(MenuActionEventTest::initialize) + .logArea() + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame f = new Frame("Menu Action Event Test"); + f.setLayout(new BorderLayout()); + f.setMenuBar(new MenuBar()); + Menu m = new _Menu("Menu"); + MenuBar mb = f.getMenuBar(); + mb.add(m); + MenuItem mi = new _MenuItem("Menuitem"); + m.add(mi); + f.setBounds(204, 152, 396, 300); + return f; + } + + static class _Menu extends Menu { + public _Menu(String text) { + super(text); + enableEvents(AWTEvent.ACTION_EVENT_MASK); + } + + @Override + protected void processActionEvent(ActionEvent e) { + PassFailJFrame.log("_Menu: action event"); + super.processActionEvent(e); + } + } + + static class _MenuItem extends MenuItem { + public _MenuItem(String text) { + super(text); + enableEvents(AWTEvent.ACTION_EVENT_MASK); + } + + @Override + protected void processActionEvent(ActionEvent e) { + PassFailJFrame.log("_MenuItem: action event"); + super.processActionEvent(e); + } + } + +} diff --git a/test/jdk/java/awt/Menu/MenuVisibilityTest.java b/test/jdk/java/awt/Menu/MenuVisibilityTest.java new file mode 100644 index 00000000000..cb74cd56e1a --- /dev/null +++ b/test/jdk/java/awt/Menu/MenuVisibilityTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 5046491 6423258 + * @summary CheckboxMenuItem: menu text is missing from test frame + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MenuVisibilityTest +*/ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; + +public class MenuVisibilityTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Press on a MenuBar with a long name. + 2. Select "First item" in an opened menu. + If you see that "First menu item was pressed" in + the test log area, press PASS + Otherwise press FAIL" + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(MenuVisibilityTest::initialize) + .logArea() + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Menu visibility test"); + String menuTitle = "I_have_never_seen_so_long_Menu_Title_" + + "!_ehe-eha-ehu-ehi_ugu-gu!!!_;)_BANG_BANG..."; + MenuBar menubar = new MenuBar(); + Menu menu = new Menu(menuTitle); + MenuItem menuItem = new MenuItem("First item"); + menuItem.addActionListener(e -> + PassFailJFrame.log("First menu item was pressed.")); + menu.add(menuItem); + menubar.add(menu); + frame.setMenuBar(menubar); + frame.setSize(100, 200); + return frame; + } +} diff --git a/test/jdk/java/awt/Menu/RmInHideTest.java b/test/jdk/java/awt/Menu/RmInHideTest.java new file mode 100644 index 00000000000..b2d68400647 --- /dev/null +++ b/test/jdk/java/awt/Menu/RmInHideTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4039387 + * @summary Checks that calling Frame.remove() within hide() doesn't + * cause SEGV + * @key headful + * @run main RmInHideTest + */ + +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; + +public class RmInHideTest { + static volatile Point point; + static RmInHideTestFrame frame; + static volatile Dimension dimension; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new RmInHideTestFrame(); + frame.setSize(200, 200); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + EventQueue.invokeAndWait(() -> { + point = frame.getButtonLocation(); + dimension = frame.getButtonDimension(); + }); + robot.mouseMove(point.x + dimension.width / 2, point.y + dimension.height / 2); + robot.mousePress(MouseEvent.BUTTON2_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON2_DOWN_MASK); + robot.waitForIdle(); + robot.delay(100); + System.out.println("Test pass"); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static class RmInHideTestFrame extends Frame implements ActionListener { + MenuBar menubar = null; + Button b; + + public RmInHideTestFrame() { + super("RmInHideTest"); + b = new Button("Hide"); + b.setActionCommand("hide"); + b.addActionListener(this); + add("Center", b); + + MenuBar bar = new MenuBar(); + + Menu menu = new Menu("Test1", true); + menu.add(new MenuItem("Test1A")); + menu.add(new MenuItem("Test1B")); + menu.add(new MenuItem("Test1C")); + bar.add(menu); + + menu = new Menu("Test2", true); + menu.add(new MenuItem("Test2A")); + menu.add(new MenuItem("Test2B")); + menu.add(new MenuItem("Test2C")); + bar.add(menu); + setMenuBar(bar); + } + + @Override + public Dimension minimumSize() { + return new Dimension(200, 200); + } + + @Override + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + if (cmd.equals("hide")) { + hide(); + try { + Thread.currentThread().sleep(2000); + } catch (InterruptedException ex) { + // do nothing + } + show(); + } + } + + @Override + public void hide() { + menubar = getMenuBar(); + if (menubar != null) { + remove(menubar); + } + super.hide(); + } + + + @Override + public void show() { + if (menubar != null) { + setMenuBar(menubar); + } + super.show(); + } + + public Point getButtonLocation() { + return b.getLocationOnScreen(); + } + + public Dimension getButtonDimension() { + return b.getSize(); + } + } +} diff --git a/test/jdk/java/awt/Menu/SetShortCutTest.java b/test/jdk/java/awt/Menu/SetShortCutTest.java new file mode 100644 index 00000000000..b60b83dff9a --- /dev/null +++ b/test/jdk/java/awt/Menu/SetShortCutTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4203208 + * @summary setShortcut method does not display proper text on Menu component + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SetShortCutTest + */ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.MenuShortcut; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + +import static java.awt.event.KeyEvent.VK_META; +import static java.awt.event.KeyEvent.VK_SHIFT; + +public class SetShortCutTest { + public static void main(String[] args) throws Exception { + boolean isMac = System.getProperty("os.name").startsWith("Mac"); + String shortcut = "Ctrl+Shift+"; + if (isMac) { + shortcut = KeyEvent.getKeyText(VK_SHIFT) + "+" + KeyEvent.getKeyText(VK_META); + } + + String INSTRUCTIONS = """ + 1. Select menuitem 'Stuff -> Second' once to remove 'File -> First'. + 2. Select menuitem 'Stuff -> Second' again to add 'File -> First'. + 3. If menuitem 'File -> First' reads First """ + shortcut + """ + 'C', press PASS. Otherwise press FAIL. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(SetShortCutTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + return new TestMenuShortCut(); + } + + static class TestMenuShortCut extends Frame implements ActionListener { + Menu menu1; + MenuItem item1; + MenuItem item2; + boolean beenHere; + + public TestMenuShortCut() { + setTitle("Set ShortCut test"); + beenHere = false; + MenuBar mTopMenu = buildMenu(); + setSize(300, 300); + this.setMenuBar(mTopMenu); + } + + public MenuBar buildMenu() { + MenuBar bar; + bar = new MenuBar(); + menu1 = new Menu("File"); + item1 = new MenuItem("First"); + menu1.add(item1); + item1.setShortcut(new MenuShortcut(KeyEvent.VK_C, true)); + bar.add(menu1); + + // Stuff menu + item2 = new MenuItem("Second"); + Menu menu2 = new Menu("Stuff"); + menu2.add(item2); + item2.setShortcut(new MenuShortcut(KeyEvent.VK_C, false)); + bar.add(menu2); + + item1.addActionListener(this); + item2.addActionListener(this); + return bar; + } + + @Override + public void actionPerformed(ActionEvent event) { + if (event.getSource() == item1) { + Frame temp = new Frame("Accelerator key is working for 'First'"); + temp.setSize(300, 50); + temp.setVisible(true); + } + + // Click on the "Stuff" menu to remove the "first" menu item + else if (event.getSource() == item2) { + // If the item has not been removed from the menu, + // then remove "First" from the "File" menu + if (beenHere == false) { + item1.removeActionListener(this); + menu1.remove(item1); + beenHere = true; + } else { + item1 = new MenuItem("First"); + menu1.add(item1); + item1.addActionListener(this); + item1.setShortcut(new MenuShortcut(KeyEvent.VK_C, true)); + beenHere = false; + } + } + } + } +} diff --git a/test/jdk/java/awt/Modal/AddRemoveTransientForsTest.java b/test/jdk/java/awt/Modal/AddRemoveTransientForsTest.java new file mode 100644 index 00000000000..65b66e8ce8d --- /dev/null +++ b/test/jdk/java/awt/Modal/AddRemoveTransientForsTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Dialog; +import java.awt.Frame; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +/* + * @test + * @bug 6271779 + * @summary This test shows and hides a modal dialog several times without destroying its + * peer. Without the fix this may lead to application (or even WM) hang. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AddRemoveTransientForsTest + */ + +public class AddRemoveTransientForsTest { + + private static Dialog d1; + private static Dialog d2; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + When the test starts, a frame is shown with a button 'Show Dialog D1'. + + 1. Press the button 'Show Dialog D1' to show a modal dialog D1 with a button + 'Show dialog D2'. + + 2. Press the button 'Show dialog D2' to show another modal dialog D2 with a button + 'Close'. + + 3. Press the button 'Close' to close dialog D2. + + 4. Repeat steps 2 and 3 several times (at least 3-4 times). + + If the application is not hung, press Pass. + + NOTE: all the modal dialogs must be closed before pressing Pass button."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(AddRemoveTransientForsTest::init) + .build() + .awaitAndCheck(); + } + + public static Frame init() { + Frame f = new Frame("AddRemoveTransientForsTest Frame"); + Button b = new Button("Show dialog D1"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + d1.setVisible(true); + } + }); + f.add(b); + f.setSize(200, 100); + + WindowListener wl = new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) + { + e.getWindow().dispose(); + } + }; + + d1 = new Dialog(f, "D1", true); + d1.setBounds(200, 200, 200, 100); + d1.addWindowListener(wl); + Button b1 = new Button("Show dialog D2"); + b1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + d2.setVisible(true); + } + }); + d1.add(b1); + + d2 = new Dialog(d1, "D2", true); + d2.setBounds(300, 300, 200, 100); + Button b2 = new Button("Close"); + b2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + d2.setVisible(false); + } + }); + d2.add(b2); + + return f; + } +} diff --git a/test/jdk/java/awt/Modal/DialogLosesFocusTest.java b/test/jdk/java/awt/Modal/DialogLosesFocusTest.java new file mode 100644 index 00000000000..738c2c29ee2 --- /dev/null +++ b/test/jdk/java/awt/Modal/DialogLosesFocusTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +/* + * @test + * @bug 6278150 + * @key headful + * @summary Initially modal blocked window causes modal dialog to lose focus + * @run main DialogLosesFocusTest + */ + +public class DialogLosesFocusTest { + private static Frame parent; + private static Dialog dialog; + private static Frame blocked; + private static volatile boolean failed; + + public static void main(String[] args) throws Exception { + try { + createAndShowUI(); + + sleepForMsecs(10000); + + if (failed) { + throw new RuntimeException("Test Failed"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (parent != null) { + parent.dispose(); + } + if (dialog != null) { + dialog.dispose(); + } + if (blocked != null) { + blocked.dispose(); + } + }); + } + } + + public static void createAndShowUI() throws Exception { + EventQueue.invokeAndWait(() -> { + parent = new Frame("Parent frame"); + parent.setBounds(0, 0, 300, 100); + parent.setVisible(true); + }); + + sleepForMsecs(1000); + + EventQueue.invokeLater(() -> { + dialog = new Dialog(parent, "Modal dialog", Dialog.ModalityType.APPLICATION_MODAL); + dialog.setBounds(100, 120, 300, 100); + dialog.setVisible(true); + }); + + sleepForMsecs(1000); + + EventQueue.invokeAndWait(() -> { + blocked = new Frame("Blocked frame"); + blocked.setBounds(200, 240, 300, 100); + blocked.addWindowListener(new WindowAdapter() { + @Override + public void windowActivated(WindowEvent we) { + if (dialog.isVisible()) { + failed = true; + } + } + }); + blocked.setVisible(true); + }); + } + + private static void sleepForMsecs(int t) { + try { + Thread.sleep(t); + } catch (Exception z) {} + } +} diff --git a/test/jdk/java/awt/Modal/NativeDialogToFrontBackTest.java b/test/jdk/java/awt/Modal/NativeDialogToFrontBackTest.java new file mode 100644 index 00000000000..6c41ef73b1e --- /dev/null +++ b/test/jdk/java/awt/Modal/NativeDialogToFrontBackTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Dialog; +import java.awt.FileDialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.util.List; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.print.PageFormat; +import java.awt.print.PrinterJob; + +/* + * @test + * @bug 6393608 + * @summary Tests that toBack/toFront methods works correctly for native dialogs + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NativeDialogToFrontBackTest + */ + +public class NativeDialogToFrontBackTest { + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + When the test starts two frames appear: 'Control' and 'Blocked' + 1. Click on the 'Show file dialog' button + 2. Drag the file dialog so it partially overlaps the 'Blocked' frame + 3. 'Blocked' frame must be below the file dialog, if not - press Fail + 3. Click on the 'Blocked to front' button + 4. 'Blocked' frame must still be below the file dialog, if not - press Fail + 5. Close the file dialog + 6. Repeat steps 2 to 4 with print and page dialogs using the corresponding button + 7. If 'Blocked' frame is always below File/Print/Page dialog, press Pass"""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(NativeDialogToFrontBackTest::init) + .positionTestUI(WindowLayouts::rightOneColumn) + .build() + .awaitAndCheck(); + } + + public static List init() { + Frame blocked = new Frame("Blocked"); + blocked.setSize(200, 200); + + Frame control = new Frame("Control"); + control.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); + control.setLayout(new FlowLayout()); + + Button showFileDialog = new Button("Show file dialog"); + showFileDialog.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + new FileDialog(control, "File dialog").setVisible(true); + } + }); + control.add(showFileDialog); + + Button showPrintDialog = new Button("Show print dialog"); + showPrintDialog.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + PrinterJob.getPrinterJob().printDialog(); + } + }); + control.add(showPrintDialog); + + Button showPageDialog = new Button("Show page dialog"); + showPageDialog.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + PrinterJob.getPrinterJob().pageDialog(new PageFormat()); + } + }); + control.add(showPageDialog); + + Button blockedToFront = new Button("Blocked to front"); + blockedToFront.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + blocked.toFront(); + } + }); + control.add(blockedToFront); + + control.setSize(200, 200); + return List.of(control, blocked); + } +} diff --git a/test/jdk/java/awt/Multiscreen/DialogTest.java b/test/jdk/java/awt/Multiscreen/DialogTest.java new file mode 100644 index 00000000000..fbd72bfd6f0 --- /dev/null +++ b/test/jdk/java/awt/Multiscreen/DialogTest.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Point; +import java.awt.ScrollPane; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.WindowConstants; + +import jtreg.SkippedException; + +/* + * @test + * @bug 4368500 + * @key multimon + * @summary Dialog needs a constructor with GraphicsConfiguration + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual DialogTest + */ + +public class DialogTest { + static GraphicsDevice[] gds; + + private static Frame f; + private static Frame dummyFrame = new Frame(); + private static Dialog dummyDialog = new Dialog(dummyFrame); + + public static void main(String[] args) throws Exception { + gds = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + if (gds.length < 2) { + throw new SkippedException("You have only one monitor in your system" + + " - test skipped"); + } + + String INSTRUCTIONS = """ + This test tests the multiscreen functionality of Dialogs and JDialogs. + You should see the message "X screens detected", where X + is the number of screens on your system. If X is incorrect, press Fail. + + In the test window, there are a list of buttons representing each + type of dialog for each screen. + If there aren't buttons for every screen in your system, press Fail. + + Press each button, and the indicated type of dialog should appear + on the indicated screen. + Modal dialogs should not allow to click on the Instructions or + DialogTest windows. + + The buttons turn yellow once they have been pressed, to keep track + of test progress. + + If all Dialogs appear correctly, press Pass. + If Dialogs appear on the wrong screen or don't behave in + proper modality, press Fail."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .logArea(5) + .testUI(DialogTest::init) + .build() + .awaitAndCheck(); + } + + public static Frame init() { + PassFailJFrame.log(gds.length + " screens detected."); + f = new Frame("DialogTest UI"); + f.setSize(400, 400); + MyScrollPane sp = new MyScrollPane(); + + Panel p = new Panel(); + p.setLayout(new GridLayout(0, 1)); + + for (int i = 0; i < gds.length; i++) { + Button btn; + + //screen # , modal, frame-owned, swing + btn = new MyButton(new DialogInfo(i, false, false, false)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, true, false, false)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, false, true, false)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, true, true, false)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, false, false, true)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, true, false, true)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, false, true, true)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, true, true, true)); + p.add(btn); + + } + sp.add(p); + f.add(sp); + return f; + } + + static class MyScrollPane extends ScrollPane { + @Override + public Dimension getPreferredSize() { + return f.getSize(); + } + } + + static class MyButton extends Button { + public MyButton(DialogInfo info) { + setLabel(info.toString()); + addActionListener(new PutupDialog(info)); + } + } + + static class PutupDialog implements ActionListener { + DialogInfo info; + + public PutupDialog(DialogInfo info) { + this.info = info; + } + + @Override + public void actionPerformed(ActionEvent e) { + ((Button) (e.getSource())).setBackground(Color.yellow); + Dialog d = info.createDialog(); + d.show(); + } + } + + static class DialogInfo { + int num; + boolean modal; + boolean frameOwned; + boolean swing; + + public DialogInfo(int num, boolean modal, boolean frameOwned, boolean swing) { + this.num = num; + this.modal = modal; + this.frameOwned = frameOwned; + this.swing = swing; + } + + public Dialog createDialog() { + GraphicsConfiguration gc = gds[num].getDefaultConfiguration(); + + Dialog d; + + if (swing) { + if (frameOwned) { + d = new JDialog(dummyFrame, toString(), modal, gc); + } else { + d = new JDialog(dummyDialog, toString(), modal, gc); + } + + ((JDialog) d).setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); + if (modal) { + ((JDialog) d).getContentPane().add(new JLabel("Check that I am modal!")); + } + } else { + if (frameOwned) { + d = new Dialog(dummyFrame, toString(), modal, gc); + } else { + d = new Dialog(dummyDialog, toString(), modal, gc); + } + + d.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + e.getComponent().hide(); + } + }); + if (modal) { + d.add(new Label("Check that I am modal!")); + } + } + + d.setLocation(new Point((int) (gc.getBounds().getX() + 20) + , (int) (gc.getBounds().getY() + 20))); + d.setSize(300, 100); + + return d; + } + + public String toString() { + return "Screen " + num + (frameOwned ? " Frame-owned" : " Dialog-owned") + + (modal ? " modal " : " non-modal ") + + (swing ? "JDialog" : "Dialog"); + } + } +} + + diff --git a/test/jdk/java/awt/Multiscreen/FillThisScreen.java b/test/jdk/java/awt/Multiscreen/FillThisScreen.java new file mode 100644 index 00000000000..542127827ec --- /dev/null +++ b/test/jdk/java/awt/Multiscreen/FillThisScreen.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.GridLayout; +import java.awt.Rectangle; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import jtreg.SkippedException; + +/* + * @test + * @bug 4356756 + * @key multimon + * @summary Return all screen devices for physical and virtual display devices + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual FillThisScreen + */ + +public class FillThisScreen { + private static Frame f; + private static Button b; + private static Rectangle oldSize; + private static boolean fillmode = true; + static GraphicsDevice[] gs; + + public static void main(String[] args) throws Exception { + gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + if (gs.length < 2) { + throw new SkippedException("You have only one monitor in your system" + + " - test skipped"); + } + + String INSTRUCTIONS = """ + This test is for testing the bounds of a multimonitor system. + You will see a Frame with several buttons: one marked 'Fill + This Screen' and an additional button for each display on your system. + + First, drag the Frame onto each display and click the + 'Fill This Screen' button. + + The Frame should resize to take up the entire display area + of the screen it is on, and the button text changes to say, + 'Get Smaller'. + + Click the button again to restore the Frame. + + Next, use the 'Move to screen' buttons to move the Frame to + each display and again click the 'Fill This Screen' button. + + If the number of 'Move to Screen' buttons is not equals to + the number of screens on your system, the test fails. + + If the Frame always correctly resizes to take up ONLY the + entire screen it is on (and not a different screen, or all + screens), the test passes else it fails."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(FillThisScreen::init) + .build() + .awaitAndCheck(); + } + + public static Frame init() { + Button tempBtn; + + f = new Frame("Drag Me Around"); + f.setLayout(new GridLayout(0, 1)); + + b = new Button("Fill This Screen"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (fillmode) { + oldSize = f.getBounds(); + Rectangle r = f.getGraphicsConfiguration().getBounds(); + f.setBounds(r); + b.setLabel("Get Smaller"); + } else { + f.setBounds(oldSize); + b.setLabel("Fill This Screen"); + } + fillmode = !fillmode; + } + }); + f.add(b); + + for (int i = 0; i < gs.length; i++) { + tempBtn = new Button("Move to screen:" + i); + tempBtn.addActionListener(new WinMover(i)); + f.add(tempBtn); + } + f.setSize(300, 100); + return f; + } + + private static class WinMover implements ActionListener { + int scrNum; + + public WinMover(int scrNum) { + this.scrNum = scrNum; + } + + public void actionPerformed(ActionEvent e) { + Rectangle newBounds = gs[scrNum].getDefaultConfiguration().getBounds(); + f.setLocation(newBounds.x + newBounds.width / 2, + newBounds.y + newBounds.height / 2); + } + + } +} diff --git a/test/jdk/java/awt/Multiscreen/IMCandidateWindowTest.java b/test/jdk/java/awt/Multiscreen/IMCandidateWindowTest.java new file mode 100644 index 00000000000..6af3188156d --- /dev/null +++ b/test/jdk/java/awt/Multiscreen/IMCandidateWindowTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.FlowLayout; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Rectangle; + +import javax.swing.JFrame; +import javax.swing.JTextField; + +import jtreg.SkippedException; + +/* + * @test + * @bug 4805862 + * @key multimon + * @requires (os.family == "windows") + * @summary Tests IM candidate window is positioned correctly for the + * text components inside a window in multiscreen configurations, if + * this window has negative coordinates + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual IMCandidateWindowTest + */ + +public class IMCandidateWindowTest { + static GraphicsConfiguration gc; + + public static void main(String[] args) throws Exception { + GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getScreenDevices(); + if (gds.length < 2) { + throw new SkippedException("You have only one monitor in your system" + + " - test skipped"); + } + + GraphicsDevice gd = null; + + for (int i = 0; i < gds.length; i++) { + gc = gds[i].getDefaultConfiguration(); + if ((gc.getBounds().x < 0) || (gc.getBounds().y < 0)) { + gd = gds[i]; + break; + } + } + + if (gd == null) { + // no screens with negative coords + throw new SkippedException("No screens with negative coords - test skipped"); + } + + String INSTRUCTIONS = """ + This test is for windows + Test requirements: installed support for asian languages + Chinese (PRC) w/ Chinese QuanPing input method. + Multiscreen environment where one of the monitors has negative coords + Go to the text field in the opened Frame. Switch to Chinese language and + start typing "ka". + Note, that IM helper window is appeared. + If this window is appeared near the text field, press PASS button. + If this window is appeared at the edge of the screen or on another + screen, press FAIL button"""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(IMCandidateWindowTest::createUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createUI() { + Rectangle b = gc.getBounds(); + + JFrame f = new JFrame("Frame", gc); + f.setBounds(b.x + b.width / 2 - 150, b.y + b.height / 2 - 100, 300, 200); + f.getContentPane().setLayout(new FlowLayout()); + JTextField tf = new JTextField(10); + f.getContentPane().add(tf); + return f; + } +} diff --git a/test/jdk/java/awt/PrintJob/PrintCompatibilityTest.java b/test/jdk/java/awt/PrintJob/PrintCompatibilityTest.java new file mode 100644 index 00000000000..a2433f45547 --- /dev/null +++ b/test/jdk/java/awt/PrintJob/PrintCompatibilityTest.java @@ -0,0 +1,446 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Canvas; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.JobAttributes; +import java.awt.Label; +import java.awt.List; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.PageAttributes; +import java.awt.Panel; +import java.awt.PrintJob; +import java.awt.Scrollbar; +import java.awt.ScrollPane; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.JobAttributes.DialogType; +import java.awt.PageAttributes.OriginType; + +import java.util.Enumeration; +import java.util.Properties; + +/* + * @test + * @bug 4247583 + * @key printer + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Tests that the old Properties API still works + * @run main/manual PrintCompatibilityTest + */ + +public class PrintCompatibilityTest { + + public static void main(String[] args) throws Exception { + + String INSTRUCTIONS = """ + A frame window will appear. + Choose 'Print to Printer...' from the 'Print' menu. Make sure that you print + to a printer, not a file. Examine the output and verify that the frame and all + the components in it get printed properly. + + Known problems: + * The text in the second row of the menubar is not indented correctly. + + You can also use the 'Print to Screen...' command for a quick manual check that + printing works, but this is only for debugging purposes."""; + + PassFailJFrame.builder() + .title("PrintComponentTest Test Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(60) + .testTimeOut(10) + .testUI(new MainFrame()) + .logArea(8) + .build() + .awaitAndCheck(); + } +} + +class MainFrame extends Frame { + private LWContainer lwc; + + public MainFrame() { + super("PrintCompatibilityTest"); + + setSize(800, 400); + setLayout(new FlowLayout()); + + // peered components + Button button = new Button("Button"); + button.setFont(new Font("Dialog", Font.PLAIN, 12)); + add(button); + add(new TestCanvas()); + Checkbox cbox = new Checkbox("Checkbox", true); + cbox.setFont(new Font("DialogInput", Font.PLAIN, 12)); + add(cbox); + Choice choice = new Choice(); + choice.add("Choice 1"); + choice.add("Choice Two"); + choice.setFont(new Font("Monospaced", Font.PLAIN, 12)); + add(choice); + Label label = new Label("Label"); + label.setFont(new Font("Serif", Font.PLAIN, 12)); + add(label); + List list = new List(); + list.add("List 1"); + list.add("List Two"); + list.setFont(new Font("SansSerif", Font.PLAIN, 12)); + add(list); + add(new Scrollbar(Scrollbar.VERTICAL) ); + add(new Scrollbar(Scrollbar.HORIZONTAL) ); + ScrollPane scrollpane = new ScrollPane(); + Button spButton = new Button("Button in a scrollpane"); + spButton.setFont(new Font("Monospaced", Font.PLAIN, 12)); + scrollpane.add(spButton); + add(scrollpane); + TextArea textarea = new TextArea("TextArea", 3, 30); + textarea.setFont(new Font("Dialog", Font.ITALIC, 10)); + add(textarea); + TextField textfield = new TextField("TextField"); + textfield.setFont(new Font("DialogInput", Font.ITALIC, 10)); + add(textfield); + + // nested components + Panel panel1 = new Panel(); + panel1.setLayout(new FlowLayout()); + panel1.setBackground(Color.red); + this.add(panel1); + + Button p1Button = new Button("level 2"); + p1Button.setFont(new Font("Monospaced", Font.ITALIC, 10)); + panel1.add(p1Button); + + Panel panel2 = new Panel(); + panel2.setLayout(new FlowLayout()); + panel2.setBackground(Color.green); + panel1.add(panel2); + + Button p2Button = new Button("level 3"); + p2Button.setFont(new Font("Serif", Font.ITALIC, 10)); + panel2.add(p2Button); + + + // lightweight components + LWButton lwbutton = new LWButton("LWbutton"); + lwbutton.setFont(new Font("SansSerif", Font.ITALIC, 10)); + add(lwbutton); + + lwc = new LWContainer("LWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainer"); + lwc.setFont(new Font("Monospaced", Font.ITALIC, 10)); + add(lwc); + Button lwcButton1 = new Button("HW Button 1"); + Button lwcButton2 = new Button("HW Button 2"); + LWButton lwcButton3 = new LWButton("LW Button"); + lwcButton1.setFont(new Font("Dialog", Font.BOLD, 14)); + lwcButton2.setFont(new Font("DialogInput", Font.BOLD, 14)); + lwcButton3.setFont(new Font("Monospaced", Font.BOLD, 14)); + lwc.add(lwcButton1); + lwc.add(lwcButton2); + lwc.add(lwcButton3); + + // overlapping components + add(new ZOrderPanel()); + + /////////////////////// + + Menu menu = new Menu("Print"); + Menu menu2 = new Menu("File"); + Menu menu3 = new Menu("Edit"); + Menu menu4 = new Menu("ReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLong"); + menu2.setFont(new Font("SansSerif", Font.BOLD, 20)); + menu2.setEnabled(false); + menu3.setFont(new Font("Monospaced", Font.ITALIC, 18)); + menu3.setEnabled(false); + menu4.setEnabled(false); + MenuItem itemPrinter = new MenuItem("Print to Printer..."); + MenuItem itemScreen = new MenuItem("Print to Screen..."); + menu.add(itemPrinter); + menu.add(itemScreen); + MenuBar menuBar = new MenuBar(); + menuBar.add( menu ); + menuBar.add( menu2 ); + menuBar.add( menu3 ); + menuBar.add( menu4 ); + setMenuBar(menuBar); + + itemPrinter.addActionListener( new ActionPrint() ); + itemScreen.addActionListener( new ActionPrintToScreen() ); + setVisible(true); + } + + static void printProps(Properties props) + { + Enumeration propNames = props.propertyNames(); + while (propNames.hasMoreElements()) { + String propName = (String)propNames.nextElement(); + PassFailJFrame.log( propName + " = " + props.getProperty(propName)); + } + } + + class ActionPrint implements ActionListener { + private final int ITERATIONS = 1; + private Properties props = new Properties(); + + public void actionPerformed(ActionEvent ev) { + PassFailJFrame.log("About to show print dialog..."); + printProps(props); + PrintJob pj = getToolkit().getPrintJob( + MainFrame.this, "Print test!", props); + if (pj == null) { + return; + } + Dimension d = pj.getPageDimension(); + PassFailJFrame.log("About to print..."); + PassFailJFrame.log("Dimensions: " + d); + printProps(props); + + // For xor mode set, there is a printing issue with number of copies to be print. + // So, ITERATIONS are changed to 1 from 3. + // So, for now the XOR related code is commented out. + + //boolean xor = false; + + for (int i = 0; i < ITERATIONS; i++) { + Graphics g = pj.getGraphics(); + g.setColor(Color.red); + //if (xor) { + // g.setXORMode(Color.blue); + //} + g.translate(13, 13); + printAll(g); + g.dispose(); + //xor = (xor) ? false : true; + } + + // For xor mode set, LWC components don't get printed. + // So, for now the code is commented out and separate bug + // (JDK-8340495) is filed to handle it. + + // one more page so that we can test printing a lightweight + // at the top of the hierarchy (BugId 4212564) + //Graphics g = pj.getGraphics(); + //g.setColor(Color.red); + //g.translate(13, 13); + //lwc.printAll(g); + //g.dispose(); + // end 4212564 + + pj.end(); + } + } + + class ActionPrintToScreen implements ActionListener { + public void actionPerformed(ActionEvent ev) { + PrintFrame printFrame = new PrintFrame(MainFrame.this); + printFrame.show(); + Graphics g = printFrame.getGraphics(); + g.setColor(Color.red); + printAll(g); + g.dispose(); + } + } + + // Frame window that displays results of printing + // main window to a screen Graphics-- useful for + // quick testing of printing + class PrintFrame extends Frame + { + private Component printComponent; + public PrintFrame( Component c ) + { + super("Print to Screen"); + printComponent = c ; + addWindowListener( new WindowAdapter() { + public void windowClosing(WindowEvent ev) { + setVisible(false); + dispose(); + } + } + ); + setSize(printComponent.getSize()); + setResizable(false); + } + + public void paint( Graphics g ) { + printComponent.printAll(g); + } + } + + class LWButton extends Component { + String label; + int width = 100; + int height = 30; + + public LWButton(String label) { + super(); + this.label = label; + } + + public void paint(Graphics g) { + Dimension d = getSize(); + g.setColor(Color.orange); + g.setFont(getFont()); + g.fillRect(0, 0, d.width, d.height); + g.setColor(Color.black); + int x = 5; + int y = (d.height - 5); + g.drawString(label, x, y); + } + + public Dimension getPreferredSize() + { + return new Dimension(width, height); + } + } + + class LWContainer extends Container { + String label; + int width = 300; + int height = 100; + + public LWContainer(String label) { + super(); + this.label = label; + setLayout(new FlowLayout()); + } + + public void paint(Graphics g) { + super.paint(g); + Dimension d = getSize(); + g.setColor(Color.green); + g.setFont(getFont()); + g.drawLine(0, 0, d.width - 1, 0); + g.drawLine(d.width - 1, 0, d.width - 1, d.height - 1); + g.drawLine(d.width - 1, d.height - 1, 0, d.height - 1); + g.drawLine(0, d.height - 1, 0, 0); + g.setColor(Color.black); + int x = 5; + int y = (d.height - 5); + g.drawString(label, x, y); + } + + public Dimension getPreferredSize() + { + return new Dimension(width, height); + } + } + + class TestCanvas extends Canvas { + int width = 100; + int height = 100; + + public void paint(Graphics g) { + g.setColor(Color.blue); + g.fillRoundRect(10, 10, 50, 50, 15, 30); + g.setColor(Color.red); + g.fillOval(70, 70, 25, 25); + } + public Dimension getPreferredSize() { + return new Dimension(width, height); + } + } + + class ZOrderPanel extends Panel + { + ZOrderPanel() + { + setLayout(null); + + Component first, second, third, fourth; + + setVisible(true); + // add first component + first = makeBox("Second", Color.blue, + new Font("Serif", Font.BOLD, 14), + -1); + // insert on top + second = makeBox("First", Color.yellow, + new Font("SansSerif", Font.BOLD, 14), + 0); + // put at the back + fourth = makeBox("Fourth", Color.red, + new Font("Monospaced", Font.BOLD, 14), + 2); + // insert in last position + third = makeBox("Third", Color.green, + new Font("Dialog", Font.PLAIN, 12), + 3); + // swap third and fourth to correct positions + remove(third); + add(third, 2); + // re-validate so third and fourth peers change position + validate(); + // now make things really interesting with a lightweight + // component at the top of the z-order, that should print + // _below_ the native guys to match the screen... + add(new LWButton("LWButton"), 0); + } + + public Dimension preferredSize() + { + return new Dimension(260, 80); + } + + public void layout() + { + int i, n; + Insets ins = getInsets(); + n = getComponentCount(); + for (i = n-1; i >= 0; i--) { + Component p = getComponent(i); + p.setBounds(ins.left + 40 * i, ins.top + 5 * i, 60, 60); + } + } + + public Component makeBox(String s, Color c, Font f, int index) + { + Label l = new Label(s); + l.setBackground(c); + l.setAlignment(Label.RIGHT); + l.setFont(f); + add(l, index); + validate(); + return l; + } + } +} diff --git a/test/jdk/java/awt/PrintJob/PrintComponentTest.java b/test/jdk/java/awt/PrintJob/PrintComponentTest.java new file mode 100644 index 00000000000..d568c5a4279 --- /dev/null +++ b/test/jdk/java/awt/PrintJob/PrintComponentTest.java @@ -0,0 +1,486 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Canvas; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.JobAttributes; +import java.awt.Label; +import java.awt.List; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.PageAttributes; +import java.awt.Panel; +import java.awt.PrintJob; +import java.awt.Scrollbar; +import java.awt.ScrollPane; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.JobAttributes.DialogType; +import java.awt.PageAttributes.OriginType; + + +/* + * @test + * @bug 4111262 4035285 4038900 4046147 4049680 4084038 4100004 4105875 + * @bug 4117502 4037486 4068433 4128031 4151161 4151707 4155884 4212564 + * @bug 4025626 4029565 4034365 4036068 4040622 4061890 4067405 4086256 + * @bug 4113827 4116722 4121984 4145350 4146510 4172659 4179886 4218471 + * @bug 4219657 4227128 4242308 4245917 4265746 + * @key printer + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Test printing of lightweight (and heavyweight) components + * @run main/manual PrintComponentTest + */ + +public class PrintComponentTest { + public static void main(String[] args) throws Exception { + + String INSTRUCTIONS = """ + A frame window will appear. + Choose 'Print to Printer...' from the 'Print' menu. Examine the output + and verify that the frame and all the components in it get printed properly. + + Print using both 'Portrait' and 'Landscape' orientation. + Verify that the paper dimensions printed to standard error + are exactly inverted. + (That is, if the output for 'Portrait' is + "Dimensions: java.awt.Dimension[width=612,height=792]" then the output + for 'Landscape' should be "Dimensions: java.awt.Dimension[width=792, height=612].) + + Now, attempt to print a second time. When the print dialog box appears, + however, cancel the print request. + Verify that _no_ output is sent to standard error. + + You should attempt to print with both the native and common print dialogs, + as well as with no dialog. + Note that on Linux the native and common print dialogs are identical. + + On Windows, the common print dialog communicates with the printer to + determine supported paper sizes and duplex capability. + Verify that these constraints are properly enforced in the common dialog + for the target printer. + + Known problems: + * The text in the second row of the menubar is not indented + correctly. + + You can also use the 'Print to Screen...' command for a quick manual + check that printing works, but this is only for debugging purposes."""; + + PassFailJFrame.builder() + .title("PrintComponentTest Test Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(60) + .testTimeOut(10) + .testUI(new MainFrame()) + .logArea(8) + .build() + .awaitAndCheck(); + } +} + +class MainFrame extends Frame { + private LWContainer lwc; + + public MainFrame() { + super("PrintComponentTest"); + + setSize(800, 400); + setLayout(new FlowLayout()); + + // peered components + Button button = new Button("Button"); + button.setFont(new Font("Dialog", Font.PLAIN, 12)); + add(button); + add(new TestCanvas()); + Checkbox cbox = new Checkbox("Checkbox", true); + cbox.setFont(new Font("DialogInput", Font.PLAIN, 12)); + add(cbox); + Choice choice = new Choice(); + choice.add("Choice 1"); + choice.add("Choice Two"); + choice.setFont(new Font("Monospaced", Font.PLAIN, 12)); + add(choice); + Label label = new Label("Label"); + label.setFont(new Font("Serif", Font.PLAIN, 12)); + add(label); + List list = new List(); + list.add("List 1"); + list.add("List Two"); + list.setFont(new Font("SansSerif", Font.PLAIN, 12)); + add(list); + add(new Scrollbar(Scrollbar.VERTICAL) ); + add(new Scrollbar(Scrollbar.HORIZONTAL) ); + ScrollPane scrollpane = new ScrollPane(); + Button spButton = new Button("Button in a scrollpane"); + spButton.setFont(new Font("Monospaced", Font.PLAIN, 12)); + scrollpane.add(spButton); + add(scrollpane); + TextArea textarea = new TextArea("TextArea", 3, 30); + textarea.setFont(new Font("Dialog", Font.ITALIC, 10)); + add(textarea); + TextField textfield = new TextField("TextField"); + textfield.setFont(new Font("DialogInput", Font.ITALIC, 10)); + add(textfield); + + // nested components + Panel panel1 = new Panel(); + panel1.setLayout(new FlowLayout()); + panel1.setBackground(Color.red); + this.add(panel1); + + Button p1Button = new Button("level 2"); + p1Button.setFont(new Font("Monospaced", Font.ITALIC, 10)); + panel1.add(p1Button); + + Panel panel2 = new Panel(); + panel2.setLayout(new FlowLayout()); + panel2.setBackground(Color.green); + panel1.add(panel2); + + Button p2Button = new Button("level 3"); + p2Button.setFont(new Font("Serif", Font.ITALIC, 10)); + panel2.add(p2Button); + + + // lightweight components + LWButton lwbutton = new LWButton("LWbutton"); + lwbutton.setFont(new Font("SansSerif", Font.ITALIC, 10)); + add(lwbutton); + + lwc = new LWContainer("LWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainerLWContainer"); + lwc.setFont(new Font("Monospaced", Font.ITALIC, 10)); + add(lwc); + Button lwcButton1 = new Button("HW Button 1"); + Button lwcButton2 = new Button("HW Button 2"); + LWButton lwcButton3 = new LWButton("LW Button"); + lwcButton1.setFont(new Font("Dialog", Font.BOLD, 14)); + lwcButton2.setFont(new Font("DialogInput", Font.BOLD, 14)); + lwcButton3.setFont(new Font("Monospaced", Font.BOLD, 14)); + lwc.add(lwcButton1); + lwc.add(lwcButton2); + lwc.add(lwcButton3); + + // overlapping components + add(new ZOrderPanel()); + + /////////////////////// + + Menu menu = new Menu("Print"); + Menu menu2 = new Menu("File"); + Menu menu3 = new Menu("Edit"); + Menu menu4 = new Menu("ReallyReallyReallyReallyReallyReallyReallyReally" + + "ReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReally" + + "ReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLong"); + menu2.setFont(new Font("SansSerif", Font.BOLD, 20)); + menu2.setEnabled(false); + menu3.setFont(new Font("Monospaced", Font.ITALIC, 18)); + menu3.setEnabled(false); + menu4.setEnabled(false); + MenuItem itemJFC = + new MenuItem("Print to Printer with Cross-Platform Dialog..."); + itemJFC.setActionCommand("common"); + MenuItem itemNative = + new MenuItem("Print to Printer with Native Dialog..."); + itemNative.setActionCommand("native"); + MenuItem itemBackground = + new MenuItem("Print to Printer in Background"); + itemBackground.setActionCommand("none"); + MenuItem itemScreen = new MenuItem("Print to Screen..."); + menu.add(itemJFC); + menu.add(itemNative); + menu.add(itemBackground); + menu.add(itemScreen); + MenuBar menuBar = new MenuBar(); + menuBar.add( menu ); + menuBar.add( menu2 ); + menuBar.add( menu3 ); + menuBar.add( menu4 ); + setMenuBar(menuBar); + + ActionPrint actionPrint = new ActionPrint(); + + itemJFC.addActionListener( actionPrint ); + itemNative.addActionListener( actionPrint ); + itemBackground.addActionListener( actionPrint ); + itemScreen.addActionListener( new ActionPrintToScreen() ); + } + + class ActionPrint implements ActionListener { + private final int ITERATIONS = 1; + private PageAttributes pageAttributes = new PageAttributes(); + private JobAttributes jobAttributes = new JobAttributes(); + + public void actionPerformed(ActionEvent ev) { + DialogType dialog; + if (ev.getActionCommand().equals("common")) { + dialog = DialogType.COMMON; + } else if (ev.getActionCommand().equals("native")) { + dialog = DialogType.NATIVE; + } else { + dialog = DialogType.NONE; + } + jobAttributes.setDialog(dialog); + pageAttributes.setOrigin(OriginType.PRINTABLE); + System.err.println(jobAttributes); + System.err.println(pageAttributes); + + PassFailJFrame.log("About to show print dialog..."); + + PrintJob pj = getToolkit().getPrintJob( + MainFrame.this, "Print test!", jobAttributes, pageAttributes); + if (pj == null) { + return; + } + Dimension d = pj.getPageDimension(); + PassFailJFrame.log("About to print..."); + PassFailJFrame.log("Dimensions: " + d); + System.err.println(jobAttributes); + System.err.println(pageAttributes); + + // For xor mode set, there is a printing issue with number of copies to be print. + // So, ITERATIONS are changed to 1 from 3. + // So, for now the XOR related code is commented out. + + //boolean xor = false; + + for (int i = 0; i < ITERATIONS; i++) { + Graphics g = pj.getGraphics(); + g.setColor(Color.red); + //if (xor) { + // g.setXORMode(Color.blue); + //} + printAll(g); + g.dispose(); + //xor = (xor) ? false : true; + } + + // For xor mode set, LWC components don't get printed. + // So, for now the code is commented out and separate bug + // (JDK-8340495) is filed to handle it. + + // one more page so that we can test printing a lightweight + // at the top of the hierarchy (BugId 4212564) + //Graphics g = pj.getGraphics(); + //g.setColor(Color.red); + //lwc.printAll(g); + //g.dispose(); + // end 4212564 + + pj.end(); + } + } + + class ActionPrintToScreen implements ActionListener { + public void actionPerformed(ActionEvent ev) { + PrintFrame printFrame = new PrintFrame(MainFrame.this); + printFrame.show(); + Graphics g = printFrame.getGraphics(); + g.setColor(Color.red); + printAll(g); + g.dispose(); + } + } + + // Frame window that displays results of printing + // main window to a screen Graphics-- useful for + // quick testing of printing + class PrintFrame extends Frame + { + private Component printComponent; + public PrintFrame( Component c ) + { + super("Print to Screen"); + printComponent = c ; + addWindowListener( new WindowAdapter() { + public void windowClosing(WindowEvent ev) { + setVisible(false); + dispose(); + } + } + ); + setSize(printComponent.getSize()); + setResizable(false); + } + + public void paint( Graphics g ) { + printComponent.printAll(g); + } + } + + class LWButton extends Component { + String label; + int width = 100; + int height = 30; + + public LWButton(String label) { + super(); + this.label = label; + } + + public void paint(Graphics g) { + Dimension d = getSize(); + g.setColor(Color.orange); + g.setFont(getFont()); + g.fillRect(0, 0, d.width, d.height); + g.setColor(Color.black); + int x = 5; + int y = (d.height - 5); + g.drawString(label, x, y); + } + + public Dimension getPreferredSize() + { + return new Dimension(width, height); + } + } + + class LWContainer extends Container { + String label; + int width = 300; + int height = 100; + + public LWContainer(String label) { + super(); + this.label = label; + setLayout(new FlowLayout()); + } + + public void paint(Graphics g) { + super.paint(g); + Dimension d = getSize(); + g.setColor(Color.green); + g.setFont(getFont()); + g.drawLine(0, 0, d.width - 1, 0); + g.drawLine(d.width - 1, 0, d.width - 1, d.height - 1); + g.drawLine(d.width - 1, d.height - 1, 0, d.height - 1); + g.drawLine(0, d.height - 1, 0, 0); + g.setColor(Color.black); + int x = 5; + int y = (d.height - 5); + g.drawString(label, x, y); + } + + public Dimension getPreferredSize() + { + return new Dimension(width, height); + } + } + + class TestCanvas extends Canvas { + int width = 100; + int height = 100; + + public void paint(Graphics g) { + g.setColor(Color.blue); + g.fillRoundRect(10, 10, 50, 50, 15, 30); + g.setColor(Color.red); + g.fillOval(70, 70, 25, 25); + } + public Dimension getPreferredSize() { + return new Dimension(width, height); + } + } + + class ZOrderPanel extends Panel + { + ZOrderPanel() + { + setLayout(null); + + Component first, second, third, fourth; + + setVisible(true); + // add first component + first = makeBox("Second", Color.blue, + new Font("Serif", Font.BOLD, 14), + -1); + // insert on top + second = makeBox("First", Color.yellow, + new Font("SansSerif", Font.BOLD, 14), + 0); + // put at the back + fourth = makeBox("Fourth", Color.red, + new Font("Monospaced", Font.BOLD, 14), + 2); + // insert in last position + third = makeBox("Third", Color.green, + new Font("Dialog", Font.PLAIN, 12), + 3); + // swap third and fourth to correct positions + remove(third); + add(third, 2); + // re-validate so third and fourth peers change position + validate(); + // now make things really interesting with a lightweight + // component at the top of the z-order, that should print + // _below_ the native guys to match the screen... + add(new LWButton("LWButton"), 0); + } + + public Dimension preferredSize() + { + return new Dimension(260, 80); + } + + public void layout() + { + int i, n; + Insets ins = getInsets(); + n = getComponentCount(); + for (i = n-1; i >= 0; i--) { + Component p = getComponent(i); + p.setBounds(ins.left + 40 * i, ins.top + 5 * i, 60, 60); + } + } + + public Component makeBox(String s, Color c, Font f, int index) + { + Label l = new Label(s); + l.setBackground(c); + l.setAlignment(Label.RIGHT); + l.setFont(f); + add(l, index); + validate(); + return l; + } + } +} diff --git a/test/jdk/java/awt/PrintJob/ScaledImagePrintingTest.java b/test/jdk/java/awt/PrintJob/ScaledImagePrintingTest.java new file mode 100644 index 00000000000..838c9210e30 --- /dev/null +++ b/test/jdk/java/awt/PrintJob/ScaledImagePrintingTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.PrintJob; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/* + * @test + * @bug 4257962 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary tests that scaled images are printed at resolution greater than 72dpi + * @run main/manual ScaledImagePrintingTest + */ + +public class ScaledImagePrintingTest { + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + Press 'Print' button from the test UI. + + The test will bring up a print dialog. Select a printer and proceed. + Verify that the output is a series of a horizontal lines in a + rectangular box in the center of the page. + + If output is as mentioned above, press Pass else Fail."""; + + PassFailJFrame.builder() + .title("ScaledImagePrintingTest Test Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(40) + .testTimeOut(5) + .testUI(ScaledImagePrintingTest::createUI) + .logArea(8) + .build() + .awaitAndCheck(); + } + + private static Frame createUI() { + Frame frame = new Frame("ResolutionTest"); + Button b = new Button("Print"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PrintJob pj = frame.getToolkit().getPrintJob(frame, "ResolutionTest", null); + PassFailJFrame.log("Printing code started."); + if (pj != null) { + Graphics g = pj.getGraphics(); + g.setColor(Color.black); + int w = 200; + int h = 200; + Image image = frame.createImage(w, h); + Graphics imageGraphics = image.getGraphics(); + Dimension d = pj.getPageDimension(); + imageGraphics.setColor(Color.black); + for (int i = 0; i < h; i += 20) { + imageGraphics.drawLine(0, i, w, i); + } + g.translate(d.width / 2, d.height / 2); + g.drawImage(image, -w / 8, -h / 8, w / 4, h / 4, frame); + g.setColor(Color.black); + g.drawRect(-w / 4, -h / 4, w / 2, h / 2); + imageGraphics.dispose(); + g.dispose(); + pj.end(); + } + PassFailJFrame.log("Printing code finished."); + } + }); + frame.add(b); + frame.setSize(50, 50); + return frame; + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneAsNeededTest.java b/test/jdk/java/awt/ScrollPane/ScrollPaneAsNeededTest.java new file mode 100644 index 00000000000..e4be90fae31 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneAsNeededTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4152524 + * @summary ScrollPane AS_NEEDED always places scrollbars first time component + * is laid out + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneAsNeededTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Frame; +import java.awt.ScrollPane; + +public class ScrollPaneAsNeededTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. You will see a frame titled 'ScrollPane as needed' + of minimum possible size in the middle of the screen. + 2. If for the first resize of frame(using mouse) to + a very big size(may be, to half the area of the screen) + the scrollbars(any - horizontal, vertical or both) + appear, click FAIL else, click PASS. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPaneAsNeededTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame f = new Frame("ScrollPane as needed"); + f.setLayout(new BorderLayout()); + ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + sp.add(new Button("TEST")); + f.add("Center", sp); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneComponentTest.java b/test/jdk/java/awt/ScrollPane/ScrollPaneComponentTest.java new file mode 100644 index 00000000000..b2fc4c77b63 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneComponentTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4100671 + * @summary removing and adding back ScrollPane component does not work + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneComponentTest + */ + +import java.awt.Adjustable; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class ScrollPaneComponentTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Notice the scrollbars (horizontal and vertical) + in the Frame titled 'ScrollPane Component Test' + 2. Click the button labeled 'Remove and add back + ScrollPane Contents' + 3. If the Scrollbars (horizontal or vertical or both) + disappears in the Frame, then press FAIL, else press PASS. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPaneComponentTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame fr = new Frame("ScrollPane Component Test"); + fr.setLayout(new BorderLayout()); + ScrollTester test = new ScrollTester(); + + fr.add(test); + fr.pack(); + fr.setSize(200, 200); + + Adjustable vadj = test.pane.getVAdjustable(); + Adjustable hadj = test.pane.getHAdjustable(); + vadj.setUnitIncrement(5); + hadj.setUnitIncrement(5); + return fr; + } +} + +class Box extends Component { + public Dimension getPreferredSize() { + System.out.println("asked for size"); + return new Dimension(300, 300); + } + + public void paint(Graphics gr) { + super.paint(gr); + gr.setColor(Color.red); + gr.drawLine(5, 5, 295, 5); + gr.drawLine(295, 5, 295, 295); + gr.drawLine(295, 295, 5, 295); + gr.drawLine(5, 295, 5, 5); + System.out.println("Painted!!"); + } +} + +class ScrollTester extends Panel { + public ScrollPane pane; + private final Box child; + + class Handler implements ActionListener { + public void actionPerformed(ActionEvent e) { + System.out.println("Removing scrollable component"); + pane.remove(child); + System.out.println("Adding back scrollable component"); + pane.add(child); + System.out.println("Done Adding back scrollable component"); + } + } + + public ScrollTester() { + pane = new ScrollPane(); + pane.setSize(200, 200); + child = new Box(); + pane.add(child); + setLayout(new BorderLayout()); + Button changeScrollContents = new Button("Remove and add back ScrollPane Contents"); + changeScrollContents.setBackground(Color.red); + changeScrollContents.addActionListener(new Handler()); + add("North", changeScrollContents); + add("Center", pane); + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneEventType.java b/test/jdk/java/awt/ScrollPane/ScrollPaneEventType.java new file mode 100644 index 00000000000..47b4ae416c1 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneEventType.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4075484 + * @summary Tests that events of different types are generated for the + * corresponding scroll actions. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneEventType + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.ScrollPane; +import java.awt.event.AdjustmentListener; + +public class ScrollPaneEventType { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. This test verifies that when user performs some scrolling operation on + ScrollPane the correct AdjustmentEvent is being generated. + 2. To test this, press on: + - scrollbar's arrows and verify that UNIT event is generated, + - scrollbar's grey area(non-thumb) and verify that BLOCK event is + generated, + - drag scrollbar's thumb and verify that TRACK event is generated + If you see correct events for both scroll bars then test is PASSED. + Otherwise it is FAILED. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPaneEventType::initialize) + .logArea() + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame frame = new Frame("ScrollPane event type test"); + frame.setLayout(new BorderLayout()); + ScrollPane pane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + pane.add(new Button("press") { + public Dimension getPreferredSize() { + return new Dimension(1000, 1000); + } + }); + + AdjustmentListener listener = e -> PassFailJFrame.log(e.toString()); + pane.getHAdjustable().addAdjustmentListener(listener); + pane.getVAdjustable().addAdjustmentListener(listener); + frame.add(pane); + frame.setSize(200, 200); + return frame; + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneFlicker.java b/test/jdk/java/awt/ScrollPane/ScrollPaneFlicker.java new file mode 100644 index 00000000000..3594ff50f54 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneFlicker.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4073822 + * @summary ScrollPane repaints entire window when scrolling fast + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneFlicker + */ + +import java.awt.Button; +import java.awt.Canvas; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Label; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Panel; +import java.awt.Rectangle; +import java.awt.ScrollPane; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.TextField; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +public class ScrollPaneFlicker { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + When scrolling a ScrollPane fast(i.e. holding the down/up arrow + down for a while), the ScrollPane would inexplicably refresh + the entire window. + + 1. Select a type of ScrollPane content from the content menu. + 2. Scroll the content using the up/down/left/right arrows on + the scroll bar. Try scrolling the entire content area using + the scroll arrows-- from top to bottom and left to right. + 3. Verify that the entire pane does not refresh when scrolling + - only the newly exposed areas should be repainting. + 4. Repeat for all content types. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPaneFlicker::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + return new FlickerFrame(); + } +} + +class FlickerFrame extends Frame { + ScrollPane pane; + + public FlickerFrame() { + super("ScrollPane Flicker Test"); + TextPanel textPanel = new TextPanel(); + GradientPanel gradientPanel = new GradientPanel(); + ComponentPanel componentPanel = new ComponentPanel(); + SwingPanel swingPanel = new SwingPanel(); + MenuBar menubar = new MenuBar(); + Menu testMenu = new Menu("Test Options"); + + pane = new ScrollPane(); + pane.getHAdjustable().setUnitIncrement(8); + pane.getVAdjustable().setUnitIncrement(16); + pane.add(textPanel); + add(pane); + + testMenu.add(makeContentItem("Text Lines", textPanel)); + testMenu.add(makeContentItem("Gradient Fill", gradientPanel)); + testMenu.add(makeContentItem("AWT Components", componentPanel)); + testMenu.add(makeContentItem("Swing Components", swingPanel)); + menubar.add(testMenu); + + setMenuBar(menubar); + setSize(400, 300); + } + + public MenuItem makeContentItem(String title, final Component content) { + MenuItem menuItem = new MenuItem(title); + menuItem.addActionListener( + ev -> { + pane.add(content); + pane.validate(); + } + ); + return menuItem; + } +} + +class GradientPanel extends Canvas { + public void paint(Graphics g) { + // just paint something that'll take a while + int x, y; + int width = getSize().width; + int height = getSize().height; + int step = 8; + + for (x = 0; x < width; x += step) { + for (y = 0; y < height; y += step) { + int red = (255 * y) / height; + int green = (255 * x * y) / (width * height); + int blue = (255 * x) / width; + Rectangle bounds = g.getClipBounds(); + Rectangle fbounds = new Rectangle(x, y, x + step, y + step); + if (bounds.intersects(fbounds)) { + Color color = new Color(red, green, blue); + g.setColor(color); + g.fillRect(x, y, x + step, y + step); + } + } + } + } + + public Dimension getPreferredSize() { + return new Dimension(200, 1000); + } +} + +class TextPanel extends Canvas { + public void paint(Graphics g) { + Font font = new Font("SanSerif", Font.ITALIC, 12); + + g.setFont(font); + // just paint something that'll take a while + int x, y; + int width = getWidth(); + int height = getHeight(); + int step = 16; + + for (x = y = 0; y < height; y += step) { + Rectangle bounds = g.getClipBounds(); + Rectangle tbounds = new Rectangle(x, y - 16, x + width, y); + if (bounds.intersects(tbounds)) { + g.drawString(y + " : The quick brown fox jumps over the lazy dog. " + + "The rain in Spain falls mainly on the plain.", x, y); + } + } + } + + public Dimension getPreferredSize() { + return new Dimension(640, 1000); + } +} + +class ComponentPanel extends Panel { + ComponentPanel() { + add(new Label("Label")); + add(new Button("Button")); + add(new Checkbox("Checkbox")); + Choice c = new Choice(); + c.add("choice"); + java.awt.List l = new java.awt.List(); + l.add("list"); + add(new Scrollbar()); + add(new TextField("TextField")); + add(new TextArea("TextArea")); + add(new Panel()); + add(new Canvas()); + } +} + +class SwingPanel extends JPanel { + SwingPanel() { + add(new JLabel("JLabel")); + add(new JButton("JButton")); + add(new JCheckBox("JCheckBox")); + JComboBox c = new JComboBox(); + JList l = new JList(); + add(new JScrollBar()); + add(new JTextField("This is a JTextField with some text in it to make it longer.")); + add(new JTextArea("This is a JTextArea with some text in it to make it longer.")); + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPanePaint.java b/test/jdk/java/awt/ScrollPane/ScrollPanePaint.java new file mode 100644 index 00000000000..0d7b7779018 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPanePaint.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Licensed Materials - Property of IBM + * + * (C) Copyright IBM Corporation 1998 All Rights Reserved. + * + * US Government Users Restricted Rights - Use, duplication or disclosure + * restricted by GSA ADP Schedule Contract with IBM Corp. + */ + +/* + * @test + * @bug 4160721 + * @summary AWT ScrollPane painting problem + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPanePaint + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +public class ScrollPanePaint { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Press the button marked "Toggle" a few times. + 2. The contents of the frame should alternate between + a red panel and a scroll pane containing a green panel. + If this does not happen (specifically, if the scroll + pane does not consistently contain a green panel), + then the test has FAILED. + """; + ScrollPaintTest scrollPaintTest = new ScrollPaintTest(); + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(scrollPaintTest::initialize) + .positionTestUI(WindowLayouts::rightOneColumn) + .build() + .awaitAndCheck(); + } + + private static class ScrollPaintTest implements ActionListener { + static Frame f; + static boolean showScroll; + + public List initialize() { + Frame frame = new Frame("Scrollpane paint test"); + frame.setLayout(new BorderLayout()); + f = new Frame("Scrollpane paint test"); + f.setLayout(new GridLayout(0, 1)); + + Button b = new Button("Toggle"); + b.addActionListener(this); + + frame.add(b, BorderLayout.CENTER); + frame.pack(); + + showScroll = false; + actionPerformed(null); + return List.of(frame, f); + } + + public void actionPerformed(ActionEvent e) { + Container c; + if (!showScroll) { + c = (Container) new TestPanel(new Dimension(100, 100)); + c.setBackground(Color.red); + } else { + c = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + Panel p = new TestPanel(new Dimension(20, 20)); + p.setBackground(Color.green); + c.add(p); + } + + f.removeAll(); + f.add("Center", c); + f.pack(); + showScroll = !showScroll; + } + } + + private static class TestPanel extends Panel { + Dimension dim; + + TestPanel(Dimension d) { + dim = d; + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getPreferredSize() { + return dim; + } + } + +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneSize.java b/test/jdk/java/awt/ScrollPane/ScrollPaneSize.java new file mode 100644 index 00000000000..3130563d4a9 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneSize.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4117404 + * @summary Tests that child component is always at least large as scrollpane + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneSize + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.util.List; + +public class ScrollPaneSize { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Three frames representing the three different ScrollPane scrollbar + policies will appear. + 2. Verify that when you resize the windows, the child component in the + scrollpane always expands to fill the scrollpane. The scrollpane + background is colored red to show any improper bleed through. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(ScrollPaneSize::initialize) + .positionTestUIRightColumn() + .build() + .awaitAndCheck(); + } + + static List initialize() { + return List.of(new ScrollFrame("SCROLLBARS_AS_NEEDED", ScrollPane.SCROLLBARS_AS_NEEDED), + new ScrollFrame("SCROLLBARS_ALWAYS", ScrollPane.SCROLLBARS_ALWAYS), + new ScrollFrame("SCROLLBARS_NEVER", ScrollPane.SCROLLBARS_NEVER)); + } +} + +class ScrollFrame extends Frame { + ScrollFrame(String title, int policy) { + super(title); + setLayout(new GridLayout(1, 1)); + ScrollPane c = new ScrollPane(policy); + c.setBackground(Color.red); + Panel panel = new TestPanel(); + c.add(panel); + add(c); + pack(); + Dimension size = panel.getPreferredSize(); + Insets insets = getInsets(); + setSize(size.width + 45 + insets.right + insets.left, + size.height + 20 + insets.top + insets.bottom); + } +} + +class TestPanel extends Panel { + TestPanel() { + setLayout(new FlowLayout()); + setBackground(Color.white); + + Button b1, b2, b3; + add(b1 = new Button("Button1")); + add(b2 = new Button("Button2")); + add(b3 = new Button("Button3")); + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPanechildViewportTest.java b/test/jdk/java/awt/ScrollPane/ScrollPanechildViewportTest.java new file mode 100644 index 00000000000..0dc0772aeba --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPanechildViewportTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4094581 + * @summary ScrollPane does not refresh properly when child is just smaller than viewport + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPanechildViewportTest + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class ScrollPanechildViewportTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Click "Slightly Large" and ensure scrollbars are VISIBLE + 2. Click "Slightly Small" and ensure there are NO scrollbars + 3. Click "Smaller" and ensure there are NO scrollbars + 4. If everything is ok, click PASS, else click FAIL. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPanechildViewportTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + return new Test(); + } +} + +class Test extends Frame implements ActionListener { + Button b1, b2, b3; + MyPanel p; + int state; // 0 = slightly large, 1 = slightly smaller, 2 = smaller + + public Test() { + ScrollPane sp = new ScrollPane(); + p = new MyPanel(); + p.setBackground(Color.yellow); + state = 1; + sp.add(p); + add(sp, "Center"); + + Panel p1 = new Panel(); + b1 = new Button("Slightly Large"); + b1.addActionListener(this); + p1.add(b1); + b2 = new Button("Slightly Small"); + b2.addActionListener(this); + p1.add(b2); + b3 = new Button("Smaller"); + b3.addActionListener(this); + p1.add(b3); + + add(p1, "South"); + + setSize(400, 200); + //added to test to move test frame away from instructions + setLocation(0, 350); + } + + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + + // set size to small and re-validate the panel to get correct size of + // scrollpane viewport without scrollbars + + state = 2; + p.invalidate(); + validate(); + + Dimension pd = ((ScrollPane) p.getParent()).getViewportSize(); + + if (source.equals(b1)) { + p.setBackground(Color.green); + state = 0; + } else if (source.equals(b2)) { + p.setBackground(Color.yellow); + state = 1; + } else if (source.equals(b3)) { + p.setBackground(Color.red); + state = 2; + } + + p.invalidate(); + validate(); + System.out.println("Panel Size = " + p.getSize()); + System.out.println("ScrollPane Viewport Size = " + pd); + System.out.println(" "); + } + + class MyPanel extends Panel { + public Dimension getPreferredSize() { + Dimension d = null; + Dimension pd = ((ScrollPane) getParent()).getViewportSize(); + switch (state) { + case 0 -> { + d = new Dimension(pd.width + 2, pd.height + 2); + System.out.println("Preferred size: " + d); + } + case 1 -> { + d = new Dimension(pd.width - 2, pd.height - 2); + System.out.println("Preferred size: " + d); + } + case 2 -> { + d = new Dimension(50, 50); + System.out.println("Preferred size: " + d); + } + } + return d; + } + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPositionTest.java b/test/jdk/java/awt/ScrollPane/ScrollPositionTest.java new file mode 100644 index 00000000000..9c082a8dfc9 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPositionTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4008152 + * @summary ScrollPane position does not return correct values + * @key headful + * @run main ScrollPositionTest + */ + +import java.awt.Adjustable; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.ScrollPane; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; + +public class ScrollPositionTest { + static Frame frame; + static int i = 0; + static Point p; + static ScrollPane sp; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("Scroll Position Test"); + frame.setLayout(new BorderLayout()); + frame.setSize(200, 200); + sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + Canvas canvas = new Canvas(); + canvas.setSize(300, 300); + sp.add(canvas); + frame.add("Center", sp); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + EventQueue.invokeAndWait(() -> { + Adjustable saH = sp.getHAdjustable(); + saH.addAdjustmentListener(new TestAdjustmentListener()); + }); + for (i = 0; i < 1000; i++) { + EventQueue.invokeAndWait(() -> { + p = new Point(i % 100, i % 100); + sp.setScrollPosition(p); + }); + + robot.waitForIdle(); + robot.delay(10); + EventQueue.invokeAndWait(() -> { + if (!sp.getScrollPosition().equals(p)) { + throw new RuntimeException("Test failed. " + i + " : " + + "Expected " + p + ", but Returned: " + sp.getScrollPosition()); + } + }); + } + System.out.println("Test Passed."); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static class TestAdjustmentListener implements AdjustmentListener { + public void adjustmentValueChanged(AdjustmentEvent e) { + System.out.println("AdjEvent caught:" + e); + } + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollbarsAsNeededTest.java b/test/jdk/java/awt/ScrollPane/ScrollbarsAsNeededTest.java new file mode 100644 index 00000000000..c5f48f80007 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollbarsAsNeededTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4094248 + * @summary Test initial appearance of SCROLLBARS_AS_NEEDED policy + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollbarsAsNeededTest + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.ScrollPane; + +public class ScrollbarsAsNeededTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. A Frame window with a ScrollPane that is + initially created with the SCROLLBARS_AS_NEEDED policy. + 2. If there are no scrollbars around the ScrollPane then + the test PASS. Otherwise the test FAILS. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollbarsAsNeededTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame frame = new Frame("Scrollbar as needed test"); + ScrollPane scrollPane = new ScrollPane() { + @Override + public void paint(Graphics g) { + super.paint(g); + g.drawString("ScrollPane", 10, 50); + } + }; + scrollPane.setBackground(Color.WHITE); + frame.setBackground(Color.GRAY); + frame.setSize(200, 200); + frame.setLayout(new FlowLayout()); + frame.add(scrollPane); + return frame; + } +} diff --git a/test/jdk/java/awt/Scrollbar/ListScrollbarTest.java b/test/jdk/java/awt/Scrollbar/ListScrollbarTest.java new file mode 100644 index 00000000000..fb441fe44ba --- /dev/null +++ b/test/jdk/java/awt/Scrollbar/ListScrollbarTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4029465 + * @summary Win95 Multiselect List doesn't display scrollbar + * @key headful + * @run main ListScrollbarTest + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.List; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; + +public class ListScrollbarTest { + + private static final Color BG_COLOR = Color.RED; + private static Robot robot; + private static Frame frame; + private static List list; + private static int counter = 0; + private static volatile Rectangle listBounds; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(ListScrollbarTest::createAndShowUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + EventQueue.invokeAndWait(() -> { + Point locationOnScreen = list.getLocationOnScreen(); + Dimension size = list.getSize(); + listBounds = new Rectangle(locationOnScreen, size); + }); + + Point point = new Point(listBounds.x + listBounds.width - 5, + listBounds.y + listBounds.height / 2); + + + for (int i = 0; i < 4; i++) { + scrollbarCheck(point, false); + addListItem(); + } + scrollbarCheck(point, true); + } + + public static boolean areColorsSimilar(Color c1, Color c2, int tolerance) { + return Math.abs(c1.getRed() - c2.getRed()) <= tolerance + && Math.abs(c1.getGreen() - c2.getGreen()) <= tolerance + && Math.abs(c1.getBlue() - c2.getBlue()) <= tolerance; + } + + private static void scrollbarCheck(Point point, boolean isScrollbarExpected) { + Color pixelColor = robot.getPixelColor(point.x, point.y); + boolean areColorsSimilar = areColorsSimilar(BG_COLOR, pixelColor, 5); + + if (isScrollbarExpected && areColorsSimilar) { + throw new RuntimeException((""" + Scrollbar is expected, but pixel color \ + is similar to the background color + %s pixel color + %s bg color""") + .formatted(pixelColor, BG_COLOR)); + } + + if (!isScrollbarExpected && !areColorsSimilar) { + throw new RuntimeException((""" + Scrollbar is not expected, but pixel color \ + is not similar to the background color + %s pixel color + %s bg color""") + .formatted(pixelColor, BG_COLOR)); + } + } + + private static void addListItem() throws Exception { + EventQueue.invokeAndWait(() -> { + counter++; + System.out.println("Adding list item " + counter); + list.add("List Item " + counter); + frame.validate(); + }); + robot.waitForIdle(); + robot.delay(150); + } + + private static void createAndShowUI() { + frame = new Frame("ListScrollbarTest"); + list = new List(3, true); + list.setBackground(BG_COLOR); + + // do not draw border around items, it can affect screen capture + list.setFocusable(false); + + frame.add(list); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/java/awt/Scrollbar/ScrollbarCtrlClickTest.java b/test/jdk/java/awt/Scrollbar/ScrollbarCtrlClickTest.java new file mode 100644 index 00000000000..3b5a24008fd --- /dev/null +++ b/test/jdk/java/awt/Scrollbar/ScrollbarCtrlClickTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4075950 + * @summary Test for functionality of Control Click on Scrollbar + * @key headful + * @run main ScrollbarCtrlClickTest + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class ScrollbarCtrlClickTest { + private static Frame frame; + private static TextArea ta; + private static Scrollbar scrollbar; + private static final CountDownLatch latch = new CountDownLatch(1); + private static volatile Rectangle sbBounds; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(ScrollbarCtrlClickTest::initAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void initAndShowGUI() { + frame = new Frame("ScrollbarDimensionTest"); + ta = new TextArea("", 30, 100); + + + scrollbar = new Scrollbar(Scrollbar.VERTICAL, + 0, 10, 0, 20); + + // Just setting layout so scrollbar thumb will be big enough to use + frame.setLayout(new BorderLayout()); + frame.add("East", scrollbar); + frame.add("West", ta); + + scrollbar.addAdjustmentListener(e -> { + System.out.println(e.paramString()); + ta.append(e.paramString() + "\n"); + latch.countDown(); + }); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.setAutoDelay(25); + robot.delay(500); + + EventQueue.invokeAndWait(() -> { + Point locationOnScreen = scrollbar.getLocationOnScreen(); + Dimension size = scrollbar.getSize(); + sbBounds = new Rectangle(locationOnScreen, size); + }); + + robot.mouseMove(sbBounds.x + sbBounds.width / 2, + sbBounds.y + sbBounds.height - 50); + + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.keyRelease(KeyEvent.VK_CONTROL); + + if (!latch.await(1, TimeUnit.SECONDS)) { + throw new RuntimeException("Timed out waiting for latch"); + } + } +} diff --git a/test/jdk/java/awt/Scrollbar/UnitIncrementTest.java b/test/jdk/java/awt/Scrollbar/UnitIncrementTest.java new file mode 100644 index 00000000000..03dba0f3a99 --- /dev/null +++ b/test/jdk/java/awt/Scrollbar/UnitIncrementTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4169461 + * @summary Test for Motif Scrollbar unit increment + * @key headful + * @run main UnitIncrementTest + */ + +import javax.swing.UIManager; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Scrollbar; +import java.awt.event.AdjustmentEvent; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + +public class UnitIncrementTest { + private static Frame frame; + private static Scrollbar scrollbar; + private static final java.util.List eventsList = new ArrayList<>(); + private static final int UNIT_INCREMENT_VALUE = 5; + private static final int INCREMENTS_COUNT = 10; + private static volatile Rectangle scrollbarBounds; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + + try { + EventQueue.invokeAndWait(UnitIncrementTest::createAndShowUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + frame = new Frame("UnitIncrementTest"); + + scrollbar = new Scrollbar(Scrollbar.HORIZONTAL); + + scrollbar.setUnitIncrement(UNIT_INCREMENT_VALUE); + scrollbar.setBlockIncrement(20); + + scrollbar.addAdjustmentListener(e -> { + eventsList.add(e); + System.out.println(e); + }); + + frame.add(scrollbar); + + frame.setSize(300, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.setAutoDelay(25); + robot.delay(500); + + EventQueue.invokeAndWait(() -> { + Point locationOnScreen = scrollbar.getLocationOnScreen(); + Dimension size = scrollbar.getSize(); + scrollbarBounds = new Rectangle(locationOnScreen, size); + }); + + robot.mouseMove(scrollbarBounds.x + scrollbarBounds.width - 10, + scrollbarBounds.y + scrollbarBounds.height / 2); + + for (int i = 0; i < INCREMENTS_COUNT; i++) { + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(150); + } + + robot.waitForIdle(); + robot.delay(250); + + if (eventsList.size() != INCREMENTS_COUNT) { + throw new RuntimeException("Wrong number of events: " + eventsList.size()); + } + + int oldValue = 0; + for (AdjustmentEvent event : eventsList) { + System.out.println("\nChecking event " + event); + + int diff = event.getValue() - oldValue; + System.out.printf("diff: %d - %d = %d\n", event.getValue(), oldValue, diff); + + if (diff != UNIT_INCREMENT_VALUE) { + throw new RuntimeException("Unexpected adjustment value: %d".formatted(diff)); + } + + oldValue = event.getValue(); + } + } +} diff --git a/test/jdk/java/awt/Selection/TestClipboard.java b/test/jdk/java/awt/Selection/TestClipboard.java new file mode 100644 index 00000000000..ed65d55489c --- /dev/null +++ b/test/jdk/java/awt/Selection/TestClipboard.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import java.io.Serializable; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +/* + * @test + * @bug 4139552 + * @summary Checks to see if 'isDataFlavorSupported' throws exception. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestClipboard + */ + +public class TestClipboard { + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + This test has two steps: + + 1. you need to place some text onto the system clipboard, + for example, + on Windows, you could highlight some text in notepad, and do a Ctrl-C + or select menu Edit->Copy; + + on Linux or Mac, you can do the same with any Terminal or Console or + Text application. + + 2. After you copy to system clipboard, press "Click Me" button. + + Test will fail if any exception is thrown. + + Press Pass if you see "Test Passed" in log area."""; + + PassFailJFrame.builder() + .title("TestClipboard Instruction") + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TestClipboard::createUI) + .logArea(4) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame f = new JFrame("ChildFrameIconTest UI"); + JButton b = new JButton("Click Me"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + new MyTest(); + } catch (Exception ex) { + throw new RuntimeException("Exception Thrown : " + ex); + } + } + }); + f.add(b); + f.setSize(200, 100); + return f; + } + + static class MyFlavor extends Object implements Serializable { + // Stub class needed in order to define the data flavor type + } + + static class MyTest { + public MyTest() throws Exception { + // Create an arbitrary dataflavor + DataFlavor myFlavor = new DataFlavor(MyFlavor.class, "TestClipboard"); + // Get the system clipboard + Clipboard theClipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + // Get the current contents of the clipboard + Transferable theTransfer = theClipboard.getContents(this); + + // See if the flavor is supported. This may result in a null + // pointer exception. + theTransfer.isDataFlavorSupported(myFlavor); + PassFailJFrame.log("Test Passed"); + } + } +} diff --git a/test/jdk/java/awt/TextComponent/AltPlusNumberKeyCombinationsTest.java b/test/jdk/java/awt/TextComponent/AltPlusNumberKeyCombinationsTest.java new file mode 100644 index 00000000000..27599b0a91c --- /dev/null +++ b/test/jdk/java/awt/TextComponent/AltPlusNumberKeyCombinationsTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4737679 4623376 4501485 4740906 4708221 + * @requires (os.family == "windows") + * @summary Alt+Left/right/up/down generate characters in JTextArea + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AltPlusNumberKeyCombinationsTest + */ + +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.TextArea; +import java.awt.TextField; + +public class AltPlusNumberKeyCombinationsTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + [WINDOWS PLATFORM ONLY] + Please do the following steps for both TextField and TextArea: + 1. Hold down ALT and press a NON-NUMPAD right arrow, then release + ALT key. If any symbol is typed the test failed. + 2. Hold down ALT and press one after another the following + NUMPAD keys: 0, 1, 2, 8. Release ALT key. If the Euro symbol + is not typed the test failed + 3. Hold down ALT and press one after another the following + NUMPAD keys: 0, 2, 2, 7. Release ALT key. If nothing or + the blank symbol is typed the test failed + If all the steps are done successfully the test PASSed, + else test FAILS. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(initialize()) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame f = new Frame("key combination test"); + f.setLayout(new FlowLayout()); + TextField tf = new TextField("TextField"); + f.add(tf); + TextArea ta = new TextArea("TextArea"); + f.add(ta); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/java/awt/TextComponent/BackgroundTest.java b/test/jdk/java/awt/TextComponent/BackgroundTest.java new file mode 100644 index 00000000000..543f2cfd893 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/BackgroundTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4258667 4405602 + * @summary Make sure TextComponents are grayed out when non-editable + * if the background color has not been set by client code. + * Make sure TextComponents are not grayed out when non-editable + * if the background color has been set by client code. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual BackgroundTest + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.TextArea; +import java.awt.TextField; + +public class BackgroundTest { + private static final String enableString = "EnableText"; + private static final String disableString = "DisableText"; + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. When the frame appears, it should have a blue background. + 2. The first TextField and TextArea will be the default color. + The second TextField and TextArea will be green. + 3. Press the "DisableText" button. + The first TextField and TextArea should change colors to the + default disabled color. On Windows, this is usually gray. + On linux and macos it will match the environment settings. + If the TextField or the TextArea do not change colors as described, + the test FAILS. + 4. The second TextField and TextArea should still be green. + If either of them are not green, the test FAILS. + Press the "EnableText" button (same button as before). + The first TextField and TextArea should return to their + original colors as described in the first paragraph. If they + do not, the test FAILS. + 5. The second TextField and TextArea should still be green. + If either of them are not green, the test FAILS. + Otherwise, the test PASSES. + """; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(BackgroundTest::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Background Test"); + frame.setLayout(new FlowLayout()); + TextField tf = new TextField(30); + TextArea ta = new TextArea(4, 30); + TextField setTf = new TextField(30); + TextArea setTa = new TextArea(4, 30); + Button enableButton = new Button(disableString); + + enableButton.setBackground(Color.red); + frame.setSize(500, 250); + + frame.setBackground(Color.blue); + + tf.setText("Background not set - should be default"); + tf.setEditable(true); + frame.add(tf); + ta.setText("Background not set - should be default"); + ta.setEditable(true); + frame.add(ta); + + setTf.setText("Background is set - should be Green"); + setTf.setBackground(Color.green); + setTf.setEditable(true); + frame.add(setTf); + setTa.setText("Background is set - should be Green"); + setTa.setBackground(Color.green); + setTa.setEditable(true); + frame.add(setTa); + + enableButton.addActionListener(e -> { + boolean currentlyEditable = tf.isEditable(); + + if (currentlyEditable) { + tf.setEditable(false); + ta.setEditable(false); + setTf.setEditable(false); + setTa.setEditable(false); + enableButton.setLabel(enableString); + } else { + tf.setEditable(true); + ta.setEditable(true); + setTf.setEditable(true); + setTa.setEditable(true); + enableButton.setLabel(disableString); + } + }); + frame.add(enableButton); + return frame; + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java b/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java new file mode 100644 index 00000000000..9d3e6d85637 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 5100806 + * @summary TextArea.select(0,0) does not de-select the selected text properly + * @key headful + * @run main CorrectTextComponentSelectionTest + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.TextComponent; +import java.awt.TextField; +import java.lang.reflect.InvocationTargetException; + +public class CorrectTextComponentSelectionTest { + static TextField tf = new TextField("TextField"); + static TextArea ta = new TextArea("TextArea"); + static Robot r; + static Frame frame; + static volatile Color color_center; + static volatile Point loc; + + public static void main(String[] args) throws Exception { + try { + r = new Robot(); + EventQueue.invokeAndWait(() -> { + initialize(); + }); + r.waitForIdle(); + r.delay(1000); + + test(tf); + test(ta); + System.out.println("Test Passed!"); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void initialize() { + frame = new Frame("TextComponent Selection Test"); + frame.setLayout(new BorderLayout()); + + // We should place to the text components the long strings in order to + // cover the components by the selection completely + String sf = ""; + for (int i = 0; i < 50; i++) { + sf = sf + " "; + } + tf.setText(sf); + // We check the color of the text component in order to find out the + // bug reproducible situation + tf.setForeground(Color.WHITE); + tf.setBackground(Color.WHITE); + + String sa = ""; + for (int i = 0; i < 50; i++) { + for (int j = 0; j < 50; j++) { + sa = sa + " "; + } + sa = sa + "\n"; + } + ta.setText(sa); + ta.setForeground(Color.WHITE); + ta.setBackground(Color.WHITE); + + frame.add(tf, "North"); + frame.add(ta, "South"); + frame.setSize(200, 200); + frame.setVisible(true); + } + + private static void test(TextComponent tc) throws Exception { + if (tc instanceof TextField) { + System.out.println("TextField testing ..."); + } else if (tc instanceof TextArea) { + System.out.println("TextArea testing ..."); + } + + r.waitForIdle(); + r.delay(100); + EventQueue.invokeAndWait(() -> { + tc.requestFocus(); + tc.selectAll(); + tc.select(0, 0); + }); + + r.waitForIdle(); + r.delay(100); + EventQueue.invokeAndWait(() -> { + loc = tc.getLocationOnScreen(); + }); + r.waitForIdle(); + r.delay(100); + + EventQueue.invokeAndWait(() -> { + color_center = r.getPixelColor(loc.x + tc.getWidth() / 2, loc.y + tc.getHeight() / 2); + }); + + System.out.println("Color of the text component (CENTER) =" + color_center); + System.out.println("White color=" + Color.WHITE); + + if (color_center.getRGB() != Color.WHITE.getRGB()) { + throw new RuntimeException("Test Failed"); + } + } +} diff --git a/test/jdk/java/awt/TextComponent/DisableTest.java b/test/jdk/java/awt/TextComponent/DisableTest.java new file mode 100644 index 00000000000..820b9c8bd30 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/DisableTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 5042122 + * @summary Verifies the TextComponent is grayed out when disabled + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual DisableTest + */ + +import javax.swing.BoxLayout; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Component; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionListener; +import java.util.Vector; +import java.util.Iterator; + +public class DisableTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Click "Enable" and "Disable" buttons and verify the text + components are disabled and enabled correctly. + 2. Verify that the disabled text components are grayed + out and are uneditable. + 3. Click PASS or FAIL accordingly. + """; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(DisableTest::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("TextComponent Disabled test"); + frame.setLayout(new BorderLayout()); + frame.setSize(200, 200); + final Vector comps = new Vector(); + comps.add(new TextField("TextField")); + TextArea ta = new TextArea("TextArea", 2, 100, TextArea.SCROLLBARS_NONE); + comps.add(ta); + Panel pc = new Panel(); + pc.setLayout(new BoxLayout(pc, BoxLayout.Y_AXIS)); + Iterator iter = comps.iterator(); + while (iter.hasNext()) { + Component c = (Component) iter.next(); + c.setEnabled(false); + pc.add(c); + } + frame.add(pc, BorderLayout.CENTER); + Panel p = new Panel(); + final Button be = new Button("Enable"); + final Button bd = new Button("Disable"); + p.add(be); + p.add(bd); + ActionListener al = ev -> { + boolean enable = (ev.getSource() == be); + Iterator iterator = comps.iterator(); + while (iterator.hasNext()) { + Component c = (Component) iterator.next(); + c.setEnabled(enable); + } + }; + be.addActionListener(al); + bd.addActionListener(al); + frame.add(p, BorderLayout.SOUTH); + return frame; + } +} diff --git a/test/jdk/java/awt/TextComponent/ModifiersTest.java b/test/jdk/java/awt/TextComponent/ModifiersTest.java new file mode 100644 index 00000000000..e9e76a9b694 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/ModifiersTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4035364 + * @summary Checks that Caps Lock key works + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ModifiersTest + */ + +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.TextArea; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +public class ModifiersTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Type some text in the TextArea in upper and lowercase, + using the Caps Lock ON/OFF. + 2. If Caps Lock toggles correctly and you are able to type in + both cases, the test PASS. Else Test FAILS. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ModifiersTest::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Modifiers Test"); + frame.setLayout(new GridLayout(1, 1)); + frame.addKeyListener(new KeyChecker()); + frame.setLayout(new GridLayout(2, 1)); + Label label = new Label("See if you can type in upper and lowercase using Caps Lock:"); + frame.add(label); + TextArea ta = new TextArea(); + frame.add(ta); + ta.addKeyListener(new KeyChecker()); + ta.requestFocus(); + frame.setSize(400, 300); + return frame; + } +} + +// a KeyListener for debugging purposes +class KeyChecker extends KeyAdapter { + public void keyPressed(KeyEvent ev) { + System.out.println(ev); + } + + public void keyReleased(KeyEvent ev) { + System.out.println(ev); + } + + public void keyTyped(KeyEvent ev) { + System.out.println(ev); + } +} diff --git a/test/jdk/java/awt/TextComponent/SelectionAndCaretColor.java b/test/jdk/java/awt/TextComponent/SelectionAndCaretColor.java new file mode 100644 index 00000000000..60b932e4be8 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/SelectionAndCaretColor.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 6287895 + * @requires (os.family == "linux") + * @summary Test cursor and selected text incorrectly colored in TextField + * @key headful + * @run main SelectionAndCaretColor + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.TextComponent; +import java.awt.TextField; +import java.awt.image.BufferedImage; + +public class SelectionAndCaretColor { + static TextField tf = new TextField(20); + static TextArea ta = new TextArea("", 1, 20, TextArea.SCROLLBARS_NONE); + static Robot r; + static Frame frame; + static volatile int flips; + + public static void main(String[] args) throws Exception { + try { + frame = new Frame("Selection and Caret color test"); + r = new Robot(); + + EventQueue.invokeAndWait(() -> { + frame.setLayout(new BorderLayout()); + tf.setFont(new Font("Monospaced", Font.PLAIN, 15)); + ta.setFont(new Font("Monospaced", Font.PLAIN, 15)); + + frame.add(tf, BorderLayout.NORTH); + frame.add(ta, BorderLayout.SOUTH); + frame.setSize(200, 200); + frame.setVisible(true); + }); + r.waitForIdle(); + r.delay(1000); + test(tf); + test(ta); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static int countFlips(TextComponent tc) { + int y = tc.getLocationOnScreen().y + tc.getHeight() / 2; + int x1 = tc.getLocationOnScreen().x + 5; + int x2 = tc.getLocationOnScreen().x + tc.getWidth() - 5; + + int[] fb = {tc.getBackground().getRGB(), tc.getForeground().getRGB()}; + int i = 0; + int flips = 0; + + BufferedImage img = r.createScreenCapture(new Rectangle(x1, y, x2 - x1, 1)); + for (int x = 0; x < x2 - x1; x++) { + int c = img.getRGB(x, 0); + if (c == fb[i]) { + ; + } else if (c == fb[1 - i]) { + flips++; + i = 1 - i; + } else { + throw new RuntimeException("Invalid color detected: " + + Integer.toString(c, 16) + " instead of " + + Integer.toString(fb[i], 16)); + } + } + return flips; + } + + private static void test(TextComponent tc) throws Exception { + if (tc instanceof TextField) { + System.out.println("TextField testing ..."); + } else if (tc instanceof TextArea) { + System.out.println("TextArea testing ..."); + } + + // now passing along the component's vertical center, + // skipping 5px from both sides, + // we should see bg - textcolor - bg - selcolor - + // seltextcolor - selcolor - bg + // that is bg-fg-bg-fg-bg-fg-bg, 6 flips + + EventQueue.invokeAndWait(() -> { + tc.setForeground(Color.green); + tc.setBackground(Color.magenta); + + tc.setText(" I I "); + tc.select(5, 10); + tc.requestFocus(); + }); + r.waitForIdle(); + r.delay(200); + EventQueue.invokeAndWait(() -> { + flips = countFlips(tc); + }); + if (flips != 6) { + throw new RuntimeException("Invalid number of flips: " + + flips + " instead of 6"); + } + EventQueue.invokeAndWait(() -> { + // same for caret: spaces in the tc, caret in the middle + // bg-fg-bg - 2 flips + + tc.select(0, 0); + tc.setText(" "); + tc.setCaretPosition(5); + }); + r.waitForIdle(); + r.delay(200); + + for (int i = 0; i < 10; i++) { + EventQueue.invokeAndWait(() -> { + flips = countFlips(tc); + }); + + if (flips == 2) { + break; + } + if (flips == 0) { + continue; + } + throw new RuntimeException("Invalid number of flips: " + + flips + " instead of 2"); + } + } +} diff --git a/test/jdk/java/awt/TextComponent/SelectionTest.java b/test/jdk/java/awt/TextComponent/SelectionTest.java new file mode 100644 index 00000000000..d29818d7621 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/SelectionTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4056231 + * @summary Checks that TextComponents don't grab the global CDE selection + * upon construction if their own selection is null. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SelectionTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Frame; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class SelectionTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. "Select some text in another window, then click the button.", + 2. "If the text in the other window is de-selected, the test FAILS.", + "If the text remains selected, the test PASSES." + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(initialize()) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Selection Test"); + frame.setLayout(new BorderLayout()); + Button b = new Button("Select some text in another window, then" + + " click me"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + frame.add(new TextField("text field test")); + frame.add(new TextArea("text area test")); + } + }); + frame.add(b); + frame.setSize(400, 400); + return frame; + } +} diff --git a/test/jdk/java/awt/TextComponent/TextFieldMargin.java b/test/jdk/java/awt/TextComponent/TextFieldMargin.java new file mode 100644 index 00000000000..6baf144254c --- /dev/null +++ b/test/jdk/java/awt/TextComponent/TextFieldMargin.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4129511 + * @summary Tests that TextField margins are not exceedingly wide + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TextFieldMargin + */ + +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.TextArea; +import java.awt.TextField; + +public class TextFieldMargin { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Examine the TextField, Label, and TextArea to see + that the text is vertically aligned along the left + 2. If all are aligned along the left, then test PASS, + else test FAILS. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(TextFieldMargin::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Frame with a text field & a label"); + frame.setLayout(new GridLayout(5, 1)); + TextField text_field = new TextField("Left Textfield"); + frame.add(text_field); + Label label = new Label("Left Label"); + frame.add(label); + TextArea text_area = new TextArea("Left Textfield"); + frame.add(text_area); + frame.setBounds(50, 50, 300, 300); + return frame; + } +} diff --git a/test/jdk/java/awt/TextField/SetEchoCharTest4/SetEchoCharTest4.java b/test/jdk/java/awt/TextField/SetEchoCharTest4/SetEchoCharTest4.java index c1cc07afac0..e96485dcb54 100644 --- a/test/jdk/java/awt/TextField/SetEchoCharTest4/SetEchoCharTest4.java +++ b/test/jdk/java/awt/TextField/SetEchoCharTest4/SetEchoCharTest4.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.lang.reflect.InvocationTargetException; /* * @test @@ -54,16 +53,17 @@ public class SetEchoCharTest4 extends Frame implements ActionListener { Make sure the actual text matches what you typed in for each field. Press Pass if everything's ok, otherwise Fail - """; + """; public SetEchoCharTest4() { + super("SetEchoCharTest4"); setLayout(new FlowLayout()); tf1.setEchoChar('*'); tf2.setEchoChar('$'); tf3.setEchoChar('#'); addStuff(); b.addActionListener(this); - setSize (200,200); + setSize (300, 150); } private void addStuff() { @@ -78,7 +78,6 @@ public void actionPerformed(ActionEvent ae) { PassFailJFrame.log("TextField2 = " + tf2.getText()); PassFailJFrame.log("TextField3 = " + tf3.getText()); PassFailJFrame.log("--------------"); - setVisible(false); remove(tf1); remove(tf2); remove(tf3); @@ -86,16 +85,14 @@ public void actionPerformed(ActionEvent ae) { addStuff(); } - public static void main(String[] args) throws InterruptedException, - InvocationTargetException { + public static void main(String[] args) throws Exception { PassFailJFrame.builder() - .title("Set Echo Character Test") - .testUI(SetEchoCharTest4::new) - .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 1) - .columns(40) - .logArea() - .build() - .awaitAndCheck(); + .title("Set Echo Character Test") + .testUI(SetEchoCharTest4::new) + .instructions(INSTRUCTIONS) + .columns(40) + .logArea() + .build() + .awaitAndCheck(); } } diff --git a/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java b/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java index 825c21fdc96..9116a4dff3b 100644 --- a/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java +++ b/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * 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,7 +30,7 @@ /* * @test - * @bug 6191897 + * @bug 6191897 8354646 * @summary Verifies that ctrl+left/right does not move word-by-word in a TextField * with echo character set * @library /java/awt/regtesthelpers /test/lib diff --git a/test/jdk/java/awt/Toolkit/DesktopProperties/DesktopPropertyTest.java b/test/jdk/java/awt/Toolkit/DesktopProperties/DesktopPropertyTest.java new file mode 100644 index 00000000000..c2e3f5652f0 --- /dev/null +++ b/test/jdk/java/awt/Toolkit/DesktopProperties/DesktopPropertyTest.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4287882 + * @summary Tests internal use Windows properties + * @requires os.family == "windows" + * @key headful + * @run main DesktopPropertyTest + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableModel; +import java.awt.Robot; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Arrays; +import java.util.Vector; + +/* + * This is a test of new Windows-specific desktop + * properties added in Kestrel. + * + * The new properties are meant for the use of the + * Windows PLAF only and are not public at this time. + */ +public class DesktopPropertyTest { + private static JFrame frame; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + SwingUtilities.invokeAndWait(DesktopPropertyTest::runTest); + robot.waitForIdle(); + robot.delay(1000); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void runTest() { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + throw new RuntimeException(e); + } + frame = new DesktopPropertyFrame(); + frame.setVisible(true); + } + + static class DesktopPropertyFrame extends JFrame { + JTable table; + + DesktopPropertyFrame() { + super("Toolkit.getDesktopProperty API Test"); + setBackground(Color.white); + add(new JScrollPane(createTable())); + setLocationRelativeTo(null); + setSize(500, 400); + } + + public JTable createTable() { + TableModel dataModel = new AbstractTableModel() { + final PropertyVector pv = new PropertyVector(); + + public int getColumnCount() { + return 3; + } + + public int getRowCount() { + return pv.size(); + } + + public String getColumnName(int column) { + String[] colnames = {"Property", "Type", "Value"}; + return colnames[column]; + } + + public Object getValueAt(int row, int col) { + Object[] prow = pv.get(row); + return prow[col]; + } + }; + + table = new JTable(dataModel); + table.setDefaultRenderer(Object.class, new DesktopPropertyRenderer()); + table.addMouseListener(new ClickListener()); + return table; + } + + class ClickListener extends MouseAdapter { + ClickListener() { + } + + public void mouseClicked(MouseEvent e) { + for (int row = 0; row <= table.getModel().getRowCount(); row++) { + Rectangle r = table.getCellRect(row, 2, false); + if (r.contains(e.getX(), e.getY())) { + Object value = table.getModel().getValueAt(row, 2); + if (value instanceof Runnable) { + ((Runnable) value).run(); + } + } + } + } + } + + class PropertyVector { + private static final int NAME = 0; + private static final int TYPE = 1; + private static final int VALUE = 2; + + private final Vector vector = new Vector<>(); + + PropertyVector() { + Object[] props = (Object[]) getToolkit() + .getDesktopProperty("win.propNames"); + if (props == null) { + throw new RuntimeException( + "'win.propNames' property not available. " + + "This test is valid only on Windows."); + } + for (Object prop : props) { + String propertyName = prop.toString(); + vector.addElement(createEntry(propertyName)); + } + } + + Object[] createEntry(String name) { + Object[] row = new Object[3]; + Object value = getToolkit().getDesktopProperty(name); + row[NAME] = name; + row[TYPE] = value.getClass().getName(); + row[VALUE] = value; + + System.out.println(Arrays.toString(row)); + // update this vector when property changes + getToolkit().addPropertyChangeListener(name, new DesktopPropertyChangeListener(row)); + return row; + } + + Object[] get(int row) { + return (Object[]) vector.elementAt(row); + } + + int size() { + return vector.size(); + } + + static class DesktopPropertyChangeListener implements PropertyChangeListener { + Object[] row; + + DesktopPropertyChangeListener(Object[] row) { + this.row = row; + } + + public void propertyChange(PropertyChangeEvent evt) { + this.row[VALUE] = evt.getNewValue(); + } + } + } + + static class DesktopPropertyRenderer implements TableCellRenderer { + ValueProp vprop = new ValueProp(); + FontProp fprop = new FontProp(); + ColorProp cprop = new ColorProp(); + RunnableProp rprop = new RunnableProp(); + RenderingHintsProp rhprop = new RenderingHintsProp(); + + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, + int row, int column) { + + ValueProp propComponent; + if (value instanceof Boolean + || value instanceof Integer + || value instanceof String) { + propComponent = vprop; + } else if (value instanceof Font) { + propComponent = fprop; + } else if (value instanceof Color) { + propComponent = cprop; + } else if (value instanceof Runnable) { + propComponent = rprop; + } else if (value instanceof RenderingHints) { + propComponent = rhprop; + } else { + throw new RuntimeException("ASSERT unexpected value %s / %s\n" + .formatted(value != null ? value.getClass() : "", value)); + } + + propComponent.setValue(value); + + return propComponent; + } + } + + static class ValueProp extends JLabel { + public void setValue(Object value) { + setText(value.toString()); + } + } + + static class FontProp extends ValueProp { + public void setValue(Object value) { + Font font = (Font) value; + String style; + if (font.getStyle() == Font.BOLD) { + style = "Bold"; + } else if (font.getStyle() > Font.BOLD) { + style = "BoldItalic"; + } else { + style = "Plain"; + } + setText(font.getName() + ", " + style + ", " + font.getSize()); + setFont(font); + } + } + + static class ColorProp extends ValueProp { + public void setValue(Object value) { + Color color = (Color) value; + setText("%d, %d, %d" + .formatted(color.getRed(), color.getGreen(), color.getBlue())); + setBackground(color); + setOpaque(true); + } + } + + static class RunnableProp extends ValueProp {} + static class RenderingHintsProp extends ValueProp {} + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java b/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java index e2ded58e7f2..4b4041dbcfd 100644 --- a/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java +++ b/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/TestWrapped.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * 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,55 +22,52 @@ */ /* - * test + * @test * @bug 6282388 - * @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit - * @author artem.ananiev@sun.com: area=awt.headless - * @run shell WrappedToolkitTest.sh + * @summary Tests that AWT uses correct toolkit wrapped into HeadlessToolkit + * @modules java.desktop/sun.awt:open + * @library /test/lib + * @run main/othervm -Djava.awt.headless=true TestWrapped */ -import java.awt.*; +import java.awt.Toolkit; +import java.lang.Class; +import java.lang.reflect.Field; -import java.lang.reflect.*; +import jdk.test.lib.Platform; -import sun.awt.*; +public final class TestWrapped { -public class TestWrapped -{ - public static void main(String[] args) - { - try - { - if (args.length != 1) { - System.err.println("No correct toolkit class name is specified, test is not run"); - System.exit(0); + private static final String HEADLESS_TOOLKIT = "sun.awt.HeadlessToolkit"; + private static final String MACOSX_TOOLKIT = "sun.lwawt.macosx.LWCToolkit"; + private static final String UNIX_TOOLKIT = "sun.awt.X11.XToolkit"; + private static final String WINDOWS_TOOLKIT = "sun.awt.windows.WToolkit"; + + public static void main(String[] args) throws Exception { + String expectedToolkitClassName; + if (Platform.isWindows()) { + expectedToolkitClassName = WINDOWS_TOOLKIT; + } else if (Platform.isOSX()) { + expectedToolkitClassName = MACOSX_TOOLKIT; + } else { + expectedToolkitClassName = UNIX_TOOLKIT; } - String correctToolkitClassName = args[0]; Toolkit tk = Toolkit.getDefaultToolkit(); - Class tkClass = tk.getClass(); - if (!tkClass.getName().equals("sun.awt.HeadlessToolkit")) - { - System.err.println(tkClass.getName()); - System.err.println("Error: default toolkit is not an instance of HeadlessToolkit"); - System.exit(-1); + Class tkClass = tk.getClass(); + if (!tkClass.getName().equals(HEADLESS_TOOLKIT)) { + System.err.println("Expected: " + HEADLESS_TOOLKIT); + System.err.println("Actual: " + tkClass.getName()); + throw new RuntimeException("Wrong default toolkit"); } Field f = tkClass.getDeclaredField("tk"); f.setAccessible(true); - Class wrappedClass = f.get(tk).getClass(); - if (!wrappedClass.getName().equals(correctToolkitClassName)) { - System.err.println(wrappedClass.getName()); - System.err.println("Error: wrapped toolkit is not an instance of " + correctToolkitClassName); - System.exit(-1); - } + Class wrappedClass = f.get(tk).getClass(); + if (!wrappedClass.getName().equals(expectedToolkitClassName)) { + System.err.println("Expected: " + expectedToolkitClassName); + System.err.println("Actual: " + wrappedClass.getName()); + throw new RuntimeException("Wrong wrapped toolkit"); } - catch (Exception z) - { - z.printStackTrace(System.err); - System.exit(-1); - } - - System.exit(0); } } diff --git a/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh b/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh deleted file mode 100644 index ac0cf58942c..00000000000 --- a/test/jdk/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh +++ /dev/null @@ -1,221 +0,0 @@ -#!/bin/ksh -p - -# -# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# -# @test -# @bug 6282388 8030640 -# @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit -# @author artem.ananiev@sun.com: area=awt.headless -# compile TestWrapped.java -# @run shell WrappedToolkitTest.sh - -# Beginning of subroutines: -status=1 - -#Call this from anywhere to fail the test with an error message -# usage: fail "reason why the test failed" -fail() - { echo "The test failed :-(" - echo "$*" 1>&2 - echo "exit status was $status" - exit $status - } #end of fail() - -#Call this from anywhere to pass the test with a message -# usage: pass "reason why the test passed if applicable" -pass() - { echo "The test passed!!!" - echo "$*" 1>&2 - exit 0 - } #end of pass() - -# end of subroutines - - -# The beginning of the script proper - -# Checking for proper OS -OS=`uname -s` -case "$OS" in - AIX | CYGWIN* | Darwin | Linux ) - FILESEP="/" - ;; - - Windows* ) - FILESEP="\\" - ;; - - # catch all other OSs - * ) - echo "Unrecognized system! $OS" - fail "Unrecognized system! $OS" - ;; -esac - -# check that some executable or other file you need is available, abort if not -# note that the name of the executable is in the fail string as well. -# this is how to check for presence of the compiler, etc. -#RESOURCE=`whence SomeProgramOrFileNeeded` -#if [ "${RESOURCE}" = "" ] ; -# then fail "Need SomeProgramOrFileNeeded to perform the test" ; -#fi - -# Want this test to run standalone as well as in the harness, so do the -# following to copy the test's directory into the harness's scratch directory -# and set all appropriate variables: - -if [ -z "${TESTJAVA}" ] ; then - # TESTJAVA is not set, so the test is running stand-alone. - # TESTJAVA holds the path to the root directory of the build of the JDK - # to be tested. That is, any java files run explicitly in this shell - # should use TESTJAVA in the path to the java interpreter. - # So, we'll set this to the JDK spec'd on the command line. If none - # is given on the command line, tell the user that and use a cheesy - # default. - # THIS IS THE JDK BEING TESTED. - if [ -n "$1" ] ; - then TESTJAVA=$1 - else fail "no JDK specified on command line!" - fi - TESTSRC=. - TESTCLASSES=. - STANDALONE=1; -fi -echo "JDK under test is: $TESTJAVA" - -#if in test harness, then copy the entire directory that the test is in over -# to the scratch directory. This catches any support files needed by the test. -if [ -z "${STANDALONE}" ] ; - then cp ${TESTSRC}/* . -fi -case "$OS" in - Windows* | CYGWIN* ) - ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \ - --add-exports java.desktop/sun.awt=ALL-UNNAMED \ - --add-exports java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \ - *.java - status=$? - if [ ! $status -eq "0" ]; then - fail "Compilation failed"; - fi - ;; - - AIX | Linux ) - ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \ - --add-exports java.desktop/sun.awt=ALL-UNNAMED \ - --add-exports java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \ - *.java - status=$? - if [ ! $status -eq "0" ]; then - fail "Compilation failed"; - fi - ;; - - Darwin) - ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \ - --add-exports java.desktop/sun.awt=ALL-UNNAMED \ - --add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \ - *.java - status=$? - if [ ! $status -eq "0" ]; then - fail "Compilation failed"; - fi - ;; - -esac - -#Just before executing anything, make sure it has executable permission! -chmod 777 ./* - -############### YOUR TEST CODE HERE!!!!!!! ############# - -case "$OS" in - Windows* | CYGWIN* ) - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \ - TestWrapped sun.awt.windows.WToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit"; - fi - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \ - -Dawt.toolkit=sun.awt.windows.WToolkit \ - TestWrapped sun.awt.windows.WToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit"; - fi - ;; - - AIX | Linux ) - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \ - -Dawt.toolkit=sun.awt.X11.XToolkit \ - TestWrapped sun.awt.X11.XToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit"; - fi - AWT_TOOLKIT=XToolkit ${TESTJAVA}/bin/java ${TESTVMOPTS} \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \ - -Djava.awt.headless=true \ - TestWrapped sun.awt.X11.XToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit"; - fi - ;; - - Darwin) - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \ - TestWrapped sun.lwawt.macosx.LWCToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit"; - fi - ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \ - --add-opens java.desktop/sun.awt=ALL-UNNAMED \ - --add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \ - -Dawt.toolkit=sun.lwawt.macosx.LWCToolkit \ - TestWrapped sun.lwawt.macosx.LWCToolkit - status=$? - if [ ! $status -eq "0" ]; then - fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit"; - fi - ;; - -esac - -pass "All the tests are PASSED"; - -#For additional examples of how to write platform independent KSH scripts, -# see the jtreg file itself. It is a KSH script for both Solaris and Win32 diff --git a/test/jdk/java/awt/Toolkit/TimeUnsignedConversionTest.java b/test/jdk/java/awt/Toolkit/TimeUnsignedConversionTest.java new file mode 100644 index 00000000000..64d05ef2498 --- /dev/null +++ b/test/jdk/java/awt/Toolkit/TimeUnsignedConversionTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 5097241 + * @summary Tests the problem of time type conversion on XToolkit. The conversion should be unsigned. + * @requires os.family == "linux" + * @key headful + * @library /java/awt/regtesthelpers /test/lib + * @build Util jtreg.SkippedException + * @run main/othervm -Dsun.awt.disableGtkFileDialogs=true TimeUnsignedConversionTest + */ + +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FileDialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.KeyEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import jtreg.SkippedException; +import test.java.awt.regtesthelpers.Util; + +public class TimeUnsignedConversionTest { + static Robot robot; + static Frame frame; + static volatile Button button; + static volatile FileDialog dialog; + static volatile boolean dialogShown = false; + + static final CountDownLatch passedLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + if (!Toolkit.getDefaultToolkit().getClass().getName().equals("sun.awt.X11.XToolkit")) { + throw new SkippedException("XAWT test only! Skipped."); + } + + try { + EventQueue.invokeAndWait(TimeUnsignedConversionTest::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowGUI() { + frame = new Frame("TimeUnsignedConversionTest frame"); + button = new Button("Show Dialog"); + dialog = new FileDialog(frame, "TimeUnsignedConversionTest Dialog", FileDialog.LOAD); + + Toolkit.getDefaultToolkit().addAWTEventListener(e -> { + System.out.println(e); + if (dialogShown && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_K) { + passedLatch.countDown(); + } + }, KeyEvent.KEY_EVENT_MASK); + + frame.setLayout(new FlowLayout()); + frame.add(button); + + button.addActionListener(ae -> { + if (ae.getActionCommand().equals("Show Dialog")) { + dialog.setSize(200, 200); + dialog.setLocationRelativeTo(frame); + dialog.setVisible(true); + } + }); + + frame.setSize(100, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void test() throws Exception { + robot = new Robot(); + robot.waitForIdle(); + + Util.waitTillShown(button); + + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SPACE); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_SPACE); + + Util.waitTillShown(dialog); + dialogShown = true; + + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_K); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_K); + + if (!passedLatch.await(2, TimeUnit.SECONDS)) { + throw new RuntimeException("Test failed!"); + } + + System.out.println("Test passed."); + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java new file mode 100644 index 00000000000..aa50d814264 --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java @@ -0,0 +1,99 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.FileInputStream; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.OptionalDataException; + +/** + * @test + * @bug 8367384 + * @summary Verify ICC_Profile serialization per spec, all name/data cases + */ +public final class SerializationSpecTest { + + public static void main(String[] args) throws Exception { + // Serialization form for ICC_Profile includes version, profile name, + // and profile data. If the name is invalid or does not match a standard + // profile, the data is used. An exception is thrown only if both the + // name and the data are invalid, or if one of them is missing or is of + // the wrong type. + + // Naming conventions used in test file names: + // null : null reference + // valid : valid standard profile name or valid profile data (byte[]) + // invalid : unrecognized name or data with incorrect ICC header + // wrongType: incorrect type, e.g., int[] instead of String or byte[] + + // No name or data + test("empty", OptionalDataException.class); + + // Cases where only the profile name is present (no profile data) + test("null", OptionalDataException.class); + test("valid", OptionalDataException.class); + test("invalid", OptionalDataException.class); + test("wrongType", InvalidObjectException.class); + + // The test files are named as _.ser + test("null_null", InvalidObjectException.class); + test("null_valid", null); // valid data is enough if name is null + test("null_invalid", InvalidObjectException.class); + test("null_wrongType", InvalidObjectException.class); + + test("invalid_null", InvalidObjectException.class); + test("invalid_valid", null); // valid data is enough if name is invalid + test("invalid_invalid", InvalidObjectException.class); + test("invalid_wrongType", InvalidObjectException.class); + + test("wrongType_null", InvalidObjectException.class); + test("wrongType_valid", InvalidObjectException.class); + test("wrongType_invalid", InvalidObjectException.class); + test("wrongType_wrongType", InvalidObjectException.class); + + test("valid_null", null); // the valid name is enough + test("valid_valid", null); // the valid name is enough + test("valid_invalid", null); // the valid name is enough + test("valid_wrongType", InvalidObjectException.class); + } + + private static void test(String test, Class expected) { + String fileName = test + ".ser"; + File file = new File(System.getProperty("test.src", "."), fileName); + Class actual = null; + try (var fis = new FileInputStream(file); + var ois = new ObjectInputStream(fis)) + { + ois.readObject(); + } catch (Exception e) { + actual = e.getClass(); + } + if (actual != expected) { + System.err.println("Test: " + test); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + throw new RuntimeException("Test failed"); + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser new file mode 100644 index 00000000000..3fd70024d65 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser new file mode 100644 index 00000000000..dfe071e69dc Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser new file mode 100644 index 00000000000..60fb02f7783 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser new file mode 100644 index 00000000000..60fb02f7783 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser new file mode 100644 index 00000000000..e01b5766f62 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_wrongType.ser new file mode 100644 index 00000000000..65485f041d7 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser new file mode 100644 index 00000000000..1fc2022f868 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser new file mode 100644 index 00000000000..b2847de4f46 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_null.ser new file mode 100644 index 00000000000..31c87a6cb65 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser new file mode 100644 index 00000000000..b32c838c80a Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_wrongType.ser new file mode 100644 index 00000000000..3279eec381d Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser new file mode 100644 index 00000000000..a6512d244cf Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser new file mode 100644 index 00000000000..dbe11f2c6d6 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser new file mode 100644 index 00000000000..dbe11f2c6d6 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser new file mode 100644 index 00000000000..fbe90d0eb6e Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser new file mode 100644 index 00000000000..3538676276f Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser new file mode 100644 index 00000000000..3469f871ef6 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_invalid.ser new file mode 100644 index 00000000000..7da24ee9b96 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_invalid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser new file mode 100644 index 00000000000..2c1536cc094 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_valid.ser new file mode 100644 index 00000000000..2c1536cc094 Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_valid.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_wrongType.ser new file mode 100644 index 00000000000..8520dffcf4c Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_wrongType.ser differ diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/StandardProfilesRoundTrip.java b/test/jdk/java/awt/color/ICC_Profile/Serialization/StandardProfilesRoundTrip.java new file mode 100644 index 00000000000..6b29fd7f22a --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/Serialization/StandardProfilesRoundTrip.java @@ -0,0 +1,73 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * @test + * @bug 8367384 + * @summary Checks ICC_Profile serialization for standard profiles + */ +public final class StandardProfilesRoundTrip { + + private static final ICC_Profile[] PROFILES = { + ICC_Profile.getInstance(ColorSpace.CS_sRGB), + ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB), + ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ), + ICC_Profile.getInstance(ColorSpace.CS_PYCC), + ICC_Profile.getInstance(ColorSpace.CS_GRAY) + }; + + public static void main(String[] args) throws Exception { + // Test profiles one by one + for (ICC_Profile profile : PROFILES) { + test(profile); + } + // Test all profiles at once + test(PROFILES); + } + + private static void test(ICC_Profile... profiles) throws Exception { + byte[] data; + try (var bos = new ByteArrayOutputStream(); + var oos = new ObjectOutputStream(bos)) + { + for (ICC_Profile p : profiles) { + oos.writeObject(p); + } + data = bos.toByteArray(); + } + try (var ois = new ObjectInputStream(new ByteArrayInputStream(data))) { + for (ICC_Profile p : profiles) { + if (p != ois.readObject()) { + throw new RuntimeException("Wrong deserialized object"); + } + } + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java b/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java new file mode 100644 index 00000000000..3af83ff59bf --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8337703 + * @summary To verify if ICC_Profile's setData() and getInstance() methods + * validate header data and throw IAE for invalid values. + * @run main ValidateICCHeaderData + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; + +public class ValidateICCHeaderData { + private static ICC_Profile profile; + + private static final boolean DEBUG = false; + private static final int VALID_HEADER_SIZE = 128; + private static final int HEADER_TAG = ICC_Profile.icSigHead; + private static final int PROFILE_CLASS_START_INDEX = ICC_Profile.icHdrDeviceClass; + private static final int COLOR_SPACE_START_INDEX = ICC_Profile.icHdrColorSpace; + private static final int RENDER_INTENT_START_INDEX = ICC_Profile.icHdrRenderingIntent; + private static final int PCS_START_INDEX = ICC_Profile.icHdrPcs; + + private static final int[] VALID_PROFILE_CLASS = new int[] { + ICC_Profile.icSigInputClass, ICC_Profile.icSigDisplayClass, + ICC_Profile.icSigOutputClass, ICC_Profile.icSigLinkClass, + ICC_Profile.icSigAbstractClass, ICC_Profile.icSigColorSpaceClass, + ICC_Profile.icSigNamedColorClass + }; + + private static final int[] VALID_COLOR_SPACE = new int[] { + ICC_Profile.icSigXYZData, ICC_Profile.icSigLabData, + ICC_Profile.icSigLuvData, ICC_Profile.icSigYCbCrData, + ICC_Profile.icSigYxyData, ICC_Profile.icSigRgbData, + ICC_Profile.icSigGrayData, ICC_Profile.icSigHsvData, + ICC_Profile.icSigHlsData, ICC_Profile.icSigCmykData, + ICC_Profile.icSigSpace2CLR, ICC_Profile.icSigSpace3CLR, + ICC_Profile.icSigSpace4CLR, ICC_Profile.icSigSpace5CLR, + ICC_Profile.icSigSpace6CLR, ICC_Profile.icSigSpace7CLR, + ICC_Profile.icSigSpace8CLR, ICC_Profile.icSigSpace9CLR, + ICC_Profile.icSigSpaceACLR, ICC_Profile.icSigSpaceBCLR, + ICC_Profile.icSigSpaceCCLR, ICC_Profile.icSigSpaceDCLR, + ICC_Profile.icSigSpaceECLR, ICC_Profile.icSigSpaceFCLR, + ICC_Profile.icSigCmyData + }; + + private static final int[] VALID_RENDER_INTENT = new int[] { + ICC_Profile.icPerceptual, ICC_Profile.icMediaRelativeColorimetric, + ICC_Profile.icSaturation, ICC_Profile.icAbsoluteColorimetric + }; + + private static void createCopyOfBuiltInProfile() { + ICC_Profile builtInProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB); + //copy of SRGB BuiltIn Profile that can be modified + //using ICC_Profile.setData() + profile = ICC_Profile.getInstance(builtInProfile.getData()); + } + + public static void main(String[] args) throws Exception { + createCopyOfBuiltInProfile(); + + System.out.println("CASE 1: Testing VALID Profile Classes ..."); + testValidHeaderData(VALID_PROFILE_CLASS, PROFILE_CLASS_START_INDEX, 4); + System.out.println("CASE 1: Passed \n"); + + // PCS field validation for Profile class != DEVICE_LINK + System.out.println("CASE 2: Testing VALID PCS Type" + + " for Profile class != DEVICE_LINK ..."); + testValidHeaderData(new int[] {ICC_Profile.icSigXYZData, ICC_Profile.icSigLabData}, + PCS_START_INDEX, 4); + System.out.println("CASE 2: Passed \n"); + + System.out.println("CASE 3: Testing INVALID PCS Type" + + " for Profile class != DEVICE_LINK ..."); + testInvalidHeaderData(ICC_Profile.icSigCmykData, PCS_START_INDEX, 4); + System.out.println("CASE 3: Passed \n"); + + System.out.println("CASE 4: Testing DEVICE LINK PROFILE CLASS ..."); + testValidHeaderData(new int[] {ICC_Profile.icSigLinkClass}, + PROFILE_CLASS_START_INDEX, 4); + //to check if instantiating BufferedImage with + //ICC_Profile device class = CLASS_DEVICELINK does not throw IAE. + BufferedImage img = new BufferedImage(100, 100, + BufferedImage.TYPE_3BYTE_BGR); + System.out.println("CASE 4: Passed \n"); + + // PCS field validation for Profile class == DEVICE_LINK + System.out.println("CASE 5: Testing VALID PCS Type" + + " for Profile class == DEVICE_LINK ..."); + testValidHeaderData(VALID_COLOR_SPACE, PCS_START_INDEX, 4); + System.out.println("CASE 5: Passed \n"); + + System.out.println("CASE 6: Testing INVALID PCS Type" + + " for Profile class == DEVICE_LINK ..."); + //original icSigLabData = 0x4C616220 + int invalidSigLabData = 0x4C616221; + testInvalidHeaderData(invalidSigLabData, PCS_START_INDEX, 4); + System.out.println("CASE 6: Passed \n"); + + System.out.println("CASE 7: Testing VALID Color Spaces ..."); + testValidHeaderData(VALID_COLOR_SPACE, COLOR_SPACE_START_INDEX, 4); + System.out.println("CASE 7: Passed \n"); + + System.out.println("CASE 8: Testing VALID Rendering Intent ..."); + testValidHeaderData(VALID_RENDER_INTENT, RENDER_INTENT_START_INDEX, 4); + System.out.println("CASE 8: Passed \n"); + + System.out.println("CASE 9: Testing INVALID Profile Class ..."); + //original icSigInputClass = 0x73636E72 + int invalidSigInputClass = 0x73636E70; + testInvalidHeaderData(invalidSigInputClass, PROFILE_CLASS_START_INDEX, 4); + System.out.println("CASE 9: Passed \n"); + + System.out.println("CASE 10: Testing INVALID Color Space ..."); + //original icSigXYZData = 0x58595A20 + int invalidSigXYZData = 0x58595A21; + testInvalidHeaderData(invalidSigXYZData, COLOR_SPACE_START_INDEX, 4); + System.out.println("CASE 10: Passed \n"); + + System.out.println("CASE 11: Testing INVALID Rendering Intent ..."); + //valid rendering intent values are 0-3 + int invalidRenderIntent = 5; + testInvalidHeaderData(invalidRenderIntent, RENDER_INTENT_START_INDEX, 4); + System.out.println("CASE 11: Passed \n"); + + System.out.println("CASE 12: Testing INVALID Header Size ..."); + testInvalidHeaderSize(); + System.out.println("CASE 12: Passed \n"); + + System.out.println("CASE 13: Testing ICC_Profile.getInstance(..)" + + " with VALID profile data ..."); + testProfileCreation(true); + System.out.println("CASE 13: Passed \n"); + + System.out.println("CASE 14: Testing ICC_Profile.getInstance(..)" + + " with INVALID profile data ..."); + testProfileCreation(false); + System.out.println("CASE 14: Passed \n"); + + System.out.println("CASE 15: Testing loading of ICC_Profile from file ..."); + testLoading(); + System.out.println("CASE 15: Passed \n"); + + System.out.println("Successfully completed testing all 15 cases. Test Passed !!"); + } + + private static void testValidHeaderData(int[] validData, int startIndex, + int fieldLength) { + for (int value : validData) { + setTag(value, startIndex, fieldLength); + } + } + + private static void testInvalidHeaderData(int invalidData, int startIndex, + int fieldLength) { + try { + setTag(invalidData, startIndex, fieldLength); + throw new RuntimeException("Test Failed ! Expected IAE NOT thrown"); + } catch (IllegalArgumentException iae) { + System.out.println("Expected IAE thrown: " + iae.getMessage()); + } + } + + private static void setTag(int value, int startIndex, int fieldLength) { + byte[] byteArray; + if (startIndex == RENDER_INTENT_START_INDEX) { + byteArray = ByteBuffer.allocate(4).putInt(value).array(); + } else { + BigInteger big = BigInteger.valueOf(value); + byteArray = (big.toByteArray()); + } + + if (DEBUG) { + System.out.print("Byte Array : "); + for (int i = 0; i < byteArray.length; i++) { + System.out.print(byteArray[i] + " "); + } + System.out.println("\n"); + } + + byte[] iccProfileHeaderData = profile.getData(HEADER_TAG); + System.arraycopy(byteArray, 0, iccProfileHeaderData, startIndex, fieldLength); + profile.setData(HEADER_TAG, iccProfileHeaderData); + } + + private static void testProfileCreation(boolean validCase) { + ICC_Profile builtInProfile = ICC_Profile.getInstance(ColorSpace.CS_GRAY); + byte[] profileData = builtInProfile.getData(); + + int validDeviceClass = ICC_Profile.icSigInputClass; + BigInteger big = BigInteger.valueOf(validDeviceClass); + //valid case set device class to 0x73636E72 (icSigInputClass) + //invalid case set device class to 0x00000000 + byte[] field = validCase ? big.toByteArray() + : ByteBuffer.allocate(4).putInt(0).array(); + System.arraycopy(field, 0, profileData, PROFILE_CLASS_START_INDEX, 4); + + try { + ICC_Profile.getInstance(profileData); + if (!validCase) { + throw new RuntimeException("Test Failed ! Expected IAE NOT thrown"); + } + } catch (IllegalArgumentException iae) { + if (!validCase) { + System.out.println("Expected IAE thrown: " + iae.getMessage()); + } else { + throw new RuntimeException("Unexpected IAE thrown"); + } + } + } + + private static void testInvalidHeaderSize() { + byte[] iccProfileHeaderData = profile.getData(HEADER_TAG); + byte[] invalidHeaderSize = new byte[VALID_HEADER_SIZE - 1]; + System.arraycopy(iccProfileHeaderData, 0, + invalidHeaderSize, 0, invalidHeaderSize.length); + try { + profile.setData(HEADER_TAG, invalidHeaderSize); + throw new RuntimeException("Test Failed ! Expected IAE NOT thrown"); + } catch (IllegalArgumentException iae) { + System.out.println("Expected IAE thrown: " + iae.getMessage()); + } + } + + private static void testLoading() throws IOException { + // invalidSRGB.icc is a profile file that was produced by an older JDK + // When attempting to load it, the current JDK is expected to throw IAE + try { + ICC_Profile.getInstance("./invalidSRGB.icc"); + throw new RuntimeException("Test Failed ! Expected IAE NOT thrown"); + } catch (IllegalArgumentException iae) { + System.out.println("Expected IAE thrown: " + iae.getMessage()); + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/invalidSRGB.icc b/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/invalidSRGB.icc new file mode 100644 index 00000000000..1520dac1f1a Binary files /dev/null and b/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/invalidSRGB.icc differ diff --git a/test/jdk/java/awt/datatransfer/ClipboardPerformanceTest.java b/test/jdk/java/awt/datatransfer/ClipboardPerformanceTest.java new file mode 100644 index 00000000000..3bad044b949 --- /dev/null +++ b/test/jdk/java/awt/datatransfer/ClipboardPerformanceTest.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4463560 + * @requires (os.family == "windows") + * @summary Tests that datatransfer doesn't take too much time to complete + * @key headful + * @library /test/lib + * @run main/timeout=300 ClipboardPerformanceTest + */ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class ClipboardPerformanceTest { + public static final int CODE_FAILURE = 1; + public static final int CODE_OTHER_FAILURE = 2; + static String eoln; + static char[] text; + public static final int ARRAY_SIZE = 100000; + public static final int RATIO_THRESHOLD = 10; + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + ClipboardPerformanceTest clipboardPerformanceTest = new ClipboardPerformanceTest(); + clipboardPerformanceTest.initialize(); + return; + } + + long before, after, oldTime, newTime; + float ratio; + + try { + Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); + before = System.currentTimeMillis(); + String ss = (String) t.getTransferData(new DataFlavor("text/plain; class=java.lang.String")); + after = System.currentTimeMillis(); + + System.err.println("Size: " + ss.length()); + newTime = after - before; + System.err.println("Time consumed: " + newTime); + + initArray(); + + StringBuffer buf = new StringBuffer(new String(text)); + int eoln_len = eoln.length(); + before = System.currentTimeMillis(); + + for (int i = 0; i + eoln_len <= buf.length(); i++) { + if (eoln.equals(buf.substring(i, i + eoln_len))) { + buf.replace(i, i + eoln_len, "\n"); + } + } + + after = System.currentTimeMillis(); + oldTime = after - before; + System.err.println("Old algorithm: " + oldTime); + ratio = oldTime / newTime; + System.err.println("Ratio: " + ratio); + + if (ratio < RATIO_THRESHOLD) { + System.out.println("Time ratio failure!!"); + System.exit(CODE_FAILURE); + } + } catch (Throwable e) { + e.printStackTrace(); + System.exit(CODE_OTHER_FAILURE); + } + System.out.println("Test Pass!"); + } + + public static void initArray() { + text = new char[ARRAY_SIZE + 2]; + + for (int i = 0; i < ARRAY_SIZE; i += 3) { + text[i] = '\r'; + text[i + 1] = '\n'; + text[i + 2] = 'a'; + } + eoln = "\r\n"; + } + + public void initialize() throws Exception { + initArray(); + Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); + cb.setContents(new StringSelection(new String(text)), null); + + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + ClipboardPerformanceTest.class.getName(), + "child" + ); + + Process process = ProcessTools.startProcess("Child", pb); + OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process); + + if (!process.waitFor(15, TimeUnit.SECONDS)) { + process.destroyForcibly(); + throw new TimeoutException("Timed out waiting for Child"); + } + + outputAnalyzer.shouldHaveExitValue(0); + } +} diff --git a/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java b/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java index a61493b6a58..18159dce64f 100644 --- a/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java +++ b/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,7 +79,7 @@ public void windowClosing(WindowEvent e) { ProcessResults processResults = - // ProcessCommunicator.executeChildProcess(this.getClass()," -cp \"C:\\Documents and Settings\\df153228\\IdeaProjects\\UnicodeTestDebug\\out\\production\\UnicodeTestDebug\" -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 ", args); + // ProcessCommunicator.executeChildProcess(this.getClass()," -cp \"C:\\Documents and Settings\\df153228\\IdeaProjects\\UnicodeTestDebug\\out\\production\\UnicodeTestDebug\" -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 ", args); ProcessCommunicator.executeChildProcess(this.getClass(), args); verifyTestResults(processResults); diff --git a/test/jdk/java/awt/datatransfer/HTMLTransferConsoleOutputTest.java b/test/jdk/java/awt/datatransfer/HTMLTransferConsoleOutputTest.java new file mode 100644 index 00000000000..6a18a11270f --- /dev/null +++ b/test/jdk/java/awt/datatransfer/HTMLTransferConsoleOutputTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4638351 + * @summary tests that HTML transfer doesn't cause console output + * @key headful + * @library /test/lib + * @run main HTMLTransferConsoleOutputTest + */ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class HTMLTransferConsoleOutputTest implements ClipboardOwner { + static final Clipboard clipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + static final DataFlavor dataFlavor = + new DataFlavor("text/html; class=java.lang.String", null); + static final String magic = "TESTMAGICSTRING"; + static final Transferable transferable = new Transferable() { + final DataFlavor[] flavors = new DataFlavor[]{dataFlavor}; + final String data = "" + magic + ""; + + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + public boolean isDataFlavorSupported(DataFlavor df) { + return dataFlavor.equals(df); + } + + public Object getTransferData(DataFlavor df) + throws UnsupportedFlavorException { + if (!isDataFlavorSupported(df)) { + throw new UnsupportedFlavorException(df); + } + return data; + } + }; + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + public static final int CLIPBOARD_DELAY = 1000; + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + HTMLTransferConsoleOutputTest htmlTransferConsoleOutputTest = new HTMLTransferConsoleOutputTest(); + htmlTransferConsoleOutputTest.initialize(); + return; + } + final ClipboardOwner clipboardOwner = new ClipboardOwner() { + public void lostOwnership(Clipboard clip, + Transferable contents) { + System.exit(0); + } + }; + clipboard.setContents(transferable, clipboardOwner); + final Object o = new Object(); + synchronized (o) { + try { + o.wait(); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + System.out.println("Test Pass!"); + } + + public void initialize() throws Exception { + clipboard.setContents(transferable, this); + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + HTMLTransferConsoleOutputTest.class.getName(), + "child" + ); + + Process process = ProcessTools.startProcess("Child", pb); + OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process); + + if (!process.waitFor(15, TimeUnit.SECONDS)) { + process.destroyForcibly(); + throw new TimeoutException("Timed out waiting for Child"); + } + + byte[] bytes = baos.toByteArray(); + String string = null; + try { + string = new String(bytes, "ASCII"); + } catch (UnsupportedEncodingException uee) { + uee.printStackTrace(); + } + if (string.lastIndexOf(magic) != -1) { + throw new RuntimeException("Test failed. Output contains:" + + string); + } + + outputAnalyzer.shouldHaveExitValue(0); + } + + + static class ForkOutputStream extends OutputStream { + final OutputStream outputStream1; + final OutputStream outputStream2; + + public ForkOutputStream(OutputStream os1, OutputStream os2) { + outputStream1 = os1; + outputStream2 = os2; + } + + public void write(int b) throws IOException { + outputStream1.write(b); + outputStream2.write(b); + } + + public void flush() throws IOException { + outputStream1.flush(); + outputStream2.flush(); + } + + public void close() throws IOException { + outputStream1.close(); + outputStream2.close(); + } + } + + public void lostOwnership(Clipboard clip, Transferable contents) { + final Runnable r = () -> { + try { + Thread.sleep(CLIPBOARD_DELAY); + } catch (InterruptedException e) { + e.printStackTrace(); + } + final PrintStream oldOut = System.out; + final PrintStream newOut = + new PrintStream(new ForkOutputStream(oldOut, baos)); + Transferable t = clipboard.getContents(null); + try { + System.setOut(newOut); + t.getTransferData(dataFlavor); + System.setOut(oldOut); + } catch (IOException | UnsupportedFlavorException ioe) { + ioe.printStackTrace(); + } + clipboard.setContents(transferable, null); + }; + final Thread t = new Thread(r); + t.start(); + } +} diff --git a/test/jdk/java/awt/datatransfer/ImageTransferCrashTest.java b/test/jdk/java/awt/datatransfer/ImageTransferCrashTest.java new file mode 100644 index 00000000000..76e484b3ce2 --- /dev/null +++ b/test/jdk/java/awt/datatransfer/ImageTransferCrashTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4513976 + * @summary tests that inter-JVM image transfer doesn't cause crash + * @key headful + * @library /test/lib + * @run main ImageTransferCrashTest + */ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.image.BufferedImage; +import java.awt.image.WritableRaster; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class ImageTransferCrashTest implements ClipboardOwner { + static final Clipboard clipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + final Transferable textTransferable = new StringSelection("TEXT"); + public static final int CLIPBOARD_DELAY = 10; + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + ImageTransferCrashTest imageTransferCrashTest = new ImageTransferCrashTest(); + imageTransferCrashTest.initialize(); + return; + } + final ClipboardOwner clipboardOwner = (clip, contents) -> System.exit(0); + final int width = 100; + final int height = 100; + final BufferedImage bufferedImage = + new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + final WritableRaster writableRaster = + bufferedImage.getWritableTile(0, 0); + final int[] color = new int[]{0x80, 0x80, 0x80}; + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + writableRaster.setPixel(i, j, color); + } + } + bufferedImage.releaseWritableTile(0, 0); + + final Transferable imageTransferable = new Transferable() { + final DataFlavor[] flavors = new DataFlavor[]{ + DataFlavor.imageFlavor}; + + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + public boolean isDataFlavorSupported(DataFlavor df) { + return DataFlavor.imageFlavor.equals(df); + } + + public Object getTransferData(DataFlavor df) + throws UnsupportedFlavorException { + if (!isDataFlavorSupported(df)) { + throw new UnsupportedFlavorException(df); + } + return bufferedImage; + } + }; + clipboard.setContents(imageTransferable, clipboardOwner); + final Object o = new Object(); + synchronized (o) { + try { + o.wait(); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + System.out.println("Test Pass!"); + } + + public void initialize() throws Exception { + clipboard.setContents(textTransferable, this); + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + ImageTransferCrashTest.class.getName(), + "child" + ); + + Process process = ProcessTools.startProcess("Child", pb); + OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process); + + if (!process.waitFor(15, TimeUnit.SECONDS)) { + process.destroyForcibly(); + throw new TimeoutException("Timed out waiting for Child"); + } + + outputAnalyzer.shouldHaveExitValue(0); + } + + public void lostOwnership(Clipboard clip, Transferable contents) { + final Runnable r = () -> { + while (true) { + try { + Thread.sleep(CLIPBOARD_DELAY); + Transferable t = clipboard.getContents(null); + t.getTransferData(DataFlavor.imageFlavor); + } catch (IllegalStateException e) { + e.printStackTrace(); + System.err.println("clipboard is not prepared yet"); + continue; + } catch (Exception e) { + e.printStackTrace(); + } + break; + } + clipboard.setContents(textTransferable, null); + }; + final Thread t = new Thread(r); + t.start(); + } +} diff --git a/test/jdk/java/awt/event/InputEvent/InputEventTimeTest.java b/test/jdk/java/awt/event/InputEvent/InputEventTimeTest.java new file mode 100644 index 00000000000..38339f8e877 --- /dev/null +++ b/test/jdk/java/awt/event/InputEvent/InputEventTimeTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4176525 + * @summary InputEvent.getWhen() returns the wrong event time. + * @key headful + * @run main InputEventTimeTest + */ + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.Date; + +public class InputEventTimeTest extends Frame { + public void initUI() { + setTitle("Input Event Time Test"); + enableEvents(AWTEvent.MOUSE_EVENT_MASK); + enableEvents(AWTEvent.KEY_EVENT_MASK); + setSize(200, 200); + setLocationRelativeTo(null); + setVisible(true); + } + + public void center(Point point) { + Point loc = getLocationOnScreen(); + Dimension size = getSize(); + point.setLocation(loc.x + (size.width / 2), loc.y + (size.height / 2)); + } + + public void processEvent(AWTEvent e) { + long currentTime; + long eventTime; + long difference; + + if (!(e instanceof InputEvent)) { + return; + } + + currentTime = (new Date()).getTime(); + eventTime = ((InputEvent) e).getWhen(); + difference = currentTime - eventTime; + + if ((difference > 5000) || (difference < -5000)) { + throw new RuntimeException("The difference between current time" + + " and event creation time is " + difference + "ms"); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + InputEventTimeTest test = new InputEventTimeTest(); + try { + EventQueue.invokeAndWait(test::initUI); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.waitForIdle(); + robot.delay(1000); + Point center = new Point(); + EventQueue.invokeAndWait(() -> test.center(center)); + robot.mouseMove(center.x, center.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON2_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON2_DOWN_MASK); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + for (int i = 0; i < 6; i++) { + robot.keyPress(KeyEvent.VK_A + i); + robot.keyRelease(KeyEvent.VK_A + i); + robot.waitForIdle(); + } + for (int i = 0; i < 150; i += 5) { + robot.mouseMove(center.x - i, center.y - i); + } + for (int i = 150; i > 0; i -= 5) { + robot.mouseMove(center.x - i, center.y - i); + } + } finally { + EventQueue.invokeAndWait(test::dispose); + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/AltGrTest.java b/test/jdk/java/awt/event/KeyEvent/AltGrTest.java new file mode 100644 index 00000000000..9f771ea7e19 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/AltGrTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4122687 4209844 + * @summary Characters typed with AltGr have Alt bit set on + * KEY_TYPED events + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AltGrTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +public class AltGrTest extends Frame implements KeyListener { + static String INSTRUCTIONS = """ + Switch to German (Germany) keyboard layout and type + few characters using key. + Note: on windows keyboards without an AltGr key, + you should use Ctrl-Alt to synthesize AltGr. + For example, on German keyboards, `@' is AltGr-Q + `{' is AltGr-7 and '[' is AltGr-8 + If you see the corresponding symbols appear in the text field + and there are no entries in log area starting with word "FAIL:" + press "Pass", otherwise press "Fail". + """; + + public AltGrTest() { + setLayout(new BorderLayout()); + TextField entry = new TextField(); + entry.addKeyListener(this); + add(entry, BorderLayout.CENTER); + pack(); + } + + public void keyTyped(KeyEvent e) { + PassFailJFrame.log("----"); + PassFailJFrame.log("Got " + e); + + if (e.isControlDown() || e.isAltDown()) { + PassFailJFrame.log("FAIL: character typed has following modifiers bits set:"); + PassFailJFrame.log((e.isControlDown() ? " Control" : "") + + (e.isAltDown() ? " Alt" : "")); + } + + if (!(e.isAltGraphDown())) { + PassFailJFrame.log("FAIL: AltGraph modifier is missing"); + } + } + + public void keyPressed(KeyEvent ignore) {} + public void keyReleased(KeyEvent ignore) {} + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(AltGrTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/CRTest.java b/test/jdk/java/awt/event/KeyEvent/CRTest.java new file mode 100644 index 00000000000..0cc17fd568e --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/CRTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4257434 + * @summary Ensures that the right results are produced by the + * carriage return keys. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual CRTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class CRTest extends Frame implements KeyListener, ActionListener { + StringBuilder error = new StringBuilder(); + AtomicBoolean actionCompleted = new AtomicBoolean(false); + static String INSTRUCTIONS = """ + This test requires keyboard with the numeric keypad (numpad). + If your keyboard does not have numpad press "Pass" to skip testing. + Click on the text field in window named "Check KeyChar values". + Press Enter on keypad. Then press Return key on a standard keyboard. + Then click on "Done" button. Test will pass or fail automatically. + """; + + public CRTest() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + + tf.addKeyListener(this); + tf.addActionListener(this); + + add(tf, BorderLayout.CENTER); + + Button done = new Button("Done"); + done.addActionListener((event) -> { + checkAndComplete(); + }); + add(done, BorderLayout.SOUTH); + pack(); + } + + public void checkAndComplete() { + if (!actionCompleted.get()) { + error.append("\nNo action received!"); + } + + if (!error.isEmpty()) { + PassFailJFrame.forceFail(error.toString()); + } else { + PassFailJFrame.forcePass(); + } + } + + public void keyPressed(KeyEvent evt) { + if ((evt.getKeyChar() != '\n') || (evt.getKeyCode() != KeyEvent.VK_ENTER)) { + error.append("\nKeyPressed: Unexpected code " + evt.getKeyCode()); + } else { + PassFailJFrame.log("KeyPressed Test PASSED"); + } + } + + public void keyTyped(KeyEvent evt) { + if ((evt.getKeyChar() != '\n') || (evt.getKeyCode() != KeyEvent.VK_UNDEFINED)) { + error.append("\nKeyTyped: Unexpected code " + evt.getKeyCode()); + } else { + PassFailJFrame.log("KeyTyped Test PASSED"); + } + } + + public void keyReleased(KeyEvent evt) { + if ((evt.getKeyChar() != '\n') || (evt.getKeyCode() != KeyEvent.VK_ENTER)) { + error.append("\nKeyReleased: Unexpected code " + evt.getKeyCode()); + } else { + PassFailJFrame.log("KeyReleased Test PASSED"); + } + } + + public void actionPerformed(ActionEvent evt) { + PassFailJFrame.log("ActionPerformed Test PASSED"); + actionCompleted.set(true); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(CRTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/CharUndefinedTest.java b/test/jdk/java/awt/event/KeyEvent/CharUndefinedTest.java new file mode 100644 index 00000000000..bc58bdab14a --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/CharUndefinedTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4115484 4164672 4167893 + * @summary Ensures that KeyEvent has right keyChar for modifier and action keys. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual CharUndefinedTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +public class CharUndefinedTest extends Frame implements KeyListener { + + static String INSTRUCTIONS = """ + Click on the text field inside the window named "Check KeyChar values". + Of any of the keys mentioned in this list that exist on your keyboard + press each of the listed keys once and also press them in two-key combinations such as + Control-Shift or Alt-Control. + The list of keys is: "Control, Shift, Meta, Alt, Command, Option". + After that press all function keys from F1 to F12 once, + Insert, Home, End, PageUp, PageDown and four arrow keys. + Check the log area below. If there are no messages starting with word "ERROR" + press "Pass" otherwise press "Fail". + """; + + public CharUndefinedTest() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + tf.requestFocus(); + } + + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { + PassFailJFrame.log("ERROR: KeyPressed: keyChar = " + e.getKeyChar() + + " keyCode = " + e.getKeyCode() + " " + e.getKeyText(e.getKeyCode())); + } + } + + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { + PassFailJFrame.log("ERROR: KeyTyped: keyChar = " + e.getKeyChar() + + " keyCode = " + e.getKeyCode() + " " + e.getKeyText(e.getKeyCode())); + } + } + + public void keyReleased(KeyEvent e) { + if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { + PassFailJFrame.log("ERROR: KeyReleased: keyChar = " + e.getKeyChar() + + " keyCode = " + e.getKeyCode() + " " + e.getKeyText(e.getKeyCode())); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .logArea(10) + .testUI(CharUndefinedTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/ExtendedKeysTest.java b/test/jdk/java/awt/event/KeyEvent/ExtendedKeysTest.java new file mode 100644 index 00000000000..1423b2a007e --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/ExtendedKeysTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4218892 4191924 4199284 + * @summary Unable to enter some chars via european keyboard layout(s) + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ExtendedKeysTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextArea; +import java.lang.reflect.InvocationTargetException; + +public class ExtendedKeysTest extends Frame { + static String INSTRUCTIONS = """ + This test requires Swiss German input. If the Swiss German input + can not be installed or configured press "Pass" to skip testing. + Click on the text area inside the window named "Check input". + Switch to Swiss German input and press key with "\\" on it + (usually this key is above or to the left of the main "Enter" key). + If you see a dollar sign press "Pass". + If you see any other character or question mark press "Fail". + """; + + public ExtendedKeysTest() { + super("Check input"); + setLayout(new BorderLayout()); + add(new TextArea(20, 20), "Center"); + pack(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .logArea(10) + .testUI(ExtendedKeysTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyDownCaptureTest.java b/test/jdk/java/awt/event/KeyEvent/KeyDownCaptureTest.java new file mode 100644 index 00000000000..bf2ab7ae958 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyDownCaptureTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4093998 + * @summary keyDown not called on subclasses of Component + * @key headful + * @run main KeyDownCaptureTest + */ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class KeyDownCaptureTest extends Frame implements KeyListener { + static AtomicBoolean passed = new AtomicBoolean(false); + + public KeyDownCaptureTest() { + super("Key Down Capture Test"); + } + + public void initUI() { + setLayout (new BorderLayout()); + setSize(200, 200); + setLocationRelativeTo(null); + Canvas canvas = new Canvas(); + canvas.setBackground(Color.RED); + canvas.addKeyListener(this); + add(canvas, BorderLayout.CENTER); + setVisible(true); + } + + public void middle(Point p) { + Point loc = getLocationOnScreen(); + Dimension size = getSize(); + p.setLocation(loc.x + (size.width / 2), loc.y + (size.height / 2)); + } + + @Override + public void keyTyped(KeyEvent ignore) {} + + @Override + public void keyPressed(KeyEvent e) { + passed.set(true); + } + + @Override + public void keyReleased(KeyEvent ignore) {} + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + KeyDownCaptureTest test = new KeyDownCaptureTest(); + try { + EventQueue.invokeAndWait((test::initUI)); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.delay(500); + robot.waitForIdle(); + Point target = new Point(); + EventQueue.invokeAndWait(() -> { + test.middle(target); + }); + robot.mouseMove(target.x, target.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.keyPress(KeyEvent.VK_SPACE); + robot.keyRelease(KeyEvent.VK_SPACE); + robot.delay(100); + robot.waitForIdle(); + if (!passed.get()) { + throw new RuntimeException("KeyPressed has not arrived to canvas"); + } + } finally { + if (test != null) { + EventQueue.invokeAndWait(test::dispose); + } + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyEventToLightweight.java b/test/jdk/java/awt/event/KeyEvent/KeyEventToLightweight.java new file mode 100644 index 00000000000..de832bf2e6d --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyEventToLightweight.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4397557 + * @summary Check that focused lightweight component gets key events + * even if mouse is outside of it or on top of heavyweight component + * @key headful + * @run main KeyEventToLightweight + */ + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.swing.JButton; + +public class KeyEventToLightweight extends Frame { + JButton lwbutton = new JButton("Select Me"); + Button hwbutton = new Button("Heavyweight"); + + AtomicBoolean aTyped = new AtomicBoolean(false); + AtomicBoolean bTyped = new AtomicBoolean(false); + AtomicBoolean cTyped = new AtomicBoolean(false); + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + KeyEventToLightweight test = new KeyEventToLightweight(); + try { + EventQueue.invokeAndWait(test::initUI); + test.performTest(); + } finally { + EventQueue.invokeAndWait(test::dispose); + } + } + + public void initUI() { + this.setLayout(new FlowLayout()); + add(lwbutton); + add(hwbutton); + setSize(200, 200); + setLocationRelativeTo(null); + lwbutton.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_A) { + aTyped.set(true); + } else if (e.getKeyCode() == KeyEvent.VK_B) { + bTyped.set(true); + } else if (e.getKeyCode() == KeyEvent.VK_C) { + cTyped.set(true); + } + } + }); + setVisible(true); + } + + public void middleOf(Component c, Point p) { + Point loc = c.getLocationOnScreen(); + Dimension size = c.getSize(); + p.setLocation(loc.x + (size.width / 2), loc.y + (size.height / 2)); + } + + public void performTest() throws AWTException, InterruptedException, + InvocationTargetException { + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.delay(500); + robot.waitForIdle(); + Point target = new Point(); + EventQueue.invokeAndWait(() -> middleOf(lwbutton, target)); + robot.mouseMove(target.x, target.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(500); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); + robot.mouseMove(target.x - 200, target.y); + robot.keyPress(KeyEvent.VK_B); + robot.keyRelease(KeyEvent.VK_B); + robot.waitForIdle(); + robot.delay(500); + EventQueue.invokeAndWait(() -> middleOf(hwbutton, target)); + robot.mouseMove(target.x, target.y); + robot.keyPress(KeyEvent.VK_C); + robot.keyRelease(KeyEvent.VK_C); + if (!aTyped.get() || !bTyped.get() || !cTyped.get()) { + throw new RuntimeException("Key event was not delivered, case 1: " + + aTyped.get() + ", case 2: " + bTyped.get() + ", case 3: " + + cTyped.get()); + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyModifiers.java b/test/jdk/java/awt/event/KeyEvent/KeyModifiers.java new file mode 100644 index 00000000000..13cc35581db --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyModifiers.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4193779 4174399 + * @summary Ensures that KeyEvents have the right modifiers set + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jdk.test.lib.Platform + * @run main/manual KeyModifiers + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +import jdk.test.lib.Platform; + + +public class KeyModifiers extends Frame implements KeyListener { + public KeyModifiers() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + + String keys; + if (Platform.isWindows()) { + keys = "\"Shift-n\", \"Alt-n\"\n"; + } else if (Platform.isOSX()) { + keys = "\"Shift-n\", \"Alt-n\", \"Command-n\"\n"; + } else { + keys = "\"Shift-n\", \"Alt-n\", \"Meta-n\"\n"; + } + + String INSTRUCTIONS1 = """ + Click on the text field in the window named "Check KeyChar values" + and type the following key combinations: + """; + String INSTRUCTIONS2 = """ + After each combination check that the KeyPressed and KeyTyped modifiers + are correctly displayed. If modifiers are correct press "Pass", + otherwise press "Fail". + """; + PassFailJFrame.builder() + .title("KeyModifiers Test Instructions") + .instructions(INSTRUCTIONS1 + keys + INSTRUCTIONS2) + .columns(45) + .logArea(10) + .testUI(KeyModifiers::new) + .build() + .awaitAndCheck(); + } + + public void keyPressed(KeyEvent evt) { + int kc = evt.getKeyCode(); + + if (kc == KeyEvent.VK_CONTROL) { + return; + } + + if ((kc == KeyEvent.VK_SHIFT) || (kc == KeyEvent.VK_META) || + (kc == KeyEvent.VK_ALT) || (kc == KeyEvent.VK_ALT_GRAPH)) { + PassFailJFrame.log("Key pressed= " + KeyEvent.getKeyText(kc) + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } else { + PassFailJFrame.log("Key pressed = " + evt.getKeyChar() + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } + } + + public void keyTyped(KeyEvent evt) { + int kc = evt.getKeyCode(); + + if (kc == KeyEvent.VK_CONTROL) { + return; + } + + if ((kc == KeyEvent.VK_SHIFT) || (kc == KeyEvent.VK_META) || + (kc == KeyEvent.VK_ALT) || (kc == KeyEvent.VK_ALT_GRAPH)) { + PassFailJFrame.log("Key typed = " + KeyEvent.getKeyText(kc) + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } else { + PassFailJFrame.log("Key typed = " + evt.getKeyChar() + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } + } + + public void keyReleased(KeyEvent evt) { + int kc = evt.getKeyCode(); + + if (kc == KeyEvent.VK_CONTROL) + return; + + if ((kc == KeyEvent.VK_SHIFT) || (kc == KeyEvent.VK_META) || + (kc == KeyEvent.VK_ALT) || (kc == KeyEvent.VK_ALT_GRAPH)) { + PassFailJFrame.log("Key = released " + KeyEvent.getKeyText(kc) + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } else { + PassFailJFrame.log("Key released = " + evt.getKeyChar() + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyPressedModifiers.java b/test/jdk/java/awt/event/KeyEvent/KeyPressedModifiers.java new file mode 100644 index 00000000000..08958bdbac2 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyPressedModifiers.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4174399 + * @summary Check that modifier values are set on a KeyPressed event + * when a modifier key is pressed. + * @key headful + * @run main KeyPressedModifiers + */ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class KeyPressedModifiers extends Frame implements KeyListener { + static AtomicBoolean shiftDown = new AtomicBoolean(false); + static AtomicBoolean controlDown = new AtomicBoolean(false); + static AtomicBoolean altDown = new AtomicBoolean(false); + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + KeyPressedModifiers test = new KeyPressedModifiers(); + try { + EventQueue.invokeAndWait(test::initUI); + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.delay(500); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_ALT); + robot.delay(500); + robot.waitForIdle(); + if (!shiftDown.get() || !controlDown.get() || !altDown.get()) { + String error = "Following key modifiers were not registered:" + + (shiftDown.get() ? "" : " SHIFT") + + (controlDown.get() ? "" : " CONTROL") + + (altDown.get() ? "" : " ALT"); + throw new RuntimeException(error); + } + } finally { + EventQueue.invokeAndWait(test::dispose); + } + } + + public void initUI() { + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + setSize(350, 100); + setVisible(true); + tf.requestFocus(); + } + + public void keyTyped(KeyEvent ignore) { + } + + public void keyReleased(KeyEvent ignore) { + } + + public void keyPressed(KeyEvent e) { + System.out.println(e); + switch (e.getKeyCode()) { + case KeyEvent.VK_SHIFT: + shiftDown.set(e.isShiftDown()); + break; + case KeyEvent.VK_CONTROL: + controlDown.set(e.isControlDown()); + break; + case KeyEvent.VK_ALT: + altDown.set(e.isAltDown()); + break; + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyTest.java b/test/jdk/java/awt/event/KeyEvent/KeyTest.java new file mode 100644 index 00000000000..d11798b4473 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4151419 4090870 4169733 + * @summary Ensures that KeyEvent has right results for the following + * keys -=\[];,./ + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual KeyTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +public class KeyTest extends Frame implements KeyListener { + + static String INSTRUCTIONS = """ + Click on the text field in window named "Check KeyChar values" + Type the following keys/characters in the TextField: + - = \\ [ ] ; , . / + Verify that the keyChar and keyCode is correct for each key pressed. + Remember that the keyCode for the KEY_TYPED event should be zero. + Also verify that the character you typed appears in the TextField. + + Key Name keyChar Keycode + ------------------------------------- + - Minus - 45 45 + = Equals = 61 61 + \\ Slash \\ 92 92 + [ Left Brace [ 91 91 + ] Right Brace ] 93 93 + ; Semicolon ; 59 59 + , Comma , 44 44 + . Period . 46 46 + / Front Slash / 47 47 + """; + public KeyTest() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + + } + + public void keyPressed(KeyEvent evt) { + printKey(evt); + } + + public void keyTyped(KeyEvent evt) { + printKey(evt); + } + + public void keyReleased(KeyEvent evt) { + printKey(evt); + } + + protected void printKey(KeyEvent evt) { + if (evt.isActionKey()) { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar() + " Action Key"); + } else { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar()); + } + } + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + PassFailJFrame.builder() + .title("KeyTest Instructions") + .instructions(INSTRUCTIONS) + .logArea(20) + .testUI(KeyTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/NumpadTest2.java b/test/jdk/java/awt/event/KeyEvent/NumpadTest2.java new file mode 100644 index 00000000000..1ee47354318 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/NumpadTest2.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4279566 + * @summary Tests that numpad keys produce the correct key codes and + * key chars when both the NumLock and CapsLock are on. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NumpadTest2 +*/ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +public class NumpadTest2 extends Frame implements KeyListener { + static String INSTRUCTIONS = """ + Make sure that the NumLock and CapsLock are both ON. + Click on the text field inside the window named "Check KeyChar values" + Then, type the NumPad 7 key (not the regular 7 key). + Verify that the keyChar and keyCode is correct for each key pressed. + Remember that the keyCode for the KEY_TYPED event should be zero. + If 7 appears in the text field and the key code printed is correct + press "Pass", otherwise press "Fail". + + Key Name keyChar Keycode + ------------------------------------------------- + Numpad-7 Numpad-7 55 103 + """; + + public NumpadTest2() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + } + + public void keyPressed(KeyEvent evt) { + printKey(evt); + } + + public void keyTyped(KeyEvent evt) { + printKey(evt); + } + + public void keyReleased(KeyEvent evt) { + printKey(evt); + } + + protected void printKey(KeyEvent evt) { + switch (evt.getID()) { + case KeyEvent.KEY_TYPED: + break; + case KeyEvent.KEY_PRESSED: + break; + case KeyEvent.KEY_RELEASED: + break; + default: + System.out.println("Other Event "); + return; + } + + if (evt.isActionKey()) { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar() + " Action Key"); + } else { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar()); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(NumpadTest2::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/TestDoubleKeyEvent.java b/test/jdk/java/awt/event/KeyEvent/TestDoubleKeyEvent.java new file mode 100644 index 00000000000..24e0bd553c8 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/TestDoubleKeyEvent.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4495473 + * @summary Tests that when you press key on canvas-type heavyweight only one key event arrives + * @key headful + * @run main TestDoubleKeyEvent + */ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; +import javax.swing.JFrame; +import javax.swing.JWindow; +import javax.swing.JTextField; + +public class TestDoubleKeyEvent extends JFrame { + JWindow w; + JTextField tf; + + public void initUI() { + setLayout(new BorderLayout()); + setTitle("Double Key Event Test"); + setLocationRelativeTo(null); + setVisible(true); + w = new JWindow(this); + w.setLayout(new FlowLayout()); + tf = new JTextField(20); + w.add(tf); + w.pack(); + w.setLocationRelativeTo(null); + w.setVisible(true); + tf.requestFocus(); + } + + public void testAndClean() { + String str = tf.getText(); + w.dispose(); + dispose(); + if (str.length() != str.chars().distinct().count()) { + throw new RuntimeException("Duplicate characters found!"); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + TestDoubleKeyEvent test = new TestDoubleKeyEvent(); + EventQueue.invokeAndWait(test::initUI); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.waitForIdle(); + robot.delay(1000); + for (int i = 0; i < 15; i++) { + robot.keyPress(KeyEvent.VK_A + i); + robot.keyRelease(KeyEvent.VK_A + i); + robot.waitForIdle(); + } + robot.delay(1000); + EventQueue.invokeAndWait(test::testAndClean); + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java b/test/jdk/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java index 47d808f336d..c8730b28964 100644 --- a/test/jdk/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java +++ b/test/jdk/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * 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,51 +22,57 @@ */ /* - @test - @bug 8041928 8158616 - @requires (os.family != "mac") - @summary Confirm that the Alt-Gr Modifier bit is set correctly. - @run main/manual AltGraphModifierTest + * @test + * @bug 8041928 8158616 + * @requires (os.family != "mac") + * @summary Confirm that the Alt-Gr Modifier bit is set correctly. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AltGraphModifierTest */ -import java.awt.Button; -import java.awt.Dialog; import java.awt.Frame; -import java.awt.Panel; -import java.awt.TextArea; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class AltGraphModifierTest { - private static void init() throws Exception { - String[] instructions - = { - "This test is for verifying Alt-Gr modifier of an event.", - "Linux :-", - "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. Navigate to System Settings-> Keyboard-> Shortcuts->", - " Typing.", - "4. Select an option for the Alternative Characters Key", - " For example. Right Alt", - "5. Close the settings and navigate to test", - "6. Press Right Alt Key & perform mouse click on the", - " TestWindow", - "7. Test will exit by itself with appropriate result.", - " ", - }; - Sysout.createDialog(); - Sysout.printInstructions(instructions); + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + This test is for verifying Alt-Gr modifier of an event. + Please check if Alt-Gr key is present on keyboard. + If not present, press Pass. + On Windows: + Press Alt-Gr or Right Alt key and simultaneously + perform mouse click on the "TestWindow". + On Linux: + Navigate to + System Settings-> Keyboard-> Special Character Entry + Select "Right Alt" option for the "Alternate Characters Key" + Close the settings and navigate to test + Press Right Alt Key & simultaneously + perform mouse click on the "TestWindow". + + If the system does not have such setting, press Pass. + After the test, change the Setting of "Alternate Characters Key" + back to "Layout default". + + If "Alt-Gr Modifier bit is set" message is displayed in logArea, + press Pass else press Fail. + """; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(AltGraphModifierTest::initTestWindow) + .logArea() + .build() + .awaitAndCheck(); } - static Frame mainFrame; - public static void initTestWindow() { - mainFrame = new Frame(); + public static Frame initTestWindow() { + Frame mainFrame = new Frame(); mainFrame.setTitle("TestWindow"); mainFrame.setBounds(700, 10, 300, 300); mainFrame.addMouseListener(new MouseAdapter() { @@ -74,186 +80,12 @@ public static void initTestWindow() { public void mousePressed(MouseEvent e) { int ex = e.getModifiersEx(); if ((ex & InputEvent.ALT_GRAPH_DOWN_MASK) == 0) { - AltGraphModifierTest.fail("Alt-Gr Modifier bit is not set."); + PassFailJFrame.log("Alt-Gr Modifier bit is not set."); } else { - AltGraphModifierTest.pass(); + PassFailJFrame.log("Alt-Gr Modifier bit is set"); } } }); - mainFrame.setVisible(true); - } - - public static void dispose() { - Sysout.dispose(); - mainFrame.dispose(); - } - - /** - * *************************************************** - * Standard Test Machinery Section DO NOT modify anything in this section -- - * it's a standard chunk of code which has all of the synchronisation - * necessary for the test harness. By keeping it the same in all tests, it - * is easier to read and understand someone else's test, as well as insuring - * that all tests behave correctly with the test harness. There is a section - * following this for test-defined classes - * **************************************************** - */ - private static boolean theTestPassed = false; - private static boolean testGeneratedInterrupt = false; - private static String failureMessage = ""; - private static Thread mainThread = null; - final private static int sleepTime = 300000; - - public static void main(String args[]) throws Exception { - mainThread = Thread.currentThread(); - try { - init(); - initTestWindow(); - } catch (Exception e) { - e.printStackTrace(); - } - try { - mainThread.sleep(sleepTime); - } catch (InterruptedException e) { - dispose(); - if (testGeneratedInterrupt && !theTestPassed) { - throw new Exception(failureMessage); - } - } - if (!testGeneratedInterrupt) { - dispose(); - throw new RuntimeException("Timed out after " + sleepTime / 1000 - + " seconds"); - } - } - - public static synchronized void pass() { - theTestPassed = true; - testGeneratedInterrupt = true; - mainThread.interrupt(); - } - - public static synchronized void fail(String whyFailed) { - theTestPassed = false; - testGeneratedInterrupt = true; - failureMessage = whyFailed; - mainThread.interrupt(); - } -} - -// *********** End Standard Test Machinery Section ********** -/** - * ************************************************** - * Standard Test Machinery DO NOT modify anything below -- it's a standard chunk - * of code whose purpose is to make user interaction uniform, and thereby make - * it simpler to read and understand someone else's test. - * ************************************************** - */ -/** - * This is part of the standard test machinery. It creates a dialog (with the - * instructions), and is the interface for sending text messages to the user. To - * print the instructions, send an array of strings to Sysout.createDialog - * WithInstructions method. Put one line of instructions per array entry. To - * display a message for the tester to see, simply call Sysout.println with the - * string to be displayed. This mimics System.out.println but works within the - * test harness as well as standalone. - */ -class Sysout { - private static TestDialog dialog; - private static Frame frame; - - public static void createDialog() { - frame = new Frame(); - dialog = new TestDialog(frame, "Instructions"); - String[] defInstr = {"Instructions will appear here. ", ""}; - dialog.printInstructions(defInstr); - dialog.show(); - println("Any messages for the tester will display here."); - } - - public static void printInstructions(String[] instructions) { - dialog.printInstructions(instructions); - } - - public static void println(String messageIn) { - dialog.displayMessage(messageIn); - } - - public static void dispose() { - dialog.dispose(); - frame.dispose(); - } -} - -/** - * This is part of the standard test machinery. It provides a place for the test - * instructions to be displayed, and a place for interactive messages to the - * user to be displayed. To have the test instructions displayed, see Sysout. To - * have a message to the user be displayed, see Sysout. Do not call anything in - * this dialog directly. - */ -class TestDialog extends Dialog implements ActionListener { - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - Panel buttonP; - Button failB; - - // 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); - - buttonP = new Panel(); - failB = new Button("Fail"); - failB.setActionCommand("fail"); - failB.addActionListener(this); - buttonP.add("Center", failB); - - add("South", buttonP); - pack(); - setVisible(true); - } - - // DO NOT call this directly, go through Sysout - public void printInstructions(String[] instructions) { - instructionsText.setText(""); - String printStr, remainingStr; - for (int i = 0; i < instructions.length; i++) { - remainingStr = instructions[i]; - while (remainingStr.length() > 0) { - if (remainingStr.length() >= maxStringLength) { - int posOfSpace = remainingStr. - lastIndexOf(' ', maxStringLength - 1); - - if (posOfSpace <= 0) { - posOfSpace = maxStringLength - 1; - } - - printStr = remainingStr.substring(0, posOfSpace + 1); - remainingStr = remainingStr.substring(posOfSpace + 1); - } - else { - printStr = remainingStr; - remainingStr = ""; - } - instructionsText.append(printStr + "\n"); - } - } - } - - public void displayMessage(String messageIn) { - messageText.append(messageIn + "\n"); - } - - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand() == "fail") { - AltGraphModifierTest.fail("User Clicked Fail"); - } + return mainFrame; } } diff --git a/test/jdk/java/awt/event/MouseWheelEvent/HWWheelScroll.java b/test/jdk/java/awt/event/MouseWheelEvent/HWWheelScroll.java new file mode 100644 index 00000000000..2851ff668fe --- /dev/null +++ b/test/jdk/java/awt/event/MouseWheelEvent/HWWheelScroll.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4425654 + * @summary Test wheel scrolling of heavyweight components + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual HWWheelScroll + */ + +import java.awt.Choice; +import java.awt.FileDialog; +import java.awt.Frame; +import java.awt.List; +import java.awt.TextArea; +import java.awt.Window; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; + +public class HWWheelScroll { + public static final int TEXT_TALL = 0; + public static final int TEXT_WIDE = 1; + public static final int TEXT_SMALL = 2; + public static final int TEXT_BIG = 3; + static String INSTRUCTIONS = """ + Test for mouse wheel scrolling of heavyweight components with built-in + scrollbars or similar functionality that is controlled by guestures + such as Apple Magic Mouse or trackpad scrolling guesture. + Several windows containing either a TextArea, List, Choice, or a + FileDialog will appear. For each window, use the mouse wheel to + scroll its content, and then minimize it or move away + and continue with the next window. + Do not close any of the opened windows except the FileDialog. + For the FileDialog, first change to a directory with enough items that a + scrollbar appears. + Some of the other windows don't have enough text to warrant scrollbars, + but should be tested anyway to make sure no crash or hang occurs. + If all scrollbars scroll correctly, press "Pass", otherwise press "Fail". + """; + + public static ArrayList initUI() { + ArrayList retValue = new ArrayList<>(); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_BOTH, TEXT_BIG)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_BOTH, TEXT_TALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_BOTH, TEXT_SMALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_BOTH, TEXT_WIDE)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_VERTICAL_ONLY, TEXT_TALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_VERTICAL_ONLY, TEXT_SMALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_HORIZONTAL_ONLY, TEXT_SMALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_HORIZONTAL_ONLY, TEXT_WIDE)); + retValue.add(makeListFrame(TEXT_TALL)); + retValue.add(makeListFrame(TEXT_WIDE)); + retValue.add(makeListFrame(TEXT_SMALL)); + Frame f = new Frame("File Dialog Owner"); + f.setSize(150, 150); + f.setLocationRelativeTo(null); + FileDialog fd = new FileDialog(f, "FileDialog"); + fd.setDirectory("."); + retValue.add(fd); + retValue.add(f); + Frame choiceFrame = new Frame("Choice"); + Choice c = new Choice(); + for (int i = 0; i < 50; i++) { + c.add(i + " choice item"); + } + choiceFrame.add(c); + choiceFrame.setSize(150, 150); + choiceFrame.setLocationRelativeTo(null); + retValue.add(choiceFrame); + return retValue; + } + + public static Frame makeTextFrame(int policy, int textShape) { + Frame f = new Frame("TextArea"); + f.add(makeTextArea(policy, textShape)); + f.setSize(150, 150); + f.setLocationRelativeTo(null); + return f; + } + + public static Frame makeListFrame(int textShape) { + Frame f = new Frame("List"); + f.add(makeList(textShape)); + f.setSize(150, 150); + f.setLocationRelativeTo(null); + return f; + } + + public static TextArea makeTextArea(int policy, int textShape) { + TextArea ta = new TextArea("", 0, 0, policy); + if (textShape == TEXT_TALL) { + for (int i = 0; i < 50 ; i++) { + ta.append(i + "\n"); + } + } else if (textShape == TEXT_WIDE) { + for (int i = 0; i < 2; i++) { + ta.append(i + "very, very, very, very, very, very, very, long line of text number\n"); + } + } else if (textShape == TEXT_SMALL) { + ta.append("text"); + } else if (textShape == TEXT_BIG) { + for (int i = 0; i < 50 ; i++) { + ta.append(i + "very, very, very, very, very, very, very, long line of text number\n"); + } + } + return ta; + } + + public static List makeList(int textShape) { + java.awt.List l = new java.awt.List(); + if (textShape == TEXT_TALL) { + for (int i = 0; i < 50 ; i++) { + l.add(" " + i + " "); + } + } else if (textShape == TEXT_WIDE) { + for (int i = 0; i < 2 ; i++) { + l.add(i + "very, very, very, very, very, very, very, long line of text number"); + } + } else if (textShape == TEXT_SMALL) { + l.add("text"); + } else if (textShape == TEXT_BIG) { + for (int i = 0; i < 50 ; i++) { + l.add(i + "very, very, very, very, very, very, very, long line of text number"); + } + } + return l; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(HWWheelScroll::initUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/MouseWheelEvent/WheelEventCoord.java b/test/jdk/java/awt/event/MouseWheelEvent/WheelEventCoord.java new file mode 100644 index 00000000000..418151d3798 --- /dev/null +++ b/test/jdk/java/awt/event/MouseWheelEvent/WheelEventCoord.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4492456 + * @summary MouseWheelEvent coordinates are wrong + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual WheelEventCoord + */ + +import java.awt.Button; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GridLayout; +import java.lang.reflect.InvocationTargetException; + +public class WheelEventCoord extends Frame { + static String INSTRUCTIONS = """ + This test requires mouse with scrolling wheel or device, + that has capability to simulate scrolling wheel with gestures + such as Apple mouse or a trackpad with gesture control. + If you do not have such device press "Pass". + Move mouse to the top of the button named "Button 1". + While constantly turning mouse wheel up and down slowly move + mouse cursor until it reaches bottom of the button named "Button 3". + While doing so look at the log area. + If despite the wheel direction y coordinate is steadily increases + as you move the mouse down press "Pass". + If y coordinate decreases when cursor is moving down or suddenly jumps + by more than 50 points when crossing to another button press "Fail". + """; + + public WheelEventCoord() { + super("Wheel Event Coordinates"); + setLayout(new GridLayout(3, 1)); + + add(new BigButton("Button 1")); + add(new BigButton("Button 2")); + add(new BigButton("Button 3")); + + addMouseWheelListener(e -> PassFailJFrame.log("Mouse y coordinate = " + e.getY())); + pack(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Wheel Event Coordinates Instructions") + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(WheelEventCoord::new) + .build() + .awaitAndCheck(); + } +} + +class BigButton extends Button { + public BigButton(String label) { + super(label); + } + + public Dimension getPreferredSize() { + return new Dimension(300, 100); + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getMaximumSize() { + return getPreferredSize(); + } +} diff --git a/test/jdk/java/awt/event/MouseWheelEvent/WheelScrollEnabled.java b/test/jdk/java/awt/event/MouseWheelEvent/WheelScrollEnabled.java new file mode 100644 index 00000000000..cbdd7676e94 --- /dev/null +++ b/test/jdk/java/awt/event/MouseWheelEvent/WheelScrollEnabled.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4372477 + * @summary Test disabling of wheel scrolling + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual WheelScrollEnabled + */ + +import java.awt.BorderLayout; +import java.awt.Checkbox; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.lang.reflect.InvocationTargetException; + +public class WheelScrollEnabled extends Frame { + static String INSTRUCTIONS = """ + This test requires mouse with a scrolling wheel or + device that is able to simulate scrolling using gestures. + If you do not have such device press "Pass" to skip testing. + You should see a ScrollPane with some labels in it and two checkboxes. + For each of the four combinations of the two checkboxes, + move the cursor over the ScrollPane and rotate the mouse wheel. + When (and ONLY when) the 'WheelListener added' checkbox is checked, + scrolling the mouse wheel should produce a text message in the log area. + When (and ONLY when) the 'Wheel scrolling enabled' checkbox is checked, + the ScrollPane should scroll when mouse wheel is scrolled on top of it. + If all four checkbox combinations work properly press "Pass", + otherwise press "Fail". + """; + MouseWheelListener mwl; + Checkbox cb; + Checkbox cb2; + ScrollPane sp; + + public WheelScrollEnabled() { + setLayout(new BorderLayout()); + Panel pnl = new Panel(); + pnl.setLayout(new GridLayout(10, 10)); + for (int i = 0; i < 100; i++) { + pnl.add(new Label("Label " + i)); + } + sp = new ScrollPane(); + sp.add(pnl); + sp.setWheelScrollingEnabled(false); + mwl = new MouseWheelListener() { + int i; + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + PassFailJFrame.log("mouseWheelMoved " + i++); + } + }; + sp.addMouseWheelListener(mwl); + add(sp, BorderLayout.CENTER); + + Panel pl2 = new Panel(); + ItemListener il = new ControlListener(); + + cb = new Checkbox("WheelListener added", true); + cb.addItemListener(il); + pl2.add(cb); + + cb2 = new Checkbox("Wheel scrolling enabled", false); + cb2.addItemListener(il); + pl2.add(cb2); + + add(pl2, BorderLayout.SOUTH); + setSize(400, 200); + } + + class ControlListener implements ItemListener { + public void itemStateChanged(ItemEvent e) { + if (e.getSource() == cb) { + boolean state = cb.getState(); + if (state) { + sp.addMouseWheelListener(mwl); + } + else { + sp.removeMouseWheelListener(mwl); + } + } + if (e.getSource() == cb2) { + sp.setWheelScrollingEnabled(cb2.getState()); + } + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Wheel Scroll Enabled Instructions") + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(WheelScrollEnabled::new) + .build() + .awaitAndCheck(); + } +} + diff --git a/test/jdk/java/awt/font/FontNames/LocaleFamilyNames.java b/test/jdk/java/awt/font/FontNames/LocaleFamilyNames.java index 5356464334e..0fc27ea3de0 100644 --- a/test/jdk/java/awt/font/FontNames/LocaleFamilyNames.java +++ b/test/jdk/java/awt/font/FontNames/LocaleFamilyNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * 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,29 +26,32 @@ * @bug 4935798 6521210 6901159 * @summary Tests that all family names that are reported in all locales * correspond to some font returned from getAllFonts(). - * @run main LocaleFamilyNames + * @run main/othervm/timeout=360 LocaleFamilyNames */ import java.awt.*; import java.util.*; public class LocaleFamilyNames { public static void main(String[] args) throws Exception { + System.out.println("Start time: " + java.time.LocalDateTime.now()); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - Font[] all_fonts = ge.getAllFonts(); - Locale[] all_locales = Locale.getAvailableLocales(); + System.out.println("Number of fonts: " + all_fonts.length); + System.out.println("Number of locales: " + all_locales.length); + HashSet all_families = new HashSet(); for (int i=0; i s.endsWith(".xbm")); + + for (File file : files) { + String fileName = file.getName(); + validCase = fileName.startsWith("valid"); + + System.out.println("--- Testing " + fileName + " ---"); + try (FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream errContent = new ByteArrayOutputStream()) { + System.setErr(new PrintStream(errContent)); + + ImageIcon icon = new ImageIcon(fis.readAllBytes()); + boolean isErrEmpty = errContent.toString().isEmpty(); + if (!isErrEmpty) { + System.out.println("Expected ImageFormatException occurred."); + System.out.print(errContent); + } + + if (validCase && !isErrEmpty) { + throw new RuntimeException("Test failed: Error stream not empty"); + } else if (!validCase && isErrEmpty) { + throw new RuntimeException("Test failed: ImageFormatException" + + " expected but not thrown"); + } + System.out.println("PASSED\n"); + } finally { + System.setErr(originalErr); + } + } + } +} diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid.xbm new file mode 100644 index 00000000000..8a8cfc27632 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid.xbm @@ -0,0 +1,2 @@ +#define k_ht 3 +h` k[] = { 01x0, 42222222222236319330:: diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm new file mode 100644 index 00000000000..c6f819582d0 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm @@ -0,0 +1,3 @@ +#define k_wt 16 +#define k_ht 1 +k[] = { 0x10, 1234567890}; diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm new file mode 100644 index 00000000000..5244651a4cb --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm @@ -0,0 +1,3 @@ +#define k_wt 16 +#define k_ht 0 +k[] = { 0x10, 0x12}; diff --git a/test/jdk/java/awt/image/XBMDecoder/valid.xbm b/test/jdk/java/awt/image/XBMDecoder/valid.xbm new file mode 100644 index 00000000000..23b57b2c811 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/valid.xbm @@ -0,0 +1,6 @@ +#define test_width 16 +#define test_height 3 +#define ht_x 1 +#define ht_y 2 +static unsigned char test_bits[] = { +0x13, 0x11, 0x15, 0x00, 0xAB, 0xcd }; diff --git a/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm new file mode 100644 index 00000000000..e365d802447 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm @@ -0,0 +1,4 @@ +#define test_width 16 +#define test_height 2 +static unsigned char test_bits[] = { 0x13, 0x11, + 0xAB, 0xff }; diff --git a/test/jdk/java/awt/print/Dialog/DialogType.java b/test/jdk/java/awt/print/Dialog/DialogType.java index 472b89e44f2..b8801583dd0 100644 --- a/test/jdk/java/awt/print/Dialog/DialogType.java +++ b/test/jdk/java/awt/print/Dialog/DialogType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * 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,49 +26,63 @@ * @bug 6568874 * @key printer * @summary Verify the native dialog works with attribute sets. - * @run main/manual=yesno DialogType + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual DialogType */ -import java.awt.print.*; -import javax.print.attribute.*; -import javax.print.attribute.standard.*; +import java.awt.print.PrinterJob; + +import javax.print.attribute.Attribute; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.DialogTypeSelection; + +import jtreg.SkippedException; public class DialogType { + private static PrinterJob job; + + private static final String INSTRUCTIONS = """ + Two print dialogs are shown in succession. + Click Cancel in the dialogs to close them. + + On macOS & on Windows, the first dialog is a native + dialog provided by the OS, the second dialog is + implemented in Swing, the dialogs differ in appearance. - static String[] instructions = { - "This test assumes and requires that you have a printer installed", - "It verifies that the dialogs behave properly when using new API", - "to optionally select a native dialog where one is present.", - "Two dialogs are shown in succession.", - "The test passes as long as no exceptions are thrown, *AND*", - "if running on Windows only, the first dialog is a native windows", - "control which differs in appearance from the second dialog", - "" - }; + The test passes as long as no exceptions are thrown. + (If there's an exception, the test will fail automatically.) - public static void main(String[] args) { + The test verifies that the dialogs behave properly when using new API + to optionally select a native dialog where one is present. + """; - for (int i=0;i { + robot.delay(2000); + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); + }); + t1.start(); + PageFormat newFormat = pj.pageDialog(oldFormat); + if (!newFormat.equals(oldFormat)) { + throw new RuntimeException("Original PageFormat not returned on cancelling PageDialog"); + } + } +} + diff --git a/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java b/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java index c0a483056df..49e56493488 100644 --- a/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java +++ b/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java @@ -72,6 +72,7 @@ import javax.swing.JTextArea; import javax.swing.Timer; import javax.swing.border.Border; +import javax.swing.event.HyperlinkListener; import javax.swing.text.JTextComponent; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; @@ -98,7 +99,8 @@ * tester. The instructions can be either plain text or HTML. If the * text of the instructions starts with {@code ""}, the * instructions are displayed as HTML, as supported by Swing, which - * provides richer formatting options. + * provides richer formatting options. To handle navigating links in the + * instructions, call {@link Builder#hyperlinkListener} to install a listener. *

* The instructions are displayed in a text component with word-wrapping * so that there's no horizontal scroll bar. If the text doesn't fit, a @@ -592,6 +594,7 @@ private static void createUI(String title, String instructions, frame.add(createInstructionUIPanel(instructions, testTimeOut, rows, columns, + null, false, false, 0), BorderLayout.CENTER); @@ -610,6 +613,7 @@ private static void createUI(Builder builder) { createInstructionUIPanel(builder.instructions, builder.testTimeOut, builder.rows, builder.columns, + builder.hyperlinkListener, builder.screenCapture, builder.addLogArea, builder.logAreaRows); @@ -631,6 +635,7 @@ private static void createUI(Builder builder) { private static JComponent createInstructionUIPanel(String instructions, long testTimeOut, int rows, int columns, + HyperlinkListener hyperlinkListener, boolean enableScreenCapture, boolean addLogArea, int logAreaRows) { @@ -643,6 +648,9 @@ private static JComponent createInstructionUIPanel(String instructions, JTextComponent text = instructions.startsWith("") ? configureHTML(instructions, rows, columns) : configurePlainText(instructions, rows, columns); + if (hyperlinkListener != null && text instanceof JEditorPane ep) { + ep.addHyperlinkListener(hyperlinkListener); + } text.setEditable(false); text.setBorder(createTextBorder()); text.setCaretPosition(0); @@ -716,7 +724,7 @@ private static JTextComponent configureHTML(String instructions, // Reduce the list default margins styles.addRule("ol, ul { margin-left-ltr: 30; margin-left-rtl: 30 }"); // Make the size of code (and other elements) the same as other text - styles.addRule("code, kbd, samp, pre { font-size: inherit }"); + styles.addRule("code, kbd, samp, pre { font-size: inherit; background: #DDD; }"); return text; } @@ -1398,6 +1406,7 @@ public static final class Builder { private int rows; private int columns; private boolean screenCapture; + private HyperlinkListener hyperlinkListener; private boolean addLogArea; private int logAreaRows = 10; @@ -1478,6 +1487,18 @@ public Builder columns(int columns) { return this; } + /** + * Sets a {@link HyperlinkListener} for navigating links inside + * the instructions pane. + * + * @param hyperlinkListener the listener + * @return this builder + */ + public Builder hyperlinkListener(HyperlinkListener hyperlinkListener) { + this.hyperlinkListener = hyperlinkListener; + return this; + } + public Builder screenCapture() { this.screenCapture = true; return this; diff --git a/test/jdk/java/io/File/MacPathTest.java b/test/jdk/java/io/File/MacPathTest.java index c5b50f7e2cf..7082c4c13e9 100644 --- a/test/jdk/java/io/File/MacPathTest.java +++ b/test/jdk/java/io/File/MacPathTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,11 @@ * questions. */ +/* + * This test is launched via a ProcessBuilder in the main test MacPath which + * includes a @requires (os.family == "mac") tag so no operating system + * conditional is applied here. + */ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -29,10 +34,6 @@ public class MacPathTest { public static void main(String args[]) throws Throwable { - String osname = System.getProperty("os.name"); - if (!osname.contains("OS X") && !osname.contains("Darwin")) - return; - // English test("TestDir_apple", // test dir "dir_macosx", // dir diff --git a/test/jdk/java/io/File/MaxPath.java b/test/jdk/java/io/File/MaxPath.java index 658d6a7904b..30951ac0d85 100644 --- a/test/jdk/java/io/File/MaxPath.java +++ b/test/jdk/java/io/File/MaxPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * 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,16 +24,14 @@ /* @test @bug 6481955 @summary Path length less than MAX_PATH (260) works on Windows + @requires (os.family == "windows") */ -import java.io.*; +import java.io.File; +import java.io.IOException; public class MaxPath { public static void main(String[] args) throws Exception { - String osName = System.getProperty("os.name"); - if (!osName.startsWith("Windows")) { - return; - } int MAX_PATH = 260; String dir = new File(".").getAbsolutePath() + "\\"; String padding = "1234567890123456789012345678901234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890"; diff --git a/test/jdk/java/io/File/MaxPathLength.java b/test/jdk/java/io/File/MaxPathLength.java index 0e0b099afd9..02b60f124d1 100644 --- a/test/jdk/java/io/File/MaxPathLength.java +++ b/test/jdk/java/io/File/MaxPathLength.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * 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,30 +24,31 @@ /* @test @bug 4759207 4403166 4165006 4403166 6182812 6274272 7160013 @summary Test to see if win32 path length can be greater than 260 + @library .. /test/lib */ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.DirectoryNotEmptyException; +import jdk.test.lib.Platform; public class MaxPathLength { private static String sep = File.separator; private static String pathComponent = sep + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; private static String fileName = - "areallylongfilenamethatsforsur"; - private static boolean isWindows = false; + "areallylongfilenamethatsforsur"; private static final int MAX_LENGTH = 256; + private static final int FILE_EXISTS_SLEEP = 100; + + private static final int MAX_PATH_COMPONENTS_WINDOWS = 20; + private static int counter = 0; public static void main(String[] args) throws Exception { - String osName = System.getProperty("os.name"); - if (osName.startsWith("Windows")) { - isWindows = true; - } for (int i = 4; i < 7; i++) { String name = fileName; @@ -59,14 +60,9 @@ public static void main(String[] args) throws Exception { } // test long paths on windows - // And these long pathes cannot be handled on Solaris and Mac platforms - if (isWindows) { - String name = fileName; - while (name.length() < MAX_LENGTH) { - testLongPath (20, name, false); - testLongPath (20, name, true); - name = getNextName(name); - } + // And these long paths cannot be handled on Linux and Mac platforms + if (Platform.isWindows()) { + testLongPath(); } } @@ -146,7 +142,7 @@ static void testLongPath(int max, String fn, if (flist == null || !fn.equals(flist[0].getName())) throw new RuntimeException ("File.listFiles() failed"); - if (isWindows && + if (Platform.isWindows() && !fu.getCanonicalPath().equals(f.getCanonicalPath())) throw new RuntimeException ("getCanonicalPath() failed"); @@ -162,7 +158,7 @@ static void testLongPath(int max, String fn, String abPath = f.getAbsolutePath(); if (!abPath.startsWith("\\\\") || abPath.length() < 1093) { - throw new RuntimeException ("File.renameTo() failed for lenth=" + throw new RuntimeException ("File.renameTo() failed for length=" + abPath.length()); } } else { @@ -189,7 +185,7 @@ static void testLongPath(int max, String fn, Files.deleteIfExists(p); // Test if the file is really deleted and wait for 1 second at most for (int j = 0; j < 10 && Files.exists(p); j++) { - Thread.sleep(100); + Thread.sleep(FILE_EXISTS_SLEEP); } } catch (DirectoryNotEmptyException ex) { // Give up the clean-up, let jtreg handle it. @@ -199,4 +195,13 @@ static void testLongPath(int max, String fn, } } } -} + + private static void testLongPath () throws Exception { + String name = fileName; + while (name.length() < MAX_LENGTH) { + testLongPath(MAX_PATH_COMPONENTS_WINDOWS, name, false); + testLongPath(MAX_PATH_COMPONENTS_WINDOWS, name, true); + name = getNextName(name); + } + } +} \ No newline at end of file diff --git a/test/jdk/java/io/File/SymLinks.java b/test/jdk/java/io/File/SymLinks.java index 967250c8430..40205a41557 100644 --- a/test/jdk/java/io/File/SymLinks.java +++ b/test/jdk/java/io/File/SymLinks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -281,22 +281,7 @@ static void go() throws IOException { assertTrue(link2dir.isDirectory()); assertTrue(link2link2dir.isDirectory()); - // on Windows we test with the DOS hidden attribute set - if (System.getProperty("os.name").startsWith("Windows")) { - DosFileAttributeView view = Files - .getFileAttributeView(file.toPath(), DosFileAttributeView.class); - view.setHidden(true); - try { - assertTrue(file.isHidden()); - assertTrue(link2file.isHidden()); - assertTrue(link2link2file.isHidden()); - } finally { - view.setHidden(false); - } - assertFalse(file.isHidden()); - assertFalse(link2file.isHidden()); - assertFalse(link2link2file.isHidden()); - } + testDOSHiddenAttributes(); header("length"); @@ -362,6 +347,26 @@ static void go() throws IOException { } } + static void testDOSHiddenAttributes() throws IOException { + // on Windows we test with the DOS hidden attribute set + if (System.getProperty("os.name").startsWith("Windows")) { + header("testDOSHiddenAttributes"); + DosFileAttributeView view = Files + .getFileAttributeView(file.toPath(), DosFileAttributeView.class); + view.setHidden(true); + try { + assertTrue(file.isHidden()); + assertTrue(link2file.isHidden()); + assertTrue(link2link2file.isHidden()); + } finally { + view.setHidden(false); + } + assertFalse(file.isHidden()); + assertFalse(link2file.isHidden()); + assertFalse(link2link2file.isHidden()); + } + } + public static void main(String[] args) throws IOException { if (supportsSymLinks(top)) { try { diff --git a/test/jdk/java/io/File/TimeZoneLastModified.java b/test/jdk/java/io/File/TimeZoneLastModified.java index 11c61a24408..bd423de619b 100644 --- a/test/jdk/java/io/File/TimeZoneLastModified.java +++ b/test/jdk/java/io/File/TimeZoneLastModified.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 +23,14 @@ /* * @test - * @bug 6212869 + * @bug 6212869 8347841 * @summary Determine if lastModified() works after TimeZone.setDefault() * @run main/othervm TimeZoneLastModified */ import java.io.File; -import java.util.Date; +import java.time.ZoneId; import java.util.TimeZone; -import java.text.SimpleDateFormat; public class TimeZoneLastModified { // Tue, 04 Jun 2002 13:56:50.002 GMT @@ -40,6 +39,9 @@ public class TimeZoneLastModified { public static void main(String[] args) throws Throwable { int failures = test(null); for (String timeZoneID : TimeZone.getAvailableIDs()) { + if (ZoneId.SHORT_IDS.containsKey(timeZoneID)) { + continue; + } failures += test(timeZoneID); } if (failures != 0) { diff --git a/test/jdk/java/io/File/WinDeviceName.java b/test/jdk/java/io/File/WinDeviceName.java index a0afe2cade9..0c357fa231f 100644 --- a/test/jdk/java/io/File/WinDeviceName.java +++ b/test/jdk/java/io/File/WinDeviceName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * 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 6176051 4858457 @summary Check whether reserved names are handled correctly on Windows + @requires (os.family == "windows") */ import java.io.File; @@ -38,10 +39,6 @@ public class WinDeviceName { }; public static void main(String[] args) { String osName = System.getProperty("os.name"); - if (!osName.startsWith("Windows")) { - return; - } - for (int i = 0; i < devnames.length; i++) { String names[] = { devnames[i], devnames[i] + ".TXT", devnames[i].toLowerCase(), diff --git a/test/jdk/java/io/File/WinMaxPath.java b/test/jdk/java/io/File/WinMaxPath.java index 21dba4cc12c..704b633395a 100644 --- a/test/jdk/java/io/File/WinMaxPath.java +++ b/test/jdk/java/io/File/WinMaxPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 +25,12 @@ @bug 6384833 @summary Check if appropriate exception FileNotFoundException gets thrown when the pathlengh exceeds the limit. + @requires (os.family == "windows") */ import java.io.*; public class WinMaxPath { public static void main(String[] args) throws Exception { - String osName = System.getProperty("os.name"); - if (!osName.startsWith("Windows")) { - return; - } try { char[] as = new char[65000]; java.util.Arrays.fill(as, 'a'); diff --git a/test/jdk/java/io/File/WinSpecialFiles.java b/test/jdk/java/io/File/WinSpecialFiles.java index a5bff301495..027aba769d9 100644 --- a/test/jdk/java/io/File/WinSpecialFiles.java +++ b/test/jdk/java/io/File/WinSpecialFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 +25,12 @@ @bug 6192331 6348207 8202076 @summary Check if File.exists()/length() works correctly on Windows special files hiberfil.sys and pagefile.sys + @requires (os.family == "windows") */ import java.io.File; public class WinSpecialFiles { public static void main(String[] args) throws Exception { - String osName = System.getProperty("os.name"); - if (!osName.startsWith("Windows")) { - return; - } File root = new File("C:\\"); File[] dir = root.listFiles(); for (int i = 0; i < dir.length; i++) { diff --git a/test/jdk/java/io/FileDescriptor/Sync.java b/test/jdk/java/io/FileDescriptor/Sync.java index 587d0bbe758..5864d5798df 100644 --- a/test/jdk/java/io/FileDescriptor/Sync.java +++ b/test/jdk/java/io/FileDescriptor/Sync.java @@ -39,7 +39,7 @@ public class Sync { static final String TEST_DIR = System.getProperty("test.dir", "."); - static final int TRIES = 10_000; + static final int TRIES = 1_000; public static void testWith(File file) throws Exception { try (FileOutputStream fos = new FileOutputStream(file)) { diff --git a/test/jdk/java/io/FileOutputStream/ManyFiles.java b/test/jdk/java/io/FileOutputStream/ManyFiles.java index 5584a8f42ca..3aad65de432 100644 --- a/test/jdk/java/io/FileOutputStream/ManyFiles.java +++ b/test/jdk/java/io/FileOutputStream/ManyFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,15 +37,6 @@ public class ManyFiles { static int NUM_FILES = 2050; public static void main(String args[]) throws Exception { - // Linux does not yet allow opening this many files; Solaris - // 8 requires an explicit allocation of more file descriptors - // to succeed. Since this test is written to check for a - // Windows capability it is much simpler to only run it - // on that platform. - String osName = System.getProperty("os.name"); - if (osName.startsWith("Linux")) - return; - for (int n = 0; n < NUM_FILES; n++) { File f = new File("file" + count++); files.add(f); diff --git a/test/jdk/java/io/pathNames/win32/SJIS.java b/test/jdk/java/io/pathNames/win32/SJIS.java index d1cad9dec9f..580f06330a6 100644 --- a/test/jdk/java/io/pathNames/win32/SJIS.java +++ b/test/jdk/java/io/pathNames/win32/SJIS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 @@ @summary Check that pathnames containing double-byte characters are not corrupted by win32 path processing @author Mark Reinhold + @library /test/lib */ -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import jtreg.SkippedException; public class SJIS { @@ -47,8 +53,11 @@ public static void main(String[] args) throws Exception { /* This test is only valid on win32 systems that use the SJIS encoding */ if (File.separatorChar != '\\') return; - String enc = System.getProperty("file.encoding"); - if ((enc == null) || !enc.equals("SJIS")) return; + String enc = System.getProperty("native.encoding"); + if ((enc == null) || !enc.equals("MS932")) { + throw new SkippedException( + "native.encoding(%s) is not MS932".formatted(enc)); + } File f = new File("\u30BD"); if (f.exists()) rm(f); diff --git a/test/jdk/java/lang/Math/FusedMultiplyAddTests.java b/test/jdk/java/lang/Math/FusedMultiplyAddTests.java index 61a3bfb0de1..014a4dedc0f 100644 --- a/test/jdk/java/lang/Math/FusedMultiplyAddTests.java +++ b/test/jdk/java/lang/Math/FusedMultiplyAddTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4851642 8253409 + * @bug 4851642 8253409 8362207 * @summary Tests for Math.fusedMac and StrictMath.fusedMac. * @build Tests * @build FusedMultiplyAddTests @@ -352,8 +352,9 @@ private static int testSimpleF() { {1.0f+Math.ulp(1.0f), 1.0f+Math.ulp(1.0f), -1.0f-2.0f*Math.ulp(1.0f), Math.ulp(1.0f)*Math.ulp(1.0f)}, - // Double-rounding if done in double precision - {0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f} + // Double-rounding if done in double precision and/or double fma + {0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f}, + {0x1.001p0f, 0x1.001p0f, 0x1p-100f, 0x1.002002p0f}, }; for (float[] testCase: testCases) diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index 9db67c180b5..a91735216ca 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -28,6 +28,7 @@ * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 * 4947220 7018606 7034570 4244896 5049299 8003488 8054494 8058464 * 8067796 8224905 8263729 8265173 8272600 8231297 8282219 8285517 + * 8352533 8368192 * @key intermittent * @summary Basic tests for Process and Environment Variable code * @modules java.base/java.lang:open @@ -89,6 +90,7 @@ public class Basic { /* Used for regex String matching for long error messages */ static final String PERMISSION_DENIED_ERROR_MSG = "(Permission denied|error=13)"; static final String NO_SUCH_FILE_ERROR_MSG = "(No such file|error=2)"; + static final String SPAWNHELPER_FAILURE_MSG = "(Possible reasons:)"; /** * Returns the number of milliseconds since time given by @@ -321,7 +323,9 @@ static void checkPermissionDenied(ProcessBuilder pb) { } catch (IOException e) { String m = e.getMessage(); if (EnglishUnix.is() && - ! matches(m, PERMISSION_DENIED_ERROR_MSG)) + !matches(m, PERMISSION_DENIED_ERROR_MSG)) + unexpected(e); + if (matches(m, SPAWNHELPER_FAILURE_MSG)) unexpected(e); } catch (Throwable t) { unexpected(t); } } @@ -431,7 +435,9 @@ public static void main(String args[]) throws Throwable { } catch (IOException e) { String m = e.getMessage(); if (EnglishUnix.is() && - ! matches(m, NO_SUCH_FILE_ERROR_MSG)) + !matches(m, NO_SUCH_FILE_ERROR_MSG)) + unexpected(e); + if (matches(m, SPAWNHELPER_FAILURE_MSG)) unexpected(e); } catch (Throwable t) { unexpected(t); } @@ -444,7 +450,9 @@ public static void main(String args[]) throws Throwable { } catch (IOException e) { String m = e.getMessage(); if (EnglishUnix.is() && - ! matches(m, NO_SUCH_FILE_ERROR_MSG)) + !matches(m, NO_SUCH_FILE_ERROR_MSG)) + unexpected(e); + if (matches(m, SPAWNHELPER_FAILURE_MSG)) unexpected(e); } catch (Throwable t) { unexpected(t); } @@ -772,30 +780,29 @@ private static boolean matches(String str, String regex) { return Pattern.compile(regex).matcher(str).find(); } - private static String matchAndExtract(String str, String regex) { - Matcher matcher = Pattern.compile(regex).matcher(str); - if (matcher.find()) { - return matcher.group(); - } else { - return ""; - } + // Return the string with the matching regex removed + private static String matchAndRemove(String str, String regex) { + return Pattern.compile(regex) + .matcher(str) + .replaceAll(""); } /* Only used for Mac OS X -- - * Mac OS X (may) add the variable __CF_USER_TEXT_ENCODING to an empty - * environment. The environment variable JAVA_MAIN_CLASS_ may also - * be set in Mac OS X. - * Remove them both from the list of env variables + * Mac OS X (may) add the variables: __CF_USER_TEXT_ENCODING, JAVA_MAIN_CLASS_, + * and TMPDIR. + * Remove them from the list of env variables */ private static String removeMacExpectedVars(String vars) { // Check for __CF_USER_TEXT_ENCODING - String cleanedVars = vars.replace("__CF_USER_TEXT_ENCODING=" - +cfUserTextEncoding+",",""); + String cleanedVars = matchAndRemove(vars, + "__CF_USER_TEXT_ENCODING=" + cfUserTextEncoding + ","); // Check for JAVA_MAIN_CLASS_ - String javaMainClassStr - = matchAndExtract(cleanedVars, - "JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,"); - return cleanedVars.replace(javaMainClassStr,""); + cleanedVars = matchAndRemove(cleanedVars, + "JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,"); + // Check and remove TMPDIR + cleanedVars = matchAndRemove(cleanedVars, + "TMPDIR=[^,]*,"); + return cleanedVars; } /* Only used for AIX -- @@ -2052,6 +2059,8 @@ public void doIt(Map environ) { if (EnglishUnix.is() && ! matches(m, NO_SUCH_FILE_ERROR_MSG)) unexpected(e); + if (matches(m, SPAWNHELPER_FAILURE_MSG)) + unexpected(e); } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- @@ -2069,6 +2078,8 @@ public void doIt(Map environ) { || (EnglishUnix.is() && ! matches(m, NO_SUCH_FILE_ERROR_MSG))) unexpected(e); + if (matches(m, SPAWNHELPER_FAILURE_MSG)) + unexpected(e); } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- @@ -2085,6 +2096,8 @@ public void doIt(Map environ) { || (EnglishUnix.is() && ! matches(m, NO_SUCH_FILE_ERROR_MSG))) unexpected(e); + if (matches(m, SPAWNHELPER_FAILURE_MSG)) + unexpected(e); } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- @@ -2143,8 +2156,9 @@ public void doIt(Map environ) { op.f(); fail(); } catch (IOException expected) { - check(expected.getMessage() - .matches("[Ss]tream [Cc]losed")); + String m = expected.getMessage(); + check(m.matches("[Ss]tream [Cc]losed")); + check(!matches(m, SPAWNHELPER_FAILURE_MSG)); } } } @@ -2196,10 +2210,14 @@ public void run() { } equal(-1, r); } catch (IOException ioe) { - if (!ioe.getMessage().equals("Stream closed")) { + String m = ioe.getMessage(); + if (!m.equals("Stream closed")) { // BufferedInputStream may throw IOE("Stream closed"). unexpected(ioe); } + if (matches(m, SPAWNHELPER_FAILURE_MSG)) { + unexpected(ioe); + } } catch (Throwable t) { unexpected(t); }}}; thread.start(); @@ -2253,6 +2271,9 @@ public void run() { ! (msg.matches(".*Bad file.*") || msg.matches(".*Stream closed.*"))) unexpected(e); + if (matches(msg, SPAWNHELPER_FAILURE_MSG)) { + unexpected(e); + } } catch (Throwable t) { unexpected(t); }}}; reader.setDaemon(true); @@ -2345,6 +2366,9 @@ public void run() { if (EnglishUnix.is() && ! matches(m, PERMISSION_DENIED_ERROR_MSG)) unexpected(e); + if (matches(m, SPAWNHELPER_FAILURE_MSG)) { + unexpected(e); + } } catch (Throwable t) { unexpected(t); } new File("emptyCommand").delete(); diff --git a/test/jdk/java/lang/ProcessBuilder/JspawnhelperProtocol.java b/test/jdk/java/lang/ProcessBuilder/JspawnhelperProtocol.java index d31905ccc63..0098bc531fd 100644 --- a/test/jdk/java/lang/ProcessBuilder/JspawnhelperProtocol.java +++ b/test/jdk/java/lang/ProcessBuilder/JspawnhelperProtocol.java @@ -49,14 +49,21 @@ public class JspawnhelperProtocol { private static final String[] CMD = { "pwd" }; private static final String ENV_KEY = "JTREG_JSPAWNHELPER_PROTOCOL_TEST"; + private static final String SPAWNHELPER_FAILURE_MSG = "Possible reasons:"; + private static void parentCode(String arg) throws IOException, InterruptedException { System.out.println("Recursively executing 'JspawnhelperProtocol " + arg + "'"); Process p = null; try { p = Runtime.getRuntime().exec(CMD); } catch (Exception e) { + // Check that exception contains rich message on failure. e.printStackTrace(System.out); - System.exit(ERROR); + if (e instanceof IOException && e.getMessage().contains(SPAWNHELPER_FAILURE_MSG)) { + System.exit(ERROR); + } else { + System.exit(ERROR + 3); + } } if (!p.waitFor(TIMEOUT, TimeUnit.SECONDS)) { System.out.println("Child process timed out"); diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties new file mode 100644 index 00000000000..8e24f2cb34d --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to ALL +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = ALL diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties index 21b19fa5ac8..b9076403cea 100644 --- a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties @@ -1,5 +1,5 @@ ############################################################ -# Enable logging java.lang.Runtime to the console +# java.lang.Runtime logging level to console to FINE ############################################################ handlers= java.util.logging.ConsoleHandler diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties new file mode 100644 index 00000000000..a31f4a35e93 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to FINER +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = FINER diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties index 212d9bd86d2..c09c0adf1ed 100644 --- a/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties @@ -1,5 +1,5 @@ ############################################################ -# Enable logging java.lang.Runtime to the console +# java.lang.Runtime logging level to console to INFO ############################################################ handlers= java.util.logging.ConsoleHandler diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties new file mode 100644 index 00000000000..6e284846e92 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to OFF +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = OFF diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties new file mode 100644 index 00000000000..cb6d32581fc --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to SEVERE +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = SEVERE diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties new file mode 100644 index 00000000000..5cd99c8d6c5 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to WARNING +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = WARNING diff --git a/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java b/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java index da40cdbd742..291c9895e19 100644 --- a/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java +++ b/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ public class RuntimeExitLogTest { private static final String TEST_JDK = System.getProperty("test.jdk"); private static final String TEST_SRC = System.getProperty("test.src"); - + private static final String NEW_LINE = System.lineSeparator(); private static Object HOLD_LOGGER; /** @@ -64,31 +64,80 @@ public static void main(String[] args) throws InterruptedException { System.exit(status); } + /** + * Generate a regular expression pattern that match the expected log output for a Runtime.exit() call. + * The pattern includes the method call stack trace and the exit status. + * @param status the exit status passed to the Runtime.exit() call + * @return the regex pattern as a string + */ + private static String generateStackTraceLogPattern(int status) { + return "(?s)^.+ java\\.lang\\.Shutdown logRuntimeExit\\n" + + ".*: Runtime\\.exit\\(\\) called with status: " + status + "\\n" + + "java\\.lang\\.Throwable: Runtime\\.exit\\(" + status + "\\)\\n" + + "\\s+at java\\.base/java\\.lang\\.Shutdown\\.logRuntimeExit\\(Shutdown\\.java:\\d+\\)\\n" + + "\\s+at(?: .+)"; + } + /** * Test various log level settings, and none. * @return a stream of arguments for parameterized test */ private static Stream logParamProvider() { return Stream.of( - // Logging enabled with level DEBUG + // Logging configuration using the java.util.logging.config.file property + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-ALL.properties").toString()), 1, + generateStackTraceLogPattern(1)), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-FINER.properties").toString()), 2, + generateStackTraceLogPattern(2)), Arguments.of(List.of("-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 1, - "Runtime.exit() called with status: 1"), - // Logging disabled due to level + Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 3, + generateStackTraceLogPattern(3)), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-INFO.properties").toString()), 4, + ""), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-WARNING.properties").toString()), 5, + ""), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-SEVERE.properties").toString()), 6, + ""), Arguments.of(List.of("-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-INFO.properties").toString()), 2, + Path.of(TEST_SRC, "ExitLogging-OFF.properties").toString()), 7, ""), - // Console logger + + // Logging configuration using the jdk.system.logger.level property + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=ALL"), 8, + generateStackTraceLogPattern(8)), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=TRACE"), 9, + generateStackTraceLogPattern(9)), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=DEBUG"), 10, + generateStackTraceLogPattern(10)), Arguments.of(List.of("--limit-modules", "java.base", - "-Djdk.system.logger.level=DEBUG"), 3, - "Runtime.exit() called with status: 3"), - // Console logger - Arguments.of(List.of(), 4, ""), + "-Djdk.system.logger.level=INFO"), 11, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=WARNING"), 12, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=ERROR"), 13, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=OFF"), 14, + ""), + // Throwing Handler Arguments.of(List.of("-DThrowingHandler", "-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 5, - "Runtime.exit(5) logging failed: Exception in publish") + Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 15, + "Runtime\\.exit\\(15\\) logging failed: Exception in publish"), + + // Default console logging configuration with no additional parameters + Arguments.of(List.of(), 16, "") ); } @@ -115,13 +164,14 @@ public void checkLogger(List logProps, int status, String expectMessage) try (BufferedReader reader = process.inputReader()) { List lines = reader.lines().toList(); boolean match = (expectMessage.isEmpty()) - ? lines.size() == 0 - : lines.stream().filter(s -> s.contains(expectMessage)).findFirst().isPresent(); + ? lines.isEmpty() + : String.join("\n", lines).matches(expectMessage); if (!match) { // Output lines for debug - System.err.println("Expected: \"" + expectMessage + "\""); + System.err.println("Expected pattern (line-break):"); + System.err.println(expectMessage.replaceAll("\\n", NEW_LINE)); System.err.println("---- Actual output begin"); - lines.forEach(l -> System.err.println(l)); + lines.forEach(System.err::println); System.err.println("---- Actual output end"); fail("Unexpected log contents"); } diff --git a/test/jdk/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java b/test/jdk/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java index 9f17478f35f..3d69f4199ce 100644 --- a/test/jdk/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java +++ b/test/jdk/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import java.security.ProtectionDomain; import java.util.concurrent.atomic.AtomicBoolean; import java.util.List; +import java.util.Locale; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -88,6 +89,8 @@ static enum TestCase { } public static void main(String[] args) throws Exception { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); if (args == null || args.length == 0) { args = new String[] { TestCase.SECURE_AND_WAIT.name() }; } @@ -373,6 +376,7 @@ public static void main(String[] args) throws Exception { LogStream.err.println("Not checking executor termination for " + test); } } finally { + Locale.setDefault(savedLocale); SimplePolicy.allowAll.set(Boolean.FALSE); } LogStream.err.println(test.name() + ": PASSED"); diff --git a/test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java b/test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java index 950f036458d..a65bf84c8e5 100644 --- a/test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java +++ b/test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java index 35986718a38..b081d261529 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java @@ -36,12 +36,13 @@ * @requires vm.debug == true * @modules java.base/java.lang:+open * @library /test/lib - * @run main/othervm/timeout=300 GetStackTraceALotWhenPinned 200000 + * @run main/othervm/timeout=300 GetStackTraceALotWhenPinned 50000 */ import java.time.Instant; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; +import jdk.test.lib.Platform; import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadPinner; @@ -53,7 +54,15 @@ public static void main(String[] args) throws Exception { VThreadRunner.ensureParallelism(2); } - int iterations = Integer.parseInt(args[0]); + int iterations; + int value = Integer.parseInt(args[0]); + if (Platform.isOSX() && Platform.isX64()) { + // reduced iterations on macosx-x64 + iterations = Math.max(value / 4, 1); + } else { + iterations = value; + } + var barrier = new Barrier(2); // Start a virtual thread that loops doing Thread.yield and parking while pinned. @@ -78,18 +87,23 @@ public static void main(String[] args) throws Exception { } }); - long lastTimestamp = System.currentTimeMillis(); - for (int i = 0; i < iterations; i++) { + long lastTime = System.nanoTime(); + for (int i = 1; i <= iterations; i++) { // wait for virtual thread to arrive barrier.await(); thread.getStackTrace(); LockSupport.unpark(thread); - long currentTime = System.currentTimeMillis(); - if ((currentTime - lastTimestamp) > 500) { - System.out.format("%s %d remaining ...%n", Instant.now(), (iterations - i)); - lastTimestamp = currentTime; + long currentTime = System.nanoTime(); + if (i == iterations || ((currentTime - lastTime) > 1_000_000_000L)) { + System.out.format("%s => %d of %d%n", Instant.now(), i, iterations); + lastTime = currentTime; + } + + if (Thread.currentThread().isInterrupted()) { + // fail quickly if interrupted by jtreg + throw new RuntimeException("interrupted"); } } } diff --git a/test/jdk/java/lang/Thread/virtual/stress/ParkALot.java b/test/jdk/java/lang/Thread/virtual/stress/ParkALot.java index ccba3fe1b4d..882e0b881bc 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/ParkALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/ParkALot.java @@ -25,29 +25,35 @@ * @test * @summary Stress test parking and unparking * @requires vm.debug != true - * @run main/othervm ParkALot 500000 + * @library /test/lib + * @run main/othervm/timeout=300 ParkALot 300000 */ /* * @test * @requires vm.debug == true - * @run main/othervm ParkALot 100000 + * @library /test/lib + * @run main/othervm/timeout=300 ParkALot 100000 */ import java.time.Instant; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; +import jdk.test.lib.Platform; public class ParkALot { - private static final int ITERATIONS = 1_000_000; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { int iterations; - if (args.length > 0) { - iterations = Integer.parseInt(args[0]); + int value = Integer.parseInt(args[0]); + if (Platform.isOSX() && Platform.isX64()) { + // reduced iterations on macosx-x64 + iterations = Math.max(value / 4, 1); } else { - iterations = ITERATIONS; + iterations = value; } int maxThreads = Math.clamp(Runtime.getRuntime().availableProcessors() / 2, 1, 4); @@ -55,8 +61,18 @@ public static void main(String[] args) { System.out.format("%s %d thread(s) ...%n", Instant.now(), nthreads); ThreadFactory factory = Thread.ofPlatform().factory(); try (var executor = Executors.newThreadPerTaskExecutor(factory)) { + var totalIterations = new AtomicInteger(); for (int i = 0; i < nthreads; i++) { - executor.submit(() -> parkALot(iterations)); + executor.submit(() -> parkALot(iterations, totalIterations::incrementAndGet)); + } + + // shutdown, await for all threads to finish with progress output + executor.shutdown(); + boolean terminated = false; + while (!terminated) { + terminated = executor.awaitTermination(1, TimeUnit.SECONDS); + System.out.format("%s => %d of %d%n", + Instant.now(), totalIterations.get(), iterations * nthreads); } } System.out.format("%s %d thread(s) done%n", Instant.now(), nthreads); @@ -66,8 +82,10 @@ public static void main(String[] args) { /** * Creates a virtual thread that alternates between untimed and timed parking. * A platform thread spins unparking the virtual thread. + * @param iterations number of iterations + * @param afterIteration the task to run after each iteration */ - private static void parkALot(int iterations) { + private static void parkALot(int iterations, Runnable afterIteration) { Thread vthread = Thread.ofVirtual().start(() -> { int i = 0; boolean timed = false; @@ -80,6 +98,7 @@ private static void parkALot(int iterations) { timed = true; } i++; + afterIteration.run(); } }); diff --git a/test/jdk/java/lang/Thread/virtual/stress/SleepALot.java b/test/jdk/java/lang/Thread/virtual/stress/SleepALot.java index 12771ab499a..a2b8d093734 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/SleepALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/SleepALot.java @@ -25,7 +25,7 @@ * @test * @summary Stress test Thread.sleep * @requires vm.debug != true & vm.continuations - * @run main/othervm SleepALot 500000 + * @run main SleepALot 500000 */ /* diff --git a/test/jdk/java/net/CookieStoreTest.java b/test/jdk/java/net/CookieStoreTest.java new file mode 100644 index 00000000000..50a5ab3fac1 --- /dev/null +++ b/test/jdk/java/net/CookieStoreTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.net.CookieManager; +import java.net.CookieStore; +import java.net.HttpCookie; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/* + * @test + * @bug 8365086 + * @summary verify that the implementation of java.net.CookieStore works + * as expected + * @run junit CookieStoreTest + */ +class CookieStoreTest { + + // neither the scheme, host nor the port matters in this test + private static final URI COOKIE_TEST_URI = URI.create("https://127.0.0.1:12345"); + + static List cookieStores() { + final List params = new ArrayList<>(); + // empty CookieStore + params.add(Arguments.of(new CookieManager().getCookieStore(), true)); + + final CookieStore cookieStore = new CookieManager().getCookieStore(); + cookieStore.add(COOKIE_TEST_URI, new HttpCookie("foo", "bar")); + // non-empty CookieStore + params.add(Arguments.of(cookieStore, false)); + + return params; + } + + /* + * Verify that the List returned by CookieStore.getURIs() is immutable. + */ + @ParameterizedTest + @MethodSource("cookieStores") + void testImmutableGetURIs(final CookieStore cookieStore, final boolean expectEmpty) { + final List uris = cookieStore.getURIs(); + assertNotNull(uris, "CookieStore.getURIs() returned null"); + assertEquals(expectEmpty, uris.isEmpty(), "CookieStore.getURIs() returned: " + uris); + assertImmutableList(uris, COOKIE_TEST_URI); + } + + /* + * Verify that the List returned by CookieStore.getCookies() is immutable. + */ + @ParameterizedTest + @MethodSource("cookieStores") + void testImmutableGetCookies(final CookieStore cookieStore, final boolean expectEmpty) { + final List cookies = cookieStore.getCookies(); + assertNotNull(cookies, "CookieStore.getCookies() returned null"); + assertEquals(expectEmpty, cookies.isEmpty(), "CookieStore.getCookies() returned: " + cookies); + assertImmutableList(cookies, new HttpCookie("hello", "world")); + } + + /* + * Verify that the List returned by CookieStore.get(URI) is immutable. + */ + @ParameterizedTest + @MethodSource("cookieStores") + void testImmutableGetCookiesForURI(final CookieStore cookieStore, final boolean expectEmpty) { + final List cookies = cookieStore.get(COOKIE_TEST_URI); + assertNotNull(cookies, "CookieStore.get(URI) returned null"); + assertEquals(expectEmpty, cookies.isEmpty(), "CookieStore.get(URI) returned: " + cookies); + assertImmutableList(cookies, new HttpCookie("hello", "world")); + } + + /* + * Verifies that the attempt to modify the contents of the list will fail + * due to the list being immutable. + */ + private static void assertImmutableList(final List list, T elementToAddOrRemove) { + // the list is expected to be immutable, so each of these operations must fail + assertThrows(UnsupportedOperationException.class, () -> list.add(elementToAddOrRemove)); + assertThrows(UnsupportedOperationException.class, () -> list.remove(elementToAddOrRemove)); + assertThrows(UnsupportedOperationException.class, list::clear); + // even try the replace operation when the list isn't empty + if (!list.isEmpty()) { + assertThrows(UnsupportedOperationException.class, () -> list.set(0, elementToAddOrRemove)); + } + } +} diff --git a/test/jdk/java/net/InetAddress/ptr/Lookup.java b/test/jdk/java/net/InetAddress/ptr/Lookup.java index 1248916023e..39e5f720cef 100644 --- a/test/jdk/java/net/InetAddress/ptr/Lookup.java +++ b/test/jdk/java/net/InetAddress/ptr/Lookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import jtreg.SkippedException; public class Lookup { private static final String HOST = "icann.org"; @@ -91,8 +92,7 @@ public static void main(String args[]) throws IOException { String tmp = lookupWithIPv4Prefer(); System.out.println("IPv4 lookup results: [" + tmp + "]"); if (SKIP.equals(tmp)) { - System.out.println(HOST + " can't be resolved - test skipped."); - return; + throw new SkippedException(HOST + " can't be resolved - test skipped."); } String[] strs = tmp.split(":"); @@ -104,8 +104,7 @@ public static void main(String args[]) throws IOException { tmp = reverseWithIPv4Prefer(addr); System.out.println("IPv4 reverse lookup results: [" + tmp + "]"); if (SKIP.equals(tmp)) { - System.out.println(addr + " can't be resolved with preferIPv4 - test skipped."); - return; + throw new SkippedException(addr + " can't be resolved with preferIPv4 - test skipped."); } strs = tmp.split(":"); diff --git a/test/jdk/java/net/NetworkInterface/IPv4Only.java b/test/jdk/java/net/NetworkInterface/IPv4Only.java index efa59aa7691..3d12b3282bd 100644 --- a/test/jdk/java/net/NetworkInterface/IPv4Only.java +++ b/test/jdk/java/net/NetworkInterface/IPv4Only.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * 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,12 +29,18 @@ */ -import java.net.*; -import java.util.*; + import jdk.test.lib.net.IPSupport; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Enumeration; + public class IPv4Only { public static void main(String[] args) throws Exception { + IPSupport.printPlatformSupport(System.out); if (IPSupport.hasIPv4()) { System.out.println("Testing IPv4"); Enumeration nifs = NetworkInterface.getNetworkInterfaces(); @@ -43,7 +49,7 @@ public static void main(String[] args) throws Exception { Enumeration addrs = nif.getInetAddresses(); while (addrs.hasMoreElements()) { InetAddress hostAddr = addrs.nextElement(); - if ( hostAddr instanceof Inet6Address ){ + if (hostAddr instanceof Inet6Address){ throw new RuntimeException( "NetworkInterfaceV6List failed - found v6 address " + hostAddr.getHostAddress() ); } } diff --git a/test/jdk/java/net/Socket/DeadlockTest.java b/test/jdk/java/net/Socket/DeadlockTest.java index 40b001171f1..3e2d38dc142 100644 --- a/test/jdk/java/net/Socket/DeadlockTest.java +++ b/test/jdk/java/net/Socket/DeadlockTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,19 @@ * @run main/othervm -Djava.net.preferIPv4Stack=true DeadlockTest */ -import java.net.*; -import java.io.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; + import jdk.test.lib.net.IPSupport; public class DeadlockTest { - public static void main(String [] argv) throws Exception { + public static void main(String[] argv) throws Exception { IPSupport.throwSkippedExceptionIfNonOperational(); ServerSocket ss = new ServerSocket(0, 0, InetAddress.getLoopbackAddress()); @@ -52,16 +59,9 @@ public static void main(String [] argv) throws Exception { Thread c1 = new Thread(ct); c1.start(); - // Wait for the client thread to finish - c1.join(20000); - - // If timeout, we assume there is a deadlock - if (c1.isAlive() == true) { - // Close the socket to force the server thread - // terminate too - s1.stop(); - throw new Exception("Takes too long. Dead lock"); - } + // Wait for the client thread to finish. + // If it doesn't finish then it's a sign of a deadlock + c1.join(); } finally { ss.close(); clientSocket.close(); @@ -73,7 +73,7 @@ class ServerThread implements Runnable { private static boolean dbg = false; - ObjectInputStream in; + ObjectInputStream in; ObjectOutputStream out; ServerSocket server; diff --git a/test/jdk/java/net/URI/Test.java b/test/jdk/java/net/URI/Test.java index 00d473f87be..95dd49ea34f 100644 --- a/test/jdk/java/net/URI/Test.java +++ b/test/jdk/java/net/URI/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * 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 @@ /* @test * @summary Unit test for java.net.URI * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800 - * 7171415 6339649 6933879 8037396 8272072 8051627 8297687 + * 7171415 6339649 6933879 8037396 8272072 8051627 8297687 8353013 * @author Mark Reinhold */ @@ -1620,6 +1620,7 @@ static void bugs() { b8051627(); b8272072(); b8297687(); + b8353013(); } private static void b8297687() { @@ -1786,6 +1787,39 @@ private static void b8272072() { } } + // 8353013 - Increase test coverage for cases where the authority component of a hierarchical + // URI has a host component that starts with a number. + private static void b8353013() { + testCreate("https://0.0.0.1").s("https").h("0.0.0.1").p("").z(); + testCreate("https://00.0.0.2").s("https").h("00.0.0.2").p("").z(); + testCreate("https://000.0.0.3").s("https").h("000.0.0.3").p("").z(); + testCreate("https://0000.0.0.4").s("https").h("0000.0.0.4").p("").z(); + + testCreate("https://00000.0.0.5").s("https").h("00000.0.0.5").p("").z(); + testCreate("https://00001.0.0.6").s("https").h("00001.0.0.6").p("").z(); + + testCreate("https://01.0.0.1").s("https").h("01.0.0.1").p("").z(); + + testCreate("https://111111.2.3.com").s("https").h("111111.2.3.com").p("").z(); + + testCreate("https://1.example.com").s("https").h("1.example.com").p("").z(); + testCreate("https://12.example.com").s("https").h("12.example.com").p("").z(); + testCreate("https://123.example.com").s("https").h("123.example.com").p("").z(); + testCreate("https://1234.example.com").s("https").h("1234.example.com").p("").z(); + testCreate("https://12345.example.com").s("https").h("12345.example.com").p("").z(); + + testCreate("https://98765432101.example.com").s("https").h("98765432101.example.com").p("").z(); + testCreate("https://98765432101.www.example.com/").s("https").h("98765432101.www.example.com").p("/").z(); + testCreate("https://98765432101.www.example.com").s("https").h("98765432101.www.example.com").p("").z(); + + testCreate("https://9223372036854775808.example.com").s("https").h("9223372036854775808.example.com").p("").z(); + testCreate("https://9223372036854775808.www.example.com").s("https").h("9223372036854775808.www.example.com").p("").z(); + testCreate("https://9223372036854775808.xyz.abc.com").s("https").h("9223372036854775808.xyz.abc.com").p("").z(); + testCreate("https://9223372036854775808.xyz.abc.pqr.com").s("https").h("9223372036854775808.xyz.abc.pqr.com").p("").z(); + + testCreate("https://256.example.com").s("https").h("256.example.com").p("").z(); + } + public static void main(String[] args) throws Exception { switch (args.length) { diff --git a/test/jdk/java/net/httpclient/HttpsTunnelAuthTest.java b/test/jdk/java/net/httpclient/HttpsTunnelAuthTest.java index 83961453f05..c6b2c323693 100644 --- a/test/jdk/java/net/httpclient/HttpsTunnelAuthTest.java +++ b/test/jdk/java/net/httpclient/HttpsTunnelAuthTest.java @@ -37,12 +37,11 @@ import java.util.stream.Stream; import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; -import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.test.lib.net.SimpleSSLContext; import static java.lang.System.out; -/** +/* * @test * @bug 8262027 * @summary Verify that it's possible to handle proxy authentication manually @@ -62,7 +61,7 @@ //-Djdk.internal.httpclient.debug=true -Dtest.debug=true public class HttpsTunnelAuthTest implements HttpServerAdapters, AutoCloseable { - static final String data[] = { + static final String[] data = { "Lorem ipsum", "dolor sit amet", "consectetur adipiscing elit, sed do eiusmod tempor", @@ -150,7 +149,7 @@ void setUp() throws IOException { @Override public void close() throws Exception { - if (proxy != null) close(proxy::stop); + if (proxy != null) close(proxy); if (http1Server != null) close(http1Server::stop); if (https1Server != null) close(https1Server::stop); if (https2Server != null) close(https2Server::stop); @@ -160,7 +159,8 @@ private void close(AutoCloseable closeable) { try { closeable.close(); } catch (Exception x) { - // OK. + // OK to ignore and just log + System.err.println("ignoring failure during close() of " + closeable + " due to: " + x); } } diff --git a/test/jdk/java/net/httpclient/ManyRequests.java b/test/jdk/java/net/httpclient/ManyRequests.java index 89f26d3a761..61b6a5a4d3d 100644 --- a/test/jdk/java/net/httpclient/ManyRequests.java +++ b/test/jdk/java/net/httpclient/ManyRequests.java @@ -24,6 +24,7 @@ /* * @test * @bug 8087112 8180044 8256459 + * @key intermittent * @modules java.net.http * java.logging * jdk.httpserver diff --git a/test/jdk/java/net/httpclient/ProxyServer.java b/test/jdk/java/net/httpclient/ProxyServer.java index e07badd2bb7..8e3e2bed5b9 100644 --- a/test/jdk/java/net/httpclient/ProxyServer.java +++ b/test/jdk/java/net/httpclient/ProxyServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,7 @@ * Two threads are created per client connection. So, it's not * intended for large numbers of parallel connections. */ -public class ProxyServer extends Thread implements Closeable { +public final class ProxyServer implements Closeable { // could use the test library here - Platform.isWindows(), // but it would force all tests that use ProxyServer to @@ -99,9 +99,7 @@ public ProxyServer(Integer port, this(port, debug, null); } - public ProxyServer(Integer port, - Boolean debug, - Credentials credentials) + private ProxyServer(Integer port, Boolean debug, Credentials credentials) throws IOException { this.debug = debug; @@ -110,15 +108,8 @@ public ProxyServer(Integer port, listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), port)); this.port = ((InetSocketAddress)listener.getLocalAddress()).getPort(); this.credentials = credentials; - setName("ProxyListener"); - setDaemon(true); - connections = new CopyOnWriteArrayList(); - start(); - } - - public ProxyServer(String s) { - credentials = null; connections = new CopyOnWriteArrayList(); + Thread.ofPlatform().name("ProxyListener").daemon().start(this::run); } /** @@ -150,7 +141,7 @@ public void close() throws IOException { volatile boolean done; - public void run() { + private void run() { if (System.getSecurityManager() == null) { execute(); } else { @@ -195,6 +186,9 @@ class Connection { volatile InputStream clientIn, serverIn; volatile OutputStream clientOut, serverOut; + boolean proxyInClosed; // only accessed from synchronized block + boolean proxyOutClosed; // only accessed from synchronized block + final static int CR = 13; final static int LF = 10; @@ -594,9 +588,7 @@ synchronized void proxyCommon(boolean log) throws IOException { if (log) System.out.printf("Proxy Forwarding [request body]: total %d%n", body); } - closing = true; - serverSocket.close(); - clientSocket.close(); + closeClientIn(); } catch (IOException e) { if (!closing && debug) { System.out.println("Proxy: " + e); @@ -615,9 +607,7 @@ synchronized void proxyCommon(boolean log) throws IOException { if (log) System.out.printf("Proxy Forwarding [response]: %s%n", new String(bb, 0, n, UTF_8)); if (log) System.out.printf("Proxy Forwarding [response]: total %d%n", resp); } - closing = true; - serverSocket.close(); - clientSocket.close(); + closeClientOut(); } catch (IOException e) { if (!closing && debug) { System.out.println("Proxy: " + e); @@ -641,6 +631,28 @@ void doTunnel(String dest) throws IOException { proxyCommon(false); } + synchronized void closeClientIn() throws IOException { + closing = true; + proxyInClosed = true; + clientSocket.shutdownInput(); + serverSocket.shutdownOutput(); + if (proxyOutClosed) { + serverSocket.close(); + clientSocket.close(); + } + } + + synchronized void closeClientOut() throws IOException { + closing = true; + proxyOutClosed = true; + serverSocket.shutdownInput(); + clientSocket.shutdownOutput(); + if (proxyInClosed) { + serverSocket.close(); + clientSocket.close(); + } + } + @Override public String toString() { return "Proxy connection " + id + ", client sock:" + clientSocket; @@ -651,10 +663,11 @@ public static void main(String[] args) throws Exception { int port = Integer.parseInt(args[0]); boolean debug = args.length > 1 && args[1].equals("-debug"); System.out.println("Debugging : " + debug); - ProxyServer ps = new ProxyServer(port, debug); - System.out.println("Proxy server listening on port " + ps.getPort()); - while (true) { - Thread.sleep(5000); + try (ProxyServer ps = new ProxyServer(port, debug)) { + System.out.println("Proxy server listening on port " + ps.getPort()); + while (true) { + Thread.sleep(5000); + } } } } diff --git a/test/jdk/java/net/vthread/HttpALot.java b/test/jdk/java/net/vthread/HttpALot.java index c016824a92a..6418e103a35 100644 --- a/test/jdk/java/net/vthread/HttpALot.java +++ b/test/jdk/java/net/vthread/HttpALot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * 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,7 +21,7 @@ * questions. */ -/** +/* * @test * @bug 8284161 * @summary Stress test the HTTP protocol handler and HTTP server @@ -44,6 +44,7 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; @@ -52,6 +53,8 @@ public class HttpALot { + private static final String HELLO = "Hello"; + public static void main(String[] args) throws Exception { int requests = 25_000; if (args.length > 0) { @@ -65,12 +68,20 @@ public static void main(String[] args) throws Exception { InetAddress lb = InetAddress.getLoopbackAddress(); HttpServer server = HttpServer.create(new InetSocketAddress(lb, 0), 1024); ThreadFactory factory = Thread.ofVirtual().factory(); - server.setExecutor(Executors.newThreadPerTaskExecutor(factory)); + final ExecutorService serverExecutor = Executors.newThreadPerTaskExecutor(factory); + server.setExecutor(serverExecutor); server.createContext("/hello", e -> { - byte[] response = "Hello".getBytes("UTF-8"); - e.sendResponseHeaders(200, response.length); - try (OutputStream out = e.getResponseBody()) { - out.write(response); + try { + byte[] response = HELLO.getBytes("UTF-8"); + e.sendResponseHeaders(200, response.length); + try (OutputStream out = e.getResponseBody()) { + out.write(response); + } + } catch (Throwable t) { + System.err.println("failed to handle request " + e.getRequestURI() + + " due to: " + t); + t.printStackTrace(); + throw t; // let it propagate } requestsHandled.incrementAndGet(); }); @@ -85,15 +96,21 @@ public static void main(String[] args) throws Exception { // go server.start(); - try { - factory = Thread.ofVirtual().name("fetcher-", 0).factory(); - try (var executor = Executors.newThreadPerTaskExecutor(factory)) { - for (int i = 1; i <= requests; i++) { - executor.submit(() -> fetch(url)).get(); + try (serverExecutor) { + try { + factory = Thread.ofVirtual().name("fetcher-", 0).factory(); + try (var executor = Executors.newThreadPerTaskExecutor(factory)) { + for (int i = 1; i <= requests; i++) { + final String actual = executor.submit(() -> fetch(url)).get(); + if (!HELLO.equals(actual)) { + throw new RuntimeException("unexpected response: \"" + actual + + "\" for request " + i); + } + } } + } finally { + server.stop(1); } - } finally { - server.stop(1); } if (requestsHandled.get() < requests) { diff --git a/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java b/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java index d6d2f083eca..cc726d19c0d 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java +++ b/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,42 +36,23 @@ import java.util.concurrent.CountDownLatch; public class StressNativeSignal { - private UDPThread udpThread; - private ServerSocketThread serverSocketThread; + private final UDPThread udpThread; + private final ServerSocketThread serverSocketThread; - StressNativeSignal() { + StressNativeSignal() throws IOException { serverSocketThread = initServerSocketThread(); - if (serverSocketThread != null) { - serverSocketThread.start(); - } + serverSocketThread.start(); udpThread = initUDPThread(); - if (udpThread != null) { - udpThread.start(); - } + udpThread.start(); } - private UDPThread initUDPThread() { - UDPThread aUDPThread = null; - try { - aUDPThread = new UDPThread(); - } catch (Exception z) { - System.err.println("failed to create and start a UDPThread"); - z.printStackTrace(); - } - return aUDPThread; + private UDPThread initUDPThread() throws IOException { + return new UDPThread(); } - private ServerSocketThread initServerSocketThread() { - ServerSocketThread aServerSocketThread = null; - try { - aServerSocketThread = new ServerSocketThread(); - - } catch (Exception z) { - System.err.println("failed to create and start a ServerSocketThread"); - z.printStackTrace(); - } - return aServerSocketThread; + private ServerSocketThread initServerSocketThread() throws IOException { + return new ServerSocketThread(); } public static void main(String[] args) throws Throwable { @@ -80,46 +61,39 @@ public static void main(String[] args) throws Throwable { test.shutdown(); } - public void shutdown() { - if ((udpThread != null) && udpThread.isAlive()) { + public void shutdown() throws InterruptedException, IOException { + if (udpThread != null && udpThread.isAlive()) { udpThread.terminate(); - try { - udpThread.join(); - } catch (Exception z) { - z.printStackTrace(System.err); - } + udpThread.join(); + } else { System.out.println("UDPThread test scenario was not run"); } - if ((serverSocketThread != null) && (serverSocketThread.isAlive())) { + if (serverSocketThread != null && serverSocketThread.isAlive()) { serverSocketThread.terminate(); - try { - serverSocketThread.join(); - } catch (Exception z) { - z.printStackTrace(System.err); - } + serverSocketThread.join(); } else { System.out.println("ServerSocketThread test scenario was not run"); } } - public void waitForTestThreadsToStart() { - if ((udpThread != null) && udpThread.isAlive()) { + public void waitForTestThreadsToStart() throws InterruptedException { + if (udpThread != null && udpThread.isAlive()) { udpThread.waitTestThreadStart(); } - if ((serverSocketThread != null) && (serverSocketThread.isAlive())) { + if (serverSocketThread != null && serverSocketThread.isAlive()) { serverSocketThread.waitTestThreadStart(); } } public class ServerSocketThread extends Thread { private volatile boolean shouldTerminate; - private ServerSocket socket; + private final ServerSocket socket; private final CountDownLatch threadStarted = new CountDownLatch(1); - public ServerSocketThread () throws Exception { - socket = new ServerSocket(1122); + public ServerSocketThread() throws IOException { + socket = new ServerSocket(0); } public void run() { @@ -129,7 +103,7 @@ public void run() { Socket client = socket.accept(); client.close(); throw new RuntimeException("Unexpected return from accept call"); - } catch (Exception z) { + } catch (IOException z) { System.err.println("ServerSocketThread: caught exception " + z.getClass().getName()); if (!shouldTerminate) { z.printStackTrace(System.err); @@ -141,7 +115,7 @@ public void terminate() { shouldTerminate = true; try { socket.close(); - } catch (Exception z) { + } catch (IOException z) { z.printStackTrace(System.err); // ignore } @@ -150,7 +124,7 @@ public void terminate() { public void waitTestThreadStart() { try { threadStarted.await(); - } catch (Exception z) { + } catch (InterruptedException z) { z.printStackTrace(System.err); // ignore } @@ -158,15 +132,14 @@ public void waitTestThreadStart() { } public class UDPThread extends Thread { - private DatagramChannel channel; + private final DatagramChannel channel; private volatile boolean shouldTerminate; private final CountDownLatch threadStarted = new CountDownLatch(1); - public UDPThread () throws Exception { - + public UDPThread() throws IOException { channel = DatagramChannel.open(); channel.setOption(StandardSocketOptions.SO_RCVBUF, 6553600); - channel.bind(new InetSocketAddress(19870)); + channel.bind(new InetSocketAddress(0)); } @Override @@ -191,7 +164,7 @@ public void terminate() { shouldTerminate = true; try { channel.close(); - } catch (Exception z) { + } catch (IOException z) { System.err.println("UDPThread: caught exception " + z.getClass().getName()); z.printStackTrace(System.err); // ignore @@ -201,7 +174,7 @@ public void terminate() { public void waitTestThreadStart() { try { threadStarted.await(); - } catch (Exception z) { + } catch (InterruptedException z) { z.printStackTrace(System.err); // ignore } diff --git a/test/jdk/java/nio/channels/FileChannel/directio/DirectIOTest.java b/test/jdk/java/nio/channels/FileChannel/directio/DirectIOTest.java index 34f2bacc7dd..b9dd309d0f7 100644 --- a/test/jdk/java/nio/channels/FileChannel/directio/DirectIOTest.java +++ b/test/jdk/java/nio/channels/FileChannel/directio/DirectIOTest.java @@ -27,11 +27,13 @@ * @summary Test for ExtendedOpenOption.DIRECT flag * @requires (os.family == "linux" | os.family == "aix") * @library /test/lib + * @modules java.base/sun.nio.ch:+open java.base/java.io:+open * @build jdk.test.lib.Platform * @run main/native DirectIOTest */ import java.io.*; +import java.lang.reflect.Field; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.*; @@ -47,10 +49,25 @@ public class DirectIOTest { private static final int BASE_SIZE = 4096; + private static final int TRIES = 3; + + public static int getFD(FileChannel channel) throws Exception { + Field fFdFd = channel.getClass().getDeclaredField("fd"); + fFdFd.setAccessible(true); + FileDescriptor fd = (FileDescriptor) fFdFd.get(channel); + + Field fFd = FileDescriptor.class.getDeclaredField("fd"); + fFd.setAccessible(true); + return fFd.getInt(fd); + } + + private static void testWrite(Path p, long blockSize) throws Exception { + try (FileChannel fc = FileChannel.open(p, + StandardOpenOption.READ, + StandardOpenOption.WRITE, + ExtendedOpenOption.DIRECT)) { + int fd = getFD(fc); - private static int testWrite(Path p, long blockSize) throws Exception { - try (FileChannel fc = FileChannel.open(p, StandardOpenOption.WRITE, - ExtendedOpenOption.DIRECT)) { int bs = (int)blockSize; int size = Math.max(BASE_SIZE, bs); int alignment = bs; @@ -60,22 +77,55 @@ private static int testWrite(Path p, long blockSize) throws Exception { for (int j = 0; j < size; j++) { src.put((byte)0); } - src.flip(); - fc.write(src); - return size; + + // If there is AV or other FS tracing software, it may cache the file + // contents on first access, even though we have asked for DIRECT here. + // Do several attempts to make test more resilient. + + for (int t = 0; t < TRIES; t++) { + flushFileCache(size, fd); + src.flip(); + fc.position(0); + fc.write(src); + if (!isFileInCache(size, fd)) { + return; + } + } + + throw new RuntimeException("DirectIO is not working properly with " + + "write. File still exists in cache!"); } } - private static int testRead(Path p, long blockSize) throws Exception { - try (FileChannel fc = FileChannel.open(p, ExtendedOpenOption.DIRECT)) { + private static void testRead(Path p, long blockSize) throws Exception { + try (FileChannel fc = FileChannel.open(p, + StandardOpenOption.READ, + ExtendedOpenOption.DIRECT)) { + int fd = getFD(fc); + int bs = (int)blockSize; int size = Math.max(BASE_SIZE, bs); int alignment = bs; ByteBuffer dest = ByteBuffer.allocateDirect(size + alignment - 1) .alignedSlice(alignment); assert dest.capacity() != 0; - fc.read(dest); - return size; + + // If there is AV or other FS tracing software, it may cache the file + // contents on first access, even though we have asked for DIRECT here. + // Do several attempts to make test more resilient. + + for (int t = 0; t < TRIES; t++) { + flushFileCache(size, fd); + dest.clear(); + fc.position(0); + fc.read(dest); + if (!isFileInCache(size, fd)) { + return; + } + } + + throw new RuntimeException("DirectIO is not working properly with " + + "read. File still exists in cache!"); } } @@ -84,12 +134,8 @@ public static Path createTempFile() throws IOException { Paths.get(System.getProperty("test.dir", ".")), "test", null); } - private static boolean isFileInCache(int size, Path p) { - String path = p.toString(); - return isFileInCache0(size, path); - } - - private static native boolean isFileInCache0(int size, String path); + private static native boolean flushFileCache(int size, int fd); + private static native boolean isFileInCache(int size, int fd); public static void main(String[] args) throws Exception { Path p = createTempFile(); @@ -98,16 +144,8 @@ public static void main(String[] args) throws Exception { System.loadLibrary("DirectIO"); try { - int size = testWrite(p, blockSize); - if (isFileInCache(size, p)) { - throw new RuntimeException("DirectIO is not working properly with " - + "write. File still exists in cache!"); - } - size = testRead(p, blockSize); - if (isFileInCache(size, p)) { - throw new RuntimeException("DirectIO is not working properly with " - + "read. File still exists in cache!"); - } + testWrite(p, blockSize); + testRead(p, blockSize); } finally { Files.delete(p); } diff --git a/test/jdk/java/nio/channels/FileChannel/directio/libDirectIO.c b/test/jdk/java/nio/channels/FileChannel/directio/libDirectIO.c index 4897500bf2d..5eea51da4c7 100644 --- a/test/jdk/java/nio/channels/FileChannel/directio/libDirectIO.c +++ b/test/jdk/java/nio/channels/FileChannel/directio/libDirectIO.c @@ -45,13 +45,27 @@ static void ThrowException(JNIEnv *env, const char *name, const char *msg) { /* * Class: DirectIO - * Method: isFileInCache0 - * Signature: (ILjava/lang/String;)Z + * Method: flushFileCache + * Signature: (II;)V */ -JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env, +JNIEXPORT void Java_DirectIOTest_flushFileCache(JNIEnv *env, jclass cls, jint file_size, - jstring file_path) { + jint fd) { +#ifdef __linux__ + posix_fadvise(fd, 0, file_size, POSIX_FADV_DONTNEED); +#endif +} + +/* + * Class: DirectIO + * Method: isFileInCache + * Signature: (II;)Z + */ +JNIEXPORT jboolean Java_DirectIOTest_isFileInCache(JNIEnv *env, + jclass cls, + jint file_size, + jint fd) { void *f_mmap; #ifdef __linux__ unsigned char *f_seg; @@ -69,17 +83,10 @@ JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env, size_t index = (file_size + page_size - 1) /page_size; jboolean result = JNI_FALSE; - const char* path = (*env)->GetStringUTFChars(env, file_path, JNI_FALSE); - - int fd = open(path, O_RDWR); - - (*env)->ReleaseStringUTFChars(env, file_path, path); - f_mmap = mmap(0, file_size, PROT_NONE, MAP_SHARED, fd, 0); if (f_mmap == MAP_FAILED) { - close(fd); ThrowException(env, "java/io/IOException", - "test of whether file exists in cache failed"); + "test of whether file exists in cache failed: mmap failed"); } f_seg = malloc(index); if (f_seg != NULL) { @@ -95,9 +102,8 @@ JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env, free(f_seg); } else { ThrowException(env, "java/io/IOException", - "test of whether file exists in cache failed"); + "test of whether file exists in cache failed: malloc failed"); } - close(fd); munmap(f_mmap, file_size); return result; } diff --git a/test/jdk/java/nio/channels/SocketChannel/PeerReadsAfterAsyncClose.java b/test/jdk/java/nio/channels/SocketChannel/PeerReadsAfterAsyncClose.java new file mode 100644 index 00000000000..98b372a4b11 --- /dev/null +++ b/test/jdk/java/nio/channels/SocketChannel/PeerReadsAfterAsyncClose.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8358764 + * @summary Test closing a socket while a thread is blocked in read. The connection + * should be closed gracefuly so that the peer reads EOF. + * @run junit PeerReadsAfterAsyncClose + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.SocketChannel; +import java.util.Arrays; +import java.util.Objects; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; + +class PeerReadsAfterAsyncClose { + + static Stream factories() { + return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory()); + } + + /** + * Close SocketChannel while a thread is blocked reading from the channel's socket. + */ + @ParameterizedTest + @MethodSource("factories") + void testCloseDuringSocketChannelRead(ThreadFactory factory) throws Exception { + var loopback = InetAddress.getLoopbackAddress(); + try (var listener = new ServerSocket()) { + listener.bind(new InetSocketAddress(loopback, 0)); + + try (SocketChannel sc = SocketChannel.open(listener.getLocalSocketAddress()); + Socket peer = listener.accept()) { + + // start thread to read from channel + var cceThrown = new AtomicBoolean(); + Thread thread = factory.newThread(() -> { + try { + sc.read(ByteBuffer.allocate(1)); + fail(); + } catch (ClosedChannelException e) { + cceThrown.set(true); + } catch (Throwable e) { + e.printStackTrace(); + } + }); + thread.start(); + try { + // close SocketChannel when thread sampled in read() + onReach(thread, "sun.nio.ch.SocketChannelImpl.read", () -> { + try { + sc.close(); + } catch (IOException ignore) { } + }); + + // peer should read EOF + int n = peer.getInputStream().read(); + assertEquals(-1, n); + } finally { + thread.join(); + } + assertEquals(true, cceThrown.get(), "ClosedChannelException not thrown"); + } + } + } + + /** + * Close Socket while a thread is blocked reading from the socket. + */ + @ParameterizedTest + @MethodSource("factories") + void testCloseDuringSocketUntimedRead(ThreadFactory factory) throws Exception { + testCloseDuringSocketRead(factory, 0); + } + + /** + * Close Socket while a thread is blocked reading from the socket with a timeout. + */ + @ParameterizedTest + @MethodSource("factories") + void testCloseDuringSockeTimedRead(ThreadFactory factory) throws Exception { + testCloseDuringSocketRead(factory, 60_000); + } + + private void testCloseDuringSocketRead(ThreadFactory factory, int timeout) throws Exception { + var loopback = InetAddress.getLoopbackAddress(); + try (var listener = new ServerSocket()) { + listener.bind(new InetSocketAddress(loopback, 0)); + + try (Socket s = new Socket(loopback, listener.getLocalPort()); + Socket peer = listener.accept()) { + + // start thread to read from socket + var seThrown = new AtomicBoolean(); + Thread thread = factory.newThread(() -> { + try { + s.setSoTimeout(timeout); + s.getInputStream().read(); + fail(); + } catch (SocketException e) { + seThrown.set(true); + } catch (Throwable e) { + e.printStackTrace(); + } + }); + thread.start(); + try { + // close Socket when thread sampled in implRead + onReach(thread, "sun.nio.ch.NioSocketImpl.implRead", () -> { + try { + s.close(); + } catch (IOException ignore) { } + }); + + // peer should read EOF + int n = peer.getInputStream().read(); + assertEquals(-1, n); + } finally { + thread.join(); + } + assertEquals(true, seThrown.get(), "SocketException not thrown"); + } + } + } + + /** + * Runs the given action when the given target thread is sampled at the given + * location. The location takes the form "{@code c.m}" where + * {@code c} is the fully qualified class name and {@code m} is the method name. + */ + private void onReach(Thread target, String location, Runnable action) { + int index = location.lastIndexOf('.'); + String className = location.substring(0, index); + String methodName = location.substring(index + 1); + Thread.ofPlatform().daemon(true).start(() -> { + try { + boolean found = false; + while (!found) { + found = contains(target.getStackTrace(), className, methodName); + if (!found) { + Thread.sleep(20); + } + } + action.run(); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + /** + * Returns true if the given stack trace contains an element for the given class + * and method name. + */ + private boolean contains(StackTraceElement[] stack, String className, String methodName) { + return Arrays.stream(stack) + .anyMatch(e -> className.equals(e.getClassName()) + && methodName.equals(e.getMethodName())); + } +} diff --git a/test/jdk/java/nio/charset/Charset/AvailableCharsetNames.java b/test/jdk/java/nio/charset/Charset/AvailableCharsetNames.java index 078700f2fae..0f20e957605 100644 --- a/test/jdk/java/nio/charset/Charset/AvailableCharsetNames.java +++ b/test/jdk/java/nio/charset/Charset/AvailableCharsetNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. * 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,27 +25,26 @@ * @bug 4422044 * @summary Ensure that keys in available-charset map * are identical to canonical names + * @run junit AvailableCharsetNames */ -import java.io.*; -import java.nio.*; -import java.nio.charset.*; -import java.util.*; +import java.nio.charset.Charset; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; public class AvailableCharsetNames { - public static void main(String[] args) throws Exception { - Iterator charsetIterator = Charset.availableCharsets().keySet().iterator(); - while (charsetIterator.hasNext()) { - String charsetName = (String) charsetIterator.next(); + /** + * Test that the keys in Charset.availableCharsets() + * are equal to the associated Charset.name() value. + */ + @Test + public void canonicalNamesTest() { + for (String charsetName : Charset.availableCharsets().keySet()) { Charset charset = Charset.forName(charsetName); - if (!charset.name().equals(charsetName)) { - throw new Exception("Error: Charset name mismatch - expected " - + charsetName + ", got " + charset.name()); - } + assertEquals(charset.name(), charsetName, "Charset name mismatch"); } - } - } diff --git a/test/jdk/java/nio/charset/Charset/CharsetContainmentTest.java b/test/jdk/java/nio/charset/Charset/CharsetContainmentTest.java index 7e763f7750c..4bc05388219 100644 --- a/test/jdk/java/nio/charset/Charset/CharsetContainmentTest.java +++ b/test/jdk/java/nio/charset/Charset/CharsetContainmentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. * 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,93 +25,116 @@ * @bug 4626545 4696726 * @summary Checks the inter containment relationships between NIO charsets * @modules jdk.charsets + * @run junit CharsetContainmentTest */ -import java.nio.charset.*; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; -public class CharsetContainmentTest { - static String[] encodings = - { "US-ASCII", "UTF-16", "UTF-16BE", "UTF-16LE", "UTF-8", - "windows-1252", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", - "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", - "ISO-8859-8", "ISO-8859-9", "ISO-8859-13", "ISO-8859-15", "ISO-8859-16", - "ISO-2022-JP", "ISO-2022-KR", +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; - // Temporarily remove ISO-2022-CN-* charsets until full encoder/decoder - // support is added (4673614) - // "x-ISO-2022-CN-CNS", "x-ISO-2022-CN-GB", +import static org.junit.jupiter.api.Assertions.assertTrue; - "x-ISCII91", "GBK", "GB18030", "Big5", - "x-EUC-TW", "GB2312", "EUC-KR", "x-Johab", "Big5-HKSCS", - "x-MS950-HKSCS", "windows-1251", "windows-1253", "windows-1254", - "windows-1255", "windows-1256", "windows-1257", "windows-1258", - "x-mswin-936", "x-windows-949", "x-windows-950", "windows-31j", - "Shift_JIS", "EUC-JP", "KOI8-R", "TIS-620" - }; +public class CharsetContainmentTest { - static String[][] contains = { - { "US-ASCII"}, - encodings, - encodings, - encodings, - encodings, - {"US-ASCII", "windows-1252"}, - {"US-ASCII", "ISO-8859-1"}, - {"US-ASCII", "ISO-8859-2"}, - {"US-ASCII", "ISO-8859-3"}, - {"US-ASCII", "ISO-8859-4"}, - {"US-ASCII", "ISO-8859-5"}, - {"US-ASCII", "ISO-8859-6"}, - {"US-ASCII", "ISO-8859-7"}, - {"US-ASCII", "ISO-8859-8"}, - {"US-ASCII", "ISO-8859-9"}, - {"US-ASCII", "ISO-8859-13"}, - {"US-ASCII", "ISO-8859-15"}, - {"US-ASCII", "ISO-8859-16"}, - {"ISO-2022-JP"}, - {"ISO-2022-KR"}, - // Temporarily remove ISO-2022-CN-* charsets until full encoder/decoder - // support is added (4673614) - //{"x-ISO-2022-CN-CNS"}, - //{"x-ISO-2022-CN-GB"}, - {"US-ASCII", "x-ISCII91"}, - {"US-ASCII", "GBK"}, - encodings, - {"US-ASCII", "Big5"}, - {"US-ASCII", "x-EUC-TW"}, - {"US-ASCII", "GB2312"}, - {"US-ASCII", "EUC-KR"}, - {"US-ASCII", "x-Johab"}, - {"US-ASCII", "Big5-HKSCS", "Big5"}, - {"US-ASCII", "x-MS950-HKSCS", "x-windows-950"}, - {"US-ASCII", "windows-1251"}, - {"US-ASCII", "windows-1253"}, - {"US-ASCII", "windows-1254"}, - {"US-ASCII", "windows-1255"}, - {"US-ASCII", "windows-1256"}, - {"US-ASCII", "windows-1257"}, - {"US-ASCII", "windows-1258"}, - {"US-ASCII", "x-mswin-936"}, - {"US-ASCII", "x-windows-949"}, - {"US-ASCII", "x-windows-950"}, - {"US-ASCII", "windows-31j" }, - {"US-ASCII", "Shift_JIS"}, - {"US-ASCII", "EUC-JP"}, - {"US-ASCII", "KOI8-R"}, - {"US-ASCII", "TIS-620"}}; + /** + * Test that the charsets in 'encodings' contain the charsets + * inside 'contains'. Each value in 'encodings' is mapped to a String + * array in 'contains'. For example, the value, "TIS-620" in 'encodings' + * should contain "US-ASCII", "TIS-620". + */ + @ParameterizedTest + @MethodSource("charsets") + public void interContainmentTest(String containerName, String containedName) { + Charset container = Charset.forName(containerName); + Charset contained = Charset.forName(containedName); + assertTrue(container.contains(contained), + String.format("Charset: %s does not contain: %s", containerName, containedName)); + } + private static Stream charsets() { + String[] encodings = { + "US-ASCII", "UTF-16", "UTF-16BE", "UTF-16LE", "UTF-8", + "windows-1252", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", + "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", + "ISO-8859-8", "ISO-8859-9", "ISO-8859-13", "ISO-8859-15", "ISO-8859-16", + "ISO-2022-JP", "ISO-2022-KR", + // Temporarily remove ISO-2022-CN-* charsets until full encoder/decoder + // support is added (4673614) + // "x-ISO-2022-CN-CNS", "x-ISO-2022-CN-GB", + "x-ISCII91", "GBK", "GB18030", "Big5", + "x-EUC-TW", "GB2312", "EUC-KR", "x-Johab", "Big5-HKSCS", + "x-MS950-HKSCS", "windows-1251", "windows-1253", "windows-1254", + "windows-1255", "windows-1256", "windows-1257", "windows-1258", + "x-mswin-936", "x-windows-949", "x-windows-950", "windows-31j", + "Shift_JIS", "EUC-JP", "KOI8-R", "TIS-620" + }; - public static void main(String[] args) throws Exception { + String[][] contains = { + {"US-ASCII"}, + encodings, + encodings, + encodings, + encodings, + {"US-ASCII", "windows-1252"}, + {"US-ASCII", "ISO-8859-1"}, + {"US-ASCII", "ISO-8859-2"}, + {"US-ASCII", "ISO-8859-3"}, + {"US-ASCII", "ISO-8859-4"}, + {"US-ASCII", "ISO-8859-5"}, + {"US-ASCII", "ISO-8859-6"}, + {"US-ASCII", "ISO-8859-7"}, + {"US-ASCII", "ISO-8859-8"}, + {"US-ASCII", "ISO-8859-9"}, + {"US-ASCII", "ISO-8859-13"}, + {"US-ASCII", "ISO-8859-15"}, + {"US-ASCII", "ISO-8859-16"}, + {"ISO-2022-JP"}, + {"ISO-2022-KR"}, + // Temporarily remove ISO-2022-CN-* charsets until full encoder/decoder + // support is added (4673614) + //{"x-ISO-2022-CN-CNS"}, + //{"x-ISO-2022-CN-GB"}, + {"US-ASCII", "x-ISCII91"}, + {"US-ASCII", "GBK"}, + encodings, + {"US-ASCII", "Big5"}, + {"US-ASCII", "x-EUC-TW"}, + {"US-ASCII", "GB2312"}, + {"US-ASCII", "EUC-KR"}, + {"US-ASCII", "x-Johab"}, + {"US-ASCII", "Big5-HKSCS", "Big5"}, + {"US-ASCII", "x-MS950-HKSCS", "x-windows-950"}, + {"US-ASCII", "windows-1251"}, + {"US-ASCII", "windows-1253"}, + {"US-ASCII", "windows-1254"}, + {"US-ASCII", "windows-1255"}, + {"US-ASCII", "windows-1256"}, + {"US-ASCII", "windows-1257"}, + {"US-ASCII", "windows-1258"}, + {"US-ASCII", "x-mswin-936"}, + {"US-ASCII", "x-windows-949"}, + {"US-ASCII", "x-windows-950"}, + {"US-ASCII", "windows-31j"}, + {"US-ASCII", "Shift_JIS"}, + {"US-ASCII", "EUC-JP"}, + {"US-ASCII", "KOI8-R"}, + {"US-ASCII", "TIS-620"}}; + + // Length of encodings and contains should always be equal + if (encodings.length != contains.length) { + throw new RuntimeException("Testing data is not set up correctly"); + } + List charsetList = new ArrayList(); for (int i = 0; i < encodings.length; i++) { - Charset c = Charset.forName(encodings[i]); - for (int j = 0 ; j < contains[i].length; j++) { - if (c.contains(Charset.forName(contains[i][j]))) - continue; - else { - throw new Exception ("Error: charset " + encodings[i] + - "doesn't contain " + contains[i][j]); - } - } + for (int j = 0 ; j < contains[i].length; j++) { + charsetList.add(Arguments.of(encodings[i], contains[i][j])); + } } + return charsetList.stream(); } } diff --git a/test/jdk/java/nio/charset/Charset/Contains.java b/test/jdk/java/nio/charset/Charset/Contains.java index 0e5cf637231..502c22873c3 100644 --- a/test/jdk/java/nio/charset/Charset/Contains.java +++ b/test/jdk/java/nio/charset/Charset/Contains.java @@ -25,166 +25,186 @@ * @summary Unit test for charset containment * @bug 6798572 8167252 * @modules jdk.charsets + * @run junit Contains */ -import java.nio.charset.*; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; -public class Contains { - - static void ck(Charset cs1, Charset cs2, boolean cont) throws Exception { - if ((cs1.contains(cs2)) != cont) - throw new Exception("Wrong answer: " - + cs1.name() + " contains " + cs2.name()); - System.err.println(cs1.name() - + (cont ? " contains " : " does not contain ") - + cs2.name()); - } - - public static void main(String[] args) throws Exception { +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; - Charset us_ascii = Charset.forName("US-ASCII"); - Charset iso_8859_1 = Charset.forName("ISO-8859-1"); - Charset iso_8859_15 = Charset.forName("ISO-8859-15"); - Charset utf_8 = Charset.forName("UTF-8"); - Charset utf_16be = Charset.forName("UTF-16BE"); - Charset cp1252 = Charset.forName("CP1252"); +public class Contains { - ck(us_ascii, us_ascii, true); - ck(us_ascii, iso_8859_1, false); - ck(us_ascii, iso_8859_15, false); - ck(us_ascii, utf_8, false); - ck(us_ascii, utf_16be, false); - ck(us_ascii, cp1252, false); - - ck(iso_8859_1, us_ascii, true); - ck(iso_8859_1, iso_8859_1, true); - ck(iso_8859_1, iso_8859_15, false); - ck(iso_8859_1, utf_8, false); - ck(iso_8859_1, utf_16be, false); - ck(iso_8859_1, cp1252, false); - - ck(iso_8859_15, us_ascii, true); - ck(iso_8859_15, iso_8859_1, false); - ck(iso_8859_15, iso_8859_15, true); - ck(iso_8859_15, utf_8, false); - ck(iso_8859_15, utf_16be, false); - ck(iso_8859_15, cp1252, false); - - ck(utf_8, us_ascii, true); - ck(utf_8, iso_8859_1, true); - ck(utf_8, iso_8859_15, true); - ck(utf_8, utf_8, true); - ck(utf_8, utf_16be, true); - ck(utf_8, cp1252, true); - - ck(utf_16be, us_ascii, true); - ck(utf_16be, iso_8859_1, true); - ck(utf_16be, iso_8859_15, true); - ck(utf_16be, utf_8, true); - ck(utf_16be, utf_16be, true); - ck(utf_16be, cp1252, true); - - ck(cp1252, us_ascii, true); - ck(cp1252, iso_8859_1, false); - ck(cp1252, iso_8859_15, false); - ck(cp1252, utf_8, false); - ck(cp1252, utf_16be, false); - ck(cp1252, cp1252, true); - - checkUTF(); - - containsSelfTest(); + /** + * Tests the containment of some charsets against themselves. + * This test takes both true and false for 'cont'. + */ + @ParameterizedTest + @MethodSource("charsets") + public void charsetsTest(Charset containerCs, Charset cs, boolean cont){ + shouldContain(containerCs, cs, cont); } - static void checkUTF() throws Exception { - for (String utfName : utfNames) - for (String csName : charsetNames) - ck(Charset.forName(utfName), - Charset.forName(csName), - true); + /** + * Tests UTF charsets with other charsets. In this case, each UTF charset + * should contain every single charset they are tested against. 'cont' is + * always true. + */ + @ParameterizedTest + @MethodSource("utfCharsets") + public void UTFCharsetsTest(Charset containerCs, Charset cs, boolean cont){ + shouldContain(containerCs, cs, cont); } /** * Tests the assertion in the contains() method: "Every charset contains itself." */ - static void containsSelfTest() { - boolean failed = false; - + @Test + public void containsSelfTest() { for (var entry : Charset.availableCharsets().entrySet()) { Charset charset = entry.getValue(); boolean contains = charset.contains(charset); - - System.out.println("Charset(" + charset.name() + ").contains(Charset(" + charset.name() - + ")) returns " + contains); - if (!contains) { - failed = true; - } - } - if (failed) { - throw new RuntimeException("Charset.contains(itself) returns false for some charsets"); + assertTrue(contains, String.format("Charset(%s).contains(Charset(%s)) returns %s", + charset.name(), charset.name(), contains)); } } - static String[] utfNames = {"utf-16", - "utf-8", - "utf-16le", - "utf-16be", - "x-utf-16le-bom"}; - - static String[] charsetNames = { - "US-ASCII", - "UTF-8", - "UTF-16", - "UTF-16BE", - "UTF-16LE", - "x-UTF-16LE-BOM", - "GBK", - "GB18030", - "ISO-8859-1", - "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", - "ISO-8859-13", - "JIS_X0201", - "x-JIS0208", - "JIS_X0212-1990", - "GB2312", - "EUC-KR", - "x-EUC-TW", - "EUC-JP", - "x-euc-jp-linux", - "KOI8-R", - "TIS-620", - "x-ISCII91", - "windows-1251", - "windows-1252", - "windows-1253", - "windows-1254", - "windows-1255", - "windows-1256", - "windows-1257", - "windows-1258", - "windows-932", - "x-mswin-936", - "x-windows-949", - "x-windows-950", - "windows-31j", - "Big5", - "Big5-HKSCS", - "x-MS950-HKSCS", - "ISO-2022-JP", - "ISO-2022-KR", - "x-ISO-2022-CN-CNS", - "x-ISO-2022-CN-GB", - "Big5-HKSCS", - "x-Johab", - "Shift_JIS" - }; + /** + * Helper method that checks if a charset should contain another charset. + */ + static void shouldContain(Charset containerCs, Charset cs, boolean cont){ + assertEquals((containerCs.contains(cs)), cont, String.format("%s %s %s", + containerCs.name(), (cont ? " contains " : " does not contain "), cs.name())); + } + + private static Stream utfCharsets() { + String[] utfNames = { + "utf-16", + "utf-8", + "utf-16le", + "utf-16be", + "x-utf-16le-bom" + }; + + String[] charsetNames = { + "US-ASCII", + "UTF-8", + "UTF-16", + "UTF-16BE", + "UTF-16LE", + "x-UTF-16LE-BOM", + "GBK", + "GB18030", + "ISO-8859-1", + "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", + "ISO-8859-13", + "JIS_X0201", + "x-JIS0208", + "JIS_X0212-1990", + "GB2312", + "EUC-KR", + "x-EUC-TW", + "EUC-JP", + "x-euc-jp-linux", + "KOI8-R", + "TIS-620", + "x-ISCII91", + "windows-1251", + "windows-1252", + "windows-1253", + "windows-1254", + "windows-1255", + "windows-1256", + "windows-1257", + "windows-1258", + "windows-932", + "x-mswin-936", + "x-windows-949", + "x-windows-950", + "windows-31j", + "Big5", + "Big5-HKSCS", + "x-MS950-HKSCS", + "ISO-2022-JP", + "ISO-2022-KR", + "x-ISO-2022-CN-CNS", + "x-ISO-2022-CN-GB", + "Big5-HKSCS", + "x-Johab", + "Shift_JIS" + }; + + // All charsets in utfNames should contain + // all charsets in charsetNames + return Arrays.stream(utfNames).flatMap(cs1 -> Arrays.stream(charsetNames) + .map(cs2 -> Arguments.of(Charset.forName(cs1), Charset.forName(cs2), true))); + } + + private static Stream charsets() { + Charset us_ascii = Charset.forName("US-ASCII"); + Charset iso_8859_1 = Charset.forName("ISO-8859-1"); + Charset iso_8859_15 = Charset.forName("ISO-8859-15"); + Charset utf_8 = Charset.forName("UTF-8"); + Charset utf_16be = Charset.forName("UTF-16BE"); + Charset cp1252 = Charset.forName("CP1252"); + + return Stream.of( + Arguments.of(us_ascii, us_ascii, true), + Arguments.of(us_ascii, iso_8859_1, false), + Arguments.of(us_ascii, iso_8859_15, false), + Arguments.of(us_ascii, utf_8, false), + Arguments.of(us_ascii, utf_16be, false), + Arguments.of(us_ascii, cp1252, false), + + Arguments.of(iso_8859_1, us_ascii, true), + Arguments.of(iso_8859_1, iso_8859_1, true), + Arguments.of(iso_8859_1, iso_8859_15, false), + Arguments.of(iso_8859_1, utf_8, false), + Arguments.of(iso_8859_1, utf_16be, false), + Arguments.of(iso_8859_1, cp1252, false), + + Arguments.of(iso_8859_15, us_ascii, true), + Arguments.of(iso_8859_15, iso_8859_1, false), + Arguments.of(iso_8859_15, iso_8859_15, true), + Arguments.of(iso_8859_15, utf_8, false), + Arguments.of(iso_8859_15, utf_16be, false), + Arguments.of(iso_8859_15, cp1252, false), + + Arguments.of(utf_8, us_ascii, true), + Arguments.of(utf_8, iso_8859_1, true), + Arguments.of(utf_8, iso_8859_15, true), + Arguments.of(utf_8, utf_8, true), + Arguments.of(utf_8, utf_16be, true), + Arguments.of(utf_8, cp1252, true), + + Arguments.of(utf_16be, us_ascii, true), + Arguments.of(utf_16be, iso_8859_1, true), + Arguments.of(utf_16be, iso_8859_15, true), + Arguments.of(utf_16be, utf_8, true), + Arguments.of(utf_16be, utf_16be, true), + Arguments.of(utf_16be, cp1252, true), + + Arguments.of(cp1252, us_ascii, true), + Arguments.of(cp1252, iso_8859_1, false), + Arguments.of(cp1252, iso_8859_15, false), + Arguments.of(cp1252, utf_8, false), + Arguments.of(cp1252, utf_16be, false), + Arguments.of(cp1252, cp1252, true) + ); + } } diff --git a/test/jdk/java/nio/charset/Charset/EmptyCharsetName.java b/test/jdk/java/nio/charset/Charset/EmptyCharsetName.java deleted file mode 100644 index 93797622553..00000000000 --- a/test/jdk/java/nio/charset/Charset/EmptyCharsetName.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @bug 4786884 - * @summary Ensure that passing the empty string to Charset methods and - * constructors causes an IllegalArgumentException to be thrown - */ - -import java.io.*; -import java.nio.*; -import java.nio.charset.*; - - -public class EmptyCharsetName { - - static abstract class Test { - - public abstract void go() throws Exception; - - Test() throws Exception { - try { - go(); - } catch (Exception x) { - if (x instanceof IllegalCharsetNameException) { - System.err.println("Thrown as expected: " + x); - return; - } - throw new Exception("Incorrect exception: " - + x.getClass().getName(), - x); - } - throw new Exception("No exception thrown"); - } - - } - - public static void main(String[] args) throws Exception { - - new Test() { - public void go() throws Exception { - Charset.forName(""); - }}; - new Test() { - public void go() throws Exception { - Charset.isSupported(""); - }}; - new Test() { - public void go() throws Exception { - new Charset("", new String[] { }) { - public CharsetDecoder newDecoder() { - return null; - } - public CharsetEncoder newEncoder() { - return null; - } - public boolean contains(Charset cs) { - return false; - } - }; - }}; - } - -} diff --git a/test/jdk/java/nio/charset/Charset/EncDec.java b/test/jdk/java/nio/charset/Charset/EncDec.java index b0d2ccd92ec..324418ad074 100644 --- a/test/jdk/java/nio/charset/Charset/EncDec.java +++ b/test/jdk/java/nio/charset/Charset/EncDec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. * 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,23 +23,42 @@ /* @test * @summary Unit test for encode/decode convenience methods + * @run junit EncDec */ +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.stream.Stream; -import java.nio.*; -import java.nio.charset.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; public class EncDec { - public static void main(String[] args) throws Exception { - String s = "Hello, world!"; + /** + * Test that the input String is the same after round tripping + * the Charset.encode() and Charset.decode() methods. + */ + @ParameterizedTest + @MethodSource("stringProvider") + public void roundTripTest(String pre) { ByteBuffer bb = ByteBuffer.allocate(100); - bb.put(Charset.forName("ISO-8859-15").encode(s)).flip(); - String t = Charset.forName("UTF-8").decode(bb).toString(); - System.err.println(t); - if (!t.equals(s)) - throw new Exception("Mismatch: " + s + " != " + t); + Charset preCs = Charset.forName("ISO-8859-15"); + if (!preCs.canEncode()) { + throw new RuntimeException("Error: Trying to test encode and " + + "decode methods on a charset that does not support encoding"); + } + bb.put(preCs.encode(pre)).flip(); + String post = Charset.forName("UTF-8").decode(bb).toString(); + assertEquals(pre, post, "Mismatch after encoding + decoding, :"); } + static Stream stringProvider() { + return Stream.of( + "Hello, world!", + "apple, banana, orange", + "car, truck, horse"); + } } diff --git a/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java b/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java index dd7c68c9782..9f2879a3ff0 100644 --- a/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java +++ b/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * 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,46 +22,71 @@ */ /* @test - * @bug 6330020 8184665 + * @bug 4786884 6330020 8184665 * @summary Ensure Charset.forName/isSupport throws the correct exception * if the charset names passed in are illegal. + * @run junit IllegalCharsetName */ -import java.nio.charset.*; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.IllegalCharsetNameException; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertThrows; public class IllegalCharsetName { - public static void main(String[] args) throws Exception { - String[] illegalNames = { - ".", - "_", - ":", - "-", - ".name", - "_name", - ":name", - "-name", - "name*name", - "name?name" - }; - for (int i = 0; i < illegalNames.length; i++) { - try { - Charset.forName(illegalNames[i]); - throw new Exception("Charset.forName(): No exception thrown"); - } catch (IllegalCharsetNameException x) { //expected - } - try { - Charset.isSupported(illegalNames[i]); - throw new Exception("Charset.isSupported(): No exception thrown"); - } catch (IllegalCharsetNameException x) { //expected - } - } + // Charset.forName and Charset.isSupported should throw an + // IllegalCharsetNameException when passed an illegal name + @ParameterizedTest + @MethodSource("illegalNames") + public void illegalCharsetsTest(String name) { + assertThrows(IllegalCharsetNameException.class, + () -> Charset.forName(name)); + assertThrows(IllegalCharsetNameException.class, + () -> Charset.isSupported(name)); + } + + // Charset.forName, Charset.isSupported, and the Charset constructor should + // throw an IllegalCharsetNameException when passed an empty name + @Test + public void emptyCharsetsTest() { + assertThrows(IllegalCharsetNameException.class, + () -> Charset.forName("")); + assertThrows(IllegalCharsetNameException.class, + () -> Charset.isSupported("")); + assertThrows(IllegalCharsetNameException.class, + () -> new Charset("", new String[]{}) { + @Override + public boolean contains(Charset cs) { + return false; + } + + @Override + public CharsetDecoder newDecoder() { + return null; + } - // Standard charsets may bypass alias checking during startup, test that - // they're all well-behaved as a sanity test - checkAliases(StandardCharsets.ISO_8859_1); - checkAliases(StandardCharsets.US_ASCII); - checkAliases(StandardCharsets.UTF_8); + @Override + public CharsetEncoder newEncoder() { + return null; + } + }); + } + + // Standard charsets may bypass alias checking during startup, test that + // they're all well-behaved as a sanity test + @Test + public void aliasTest() { + for (Charset cs : Charset.availableCharsets().values()) { + checkAliases(cs); + } } private static void checkAliases(Charset cs) { @@ -70,4 +95,19 @@ private static void checkAliases(Charset cs) { Charset.isSupported(alias); } } + + static Stream illegalNames() { + return Stream.of( + ".", + "_", + ":", + "-", + ".name", + "_name", + ":name", + "-name", + "name*name", + "name?name" + ); + } } diff --git a/test/jdk/java/nio/charset/Charset/NullCharsetName.java b/test/jdk/java/nio/charset/Charset/NullCharsetName.java index 591fbf14cdf..a6b3a952215 100644 --- a/test/jdk/java/nio/charset/Charset/NullCharsetName.java +++ b/test/jdk/java/nio/charset/Charset/NullCharsetName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved. * 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,29 +24,21 @@ /* @test * @bug 4448594 * @summary Ensure passing null to Charset.forName throws the correct exception + * @run junit NullCharsetName */ -import java.io.*; -import java.nio.*; -import java.nio.charset.*; -import java.util.*; +import java.nio.charset.Charset; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; public class NullCharsetName { - public static void main(String[] args) throws Exception { - try { - Charset.forName(null); - } catch (Exception x) { - if (x instanceof IllegalArgumentException) { - System.err.println("Thrown as expected: " + x); - return; - } - throw new Exception("Incorrect exception: " - + x.getClass().getName(), - x); - } - throw new Exception("No exception thrown"); + // Charset.forName should throw an exception when passed null + @Test + public void nullCharsetTest() { + assertThrows(IllegalArgumentException.class, + () -> Charset.forName(null)); } - } diff --git a/test/jdk/java/nio/charset/Charset/RegisteredCharsets.java b/test/jdk/java/nio/charset/Charset/RegisteredCharsets.java index 495d2a32bcd..c4a9853547b 100644 --- a/test/jdk/java/nio/charset/Charset/RegisteredCharsets.java +++ b/test/jdk/java/nio/charset/Charset/RegisteredCharsets.java @@ -26,1288 +26,1328 @@ 6911753 8071447 8186751 8242541 8260265 8301119 * @summary Check that registered charsets are actually registered * @modules jdk.charsets - * @run main RegisteredCharsets - * @run main/othervm -Djdk.charset.GB18030=2000 RegisteredCharsets + * @run junit RegisteredCharsets + * @run junit/othervm -Djdk.charset.GB18030=2000 RegisteredCharsets */ -import java.nio.charset.*; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.stream.Stream; -public class RegisteredCharsets { +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; - static String [] ianaRegistered = { - "US-ASCII", "UTF8", "Big5", "EUC-JP", - "GBK", "GB18030", "ISO-2022-KR", "ISO-2022-JP", - "GB2312", // IANA preferred name for "EUC-CN" - "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", - "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", - "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", - "ISO-8859-13", "ISO-8859-15", "ISO-8859-16", - "windows-1251", - "windows-1252", "windows-1253", "windows-1254", - "windows-1255", "windows-1256", "windows-31j", - "Shift_JIS", "JIS_X0201", "JIS_X0212-1990", - "TIS-620", "Big5-HKSCS", - "ISO-2022-CN", - "IBM850", - "IBM852", - "IBM855", - "IBM857", - "IBM860", - "IBM861", - "IBM862", - "IBM863", - "IBM864", - "IBM865", - "IBM866", - "IBM868", - "IBM869", - "IBM437", - "IBM775", - "IBM037", - "IBM1026", - "IBM273", - "IBM277", - "IBM278", - "IBM280", - "IBM284", - "IBM285", - "IBM297", - "IBM420", - "IBM424", - "IBM500", - "IBM-Thai", - "IBM870", - "IBM871", - "IBM918", - "IBM1047", - "IBM01140", - "IBM01141", - "IBM01142", - "IBM01143", - "IBM01144", - "IBM01145", - "IBM01146", - "IBM01147", - "IBM01148", - "IBM01149", - "IBM00858" }; - - static String [] ianaUnRegistered = { - "x-EUC-TW", "x-ISCII91", - "x-windows-949", "x-windows-950", - "x-mswin-936", "x-JIS0208", - "x-ISO-8859-11", - "x-windows-874", - "x-PCK", "x-JISAutoDetect", "x-Johab", - "x-MS950-HKSCS", - "x-Big5-Solaris", - "x-ISO-2022-CN-CNS", - "x-ISO-2022-CN-GB", - "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-IBM942", - "x-IBM942C", - "x-IBM943", - "x-IBM943C", - "x-IBM948", - "x-IBM950", - "x-IBM930", - "x-IBM935", - "x-IBM937", - "x-IBM856", - "x-IBM874", - "x-IBM737", - "x-IBM1006", - "x-IBM1046", - "x-IBM1098", - "x-IBM1025", - "x-IBM1112", - "x-IBM1122", - "x-IBM1123", - "x-IBM1124", - "x-IBM1129", - "x-IBM1166", - "x-IBM875", - "x-IBM921", - "x-IBM922", - "x-IBM1097", - "x-IBM949", - "x-IBM949C", - "x-IBM939", - "x-IBM933", - "x-IBM1381", - "x-IBM1383", - "x-IBM970", - "x-IBM964", - "x-IBM33722", - "x-IBM1006", - "x-IBM1046", - "x-IBM1097", - "x-IBM1098", - "x-IBM1112", - "x-IBM1122", - "x-IBM1123", - "x-IBM1124", - "x-IBM33722", - "x-IBM737", - "x-IBM856", - "x-IBM874", - "x-IBM875", - "x-IBM922", - "x-IBM933", - "x-IBM964" }; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; - static void check(String csn, boolean testRegistered) throws Exception { - if (!Charset.forName(csn).isRegistered() && testRegistered) - throw new Exception("Not registered: " + csn); - else if (Charset.forName(csn).isRegistered() && !testRegistered) - throw new Exception("Registered: " + csn + "should be unregistered"); +public class RegisteredCharsets { + + // Charset.forName should throw an exception when passed "default" + @Test + public void defaultCharsetTest() { + assertThrows(UnsupportedCharsetException.class, + () -> Charset.forName("default")); } - static void aliasCheck(String canonicalName, String[] aliasNames) throws Exception - { - for (int k = 0; k < aliasNames.length; k++ ) { - Charset cs = Charset.forName(aliasNames[k]); - if (!cs.name().equals(canonicalName)) { - throw new Exception("Unexpected Canonical name " + canonicalName); - } + /** + * Tests that the aliases of the input String convert + * to the same Charset. This is validated by ensuring the input String + * and Charset.name() values are equal. + */ + @ParameterizedTest + @MethodSource("aliases") + public void testAliases(String canonicalName, String[] aliasNames) { + for (String aliasName : aliasNames) { + Charset cs = Charset.forName(aliasName); + assertEquals(cs.name(), canonicalName); } } - public static void main(String[] args) throws Exception { + /** + * Tests charsets to ensure that they are registered in the + * IANA Charset Registry. + */ + @ParameterizedTest + @MethodSource("ianaRegistered") + public void registeredTest(String cs) throws Exception { + check(cs, true); + } - for (int i = 0; i < ianaRegistered.length ; i++) - check(ianaRegistered[i], true); + /** + * Tests charsets to ensure that they are NOT registered in the + * IANA Charset Registry. + */ + @ParameterizedTest + @MethodSource("ianaUnregistered") + public void unregisteredTest(String cs) throws Exception { + check(cs, false); + } - for (int i = 0; i < ianaUnRegistered.length ; i++) - check(ianaUnRegistered[i], false); + /** + * Helper method which checks if a charset is registered and whether + * it should be. + */ + static void check(String csn, boolean testRegistered) throws Exception { + if (!Charset.forName(csn).isRegistered() && testRegistered) { + throw new Exception("Not registered: " + csn); + } + else if (Charset.forName(csn).isRegistered() && !testRegistered) { + throw new Exception("Registered: " + csn + "should be unregistered"); + } + } + + // See https://www.iana.org/assignments/character-sets/character-sets.xhtml + private static Stream ianaRegistered() { + return Stream.of( + "US-ASCII", "UTF8", "Big5", "EUC-JP", + "GBK", "GB18030", "ISO-2022-KR", "ISO-2022-JP", + "GB2312", // IANA preferred name for "EUC-CN" + "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", + "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", + "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", + "ISO-8859-13", "ISO-8859-15", "ISO-8859-16", + "windows-1251", + "windows-1252", "windows-1253", "windows-1254", + "windows-1255", "windows-1256", "windows-31j", + "Shift_JIS", "JIS_X0201", "JIS_X0212-1990", + "TIS-620", "Big5-HKSCS", + "ISO-2022-CN", + "IBM850", + "IBM852", + "IBM855", + "IBM857", + "IBM860", + "IBM861", + "IBM862", + "IBM863", + "IBM864", + "IBM865", + "IBM866", + "IBM868", + "IBM869", + "IBM437", + "IBM775", + "IBM037", + "IBM1026", + "IBM273", + "IBM277", + "IBM278", + "IBM280", + "IBM284", + "IBM285", + "IBM297", + "IBM420", + "IBM424", + "IBM500", + "IBM-Thai", + "IBM870", + "IBM871", + "IBM918", + "IBM1047", + "IBM01140", + "IBM01141", + "IBM01142", + "IBM01143", + "IBM01144", + "IBM01145", + "IBM01146", + "IBM01147", + "IBM01148", + "IBM01149", + "IBM00858" + ); + } + private static Stream ianaUnregistered() { + return Stream.of( + "x-EUC-TW", "x-ISCII91", + "x-windows-949", "x-windows-950", + "x-mswin-936", "x-JIS0208", + "x-ISO-8859-11", + "x-windows-874", + "x-PCK", "x-JISAutoDetect", "x-Johab", + "x-MS950-HKSCS", + "x-Big5-Solaris", + "x-ISO-2022-CN-CNS", + "x-ISO-2022-CN-GB", + "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-IBM942", + "x-IBM942C", + "x-IBM943", + "x-IBM943C", + "x-IBM948", + "x-IBM950", + "x-IBM930", + "x-IBM935", + "x-IBM937", + "x-IBM856", + "x-IBM874", + "x-IBM737", + "x-IBM1006", + "x-IBM1046", + "x-IBM1098", + "x-IBM1025", + "x-IBM1112", + "x-IBM1122", + "x-IBM1123", + "x-IBM1124", + "x-IBM1129", + "x-IBM1166", + "x-IBM875", + "x-IBM921", + "x-IBM922", + "x-IBM1097", + "x-IBM949", + "x-IBM949C", + "x-IBM939", + "x-IBM933", + "x-IBM1381", + "x-IBM1383", + "x-IBM970", + "x-IBM964", + "x-IBM33722", + "x-IBM1006", + "x-IBM1046", + "x-IBM1097", + "x-IBM1098", + "x-IBM1112", + "x-IBM1122", + "x-IBM1123", + "x-IBM1124", + "x-IBM33722", + "x-IBM737", + "x-IBM856", + "x-IBM874", + "x-IBM875", + "x-IBM922", + "x-IBM933", + "x-IBM964" + ); + } + + private static Stream aliases() { // Check aliases registered with IANA for all NIO supported // Charset implementations. // // The aliases below are in sync with the IANA registered charset // document at: http://www.iana.org/assignments/character-sets // Last updated 7/25/2002 - - aliasCheck("US-ASCII", - new String[] {"ascii","ANSI_X3.4-1968", - "iso-ir-6","ANSI_X3.4-1986", "ISO_646.irv:1991", - "ASCII", "ISO646-US","us","IBM367","cp367", - "csASCII"}); - - aliasCheck("UTF-8", - new String[] { - "UTF8", - "unicode-1-1-utf-8" - }); - - aliasCheck("UTF-16", - new String[] { - "UTF_16", - "utf16" - }); - - aliasCheck("UTF-16BE", - new String[] { - "UTF_16BE", - "ISO-10646-UCS-2", - "X-UTF-16BE", - "UnicodeBigUnmarked" - }); - - aliasCheck("UTF-16LE", - new String[] { - "UTF_16LE", - "X-UTF-16LE", - "UnicodeLittleUnmarked" - }); - - aliasCheck("Big5", - new String[] { - "csBig5" - }); - - aliasCheck("Big5-HKSCS", - new String[] { - "Big5_HKSCS", - "big5hk", - "big5-hkscs", - "big5hkscs" - }); - - aliasCheck("x-MS950-HKSCS", - new String[] { - "MS950_HKSCS" - }); - - aliasCheck("GB18030", - "2000".equals(System.getProperty("jdk.charset.GB18030")) ? - new String[] { - "gb18030-2000" - } : - new String[] { - "gb18030-2022" - }); - - aliasCheck("ISO-2022-KR", new String[] {"csISO2022KR"}); - aliasCheck("ISO-2022-JP", new String[] {"csISO2022JP"}); - aliasCheck("EUC-KR", new String[] { "csEUCKR"}); - aliasCheck("ISO-8859-1", - new String[] { - - // IANA aliases - "iso-ir-100", - "ISO_8859-1", - "latin1", - "l1", - "IBM819", - "cp819", - "csISOLatin1", - - // JDK historical aliases - "819", - "IBM-819", - "ISO8859_1", - "ISO_8859-1:1987", - "ISO_8859_1", - "8859_1", - "ISO8859-1", - - }); - - aliasCheck("ISO-8859-2", - new String[] { - "ISO_8859-2", - "ISO_8859-2:1987", - "iso-ir-101", - "latin2", - "l2", - "8859_2", - "iso_8859-2:1987", - "iso8859-2", - "ibm912", - "ibm-912", - "cp912", - "912", - "csISOLatin2"}); - - aliasCheck("ISO-8859-3", - new String[] {"latin3", - "ISO_8859-3:1988", - "iso-ir-109", - "l3", - "8859_3", - "iso_8859-3:1988", - "iso8859-3", - "ibm913", - "ibm-913", - "cp913", - "913", - "csISOLatin3"}); - - aliasCheck("ISO-8859-4", - new String[] {"csISOLatin4", - "ISO_8859-4:1988", - "iso-ir-110", - "latin4", - "8859_4", - "iso_8859-4:1988", - "iso8859-4", - "ibm914", - "ibm-914", - "cp914", - "914", - "l4"}); - - aliasCheck("ISO-8859-5", - new String[] { - "iso8859_5", // JDK historical - "8859_5", - "iso-ir-144", - "ISO_8859-5", - "ISO_8859-5:1988", - "ISO8859-5", - "cyrillic", - "ibm915", - "ibm-915", - "915", - "cp915", - "csISOLatinCyrillic" - }); - - aliasCheck("ISO-8859-6", - new String[] {"ISO_8859-6:1987", - "iso-ir-127", - "ISO_8859-6", - "ECMA-114", - "ASMO-708", - "arabic", - "8859_6", - "iso_8859-6:1987", - "iso8859-6", - "ibm1089", - "ibm-1089", - "cp1089", - "1089", - "csISOLatinArabic"}); - - aliasCheck("ISO-8859-7", - new String[] {"ISO_8859-7:1987", - "iso-ir-126", - "ISO_8859-7", - "ELOT_928", - "ECMA-118", - "greek", - "greek8", - "8859_7", - "iso_8859-7:1987", - "iso8859-7", - "ibm813", - "ibm-813", - "cp813", - "813", - "csISOLatinGreek"}); - - aliasCheck("ISO-8859-8", - new String[] { - "ISO_8859-8:1988", - "iso-ir-138", - "ISO_8859-8", - "hebrew", - "8859_8", - "iso_8859-8:1988", - "iso8859-8", - "ibm916", - "ibm-916", - "cp916", - "916", - "csISOLatinHebrew"}); - - aliasCheck("ISO-8859-9", - new String[] {"ISO_8859-9:1989", - "iso-ir-148", - "ISO_8859-9", - "latin5", - "l5", - "8859_9", - "iso8859-9", - "ibm920", - "ibm-920", - "cp920", - "920", - "csISOLatin5"}); - - aliasCheck("ISO-8859-13", - new String[] { - "iso8859_13", // JDK historical - "iso_8859-13", - "8859_13", - "ISO8859-13" - }); - - aliasCheck("ISO-8859-15", - new String[] { - // IANA alias - "ISO_8859-15", - "Latin-9", - "csISO885915", - // JDK historical aliases - "8859_15", - "ISO-8859-15", - "ISO_8859-15", - "ISO8859-15", - "ISO8859_15", - "IBM923", - "IBM-923", - "cp923", - "923", - "LATIN0", - "LATIN9", - "L9", - "csISOlatin0", - "csISOlatin9", - "ISO8859_15_FDIS" - }); - - aliasCheck("ISO-8859-16", - new String[] { - "iso-ir-226", - "ISO_8859-16:2001", - "ISO_8859-16", - "ISO8859_16", - "latin10", - "l10", - "csISO885916" - }); - - aliasCheck("JIS_X0212-1990", - new String[] { - "iso-ir-159", - "csISO159JISX02121990"}); - - aliasCheck("JIS_X0201", - new String[]{ - "X0201", - "csHalfWidthKatakana"}); - - aliasCheck("KOI8-R", - new String[] { - "KOI8_R", - "csKOI8R"}); - - aliasCheck("GBK", - new String[] { - "windows-936"}); - - aliasCheck("Shift_JIS", - new String[] { - "MS_Kanji", - "csShiftJIS"}); - - aliasCheck("EUC-JP", - new String[] { - "Extended_UNIX_Code_Packed_Format_for_Japanese", - "csEUCPkdFmtJapanese"}); - - aliasCheck("Big5", new String[] {"csBig5"}); - - aliasCheck("windows-31j", new String[] {"csWindows31J"}); - - aliasCheck("x-iso-8859-11", - new String[] { "iso-8859-11", "iso8859_11" }); - - aliasCheck("windows-1250", - new String[] { - "cp1250", - "cp5346" - }); - - aliasCheck("windows-1251", - new String[] { - "cp1251", - "cp5347", - "ansi-1251" - }); - - aliasCheck("windows-1252", - new String[] { - "cp1252", - "cp5348" - }); - - aliasCheck("windows-1253", - new String[] { - "cp1253", - "cp5349" - }); - - aliasCheck("windows-1254", - new String[] { - "cp1254", - "cp5350" - }); - - aliasCheck("windows-1255", - new String[] { - "cp1255" - }); - - aliasCheck("windows-1256", - new String[] { - "cp1256" - }); - - aliasCheck("windows-1257", - new String[] { - "cp1257", - "cp5353" - }); - - aliasCheck("windows-1258", - new String[] { - "cp1258" - }); - - aliasCheck("x-windows-874", - new String[] { - "ms874", "ms-874", "windows-874" }); - - aliasCheck("GB2312", - new String[] { - "x-EUC-CN", - "gb2312-80", - "gb2312-1980", - "euc-cn", - "euccn" }); - - aliasCheck("x-IBM942" , - new String[] { - "cp942", // JDK historical - "ibm942", - "ibm-942", - "942" - }); - - aliasCheck("x-IBM942C" , - new String[] { - "cp942C", // JDK historical - "ibm942C", - "ibm-942C", - "942C" - } ); - - aliasCheck("x-IBM943" , - new String[] { - "cp943", // JDK historical - "ibm943", - "ibm-943", - "943" - } ); - - aliasCheck("x-IBM943C" , - new String[] { - "cp943c", // JDK historical - "ibm943C", - "ibm-943C", - "943C" - } ); - - aliasCheck("x-IBM948" , - new String[] { - "cp948", // JDK historical - "ibm948", - "ibm-948", - "948" - } ); - - aliasCheck("x-IBM950" , - new String[] { - "cp950", // JDK historical - "ibm950", - "ibm-950", - "950" - } ); - - aliasCheck("x-IBM930" , - new String[] { - "cp930", // JDK historical - "ibm930", - "ibm-930", - "930" - } ); - - aliasCheck("x-IBM935" , - new String[] { - "cp935", // JDK historical - "ibm935", - "ibm-935", - "935" - } ); - - aliasCheck("x-IBM937" , - new String[] { - "cp937", // JDK historical - "ibm937", - "ibm-937", - "937" - } ); - - aliasCheck("IBM850" , - new String[] { - "cp850", // JDK historical - "ibm-850", - "ibm850", - "850", - "cspc850multilingual" - } ); - - aliasCheck("IBM852" , - new String[] { - "cp852", // JDK historical - "ibm852", - "ibm-852", - "852", - "csPCp852" - } ); - - aliasCheck("IBM855" , - new String[] { - "cp855", // JDK historical - "ibm-855", - "ibm855", - "855", - "cspcp855" - } ); - - aliasCheck("x-IBM856" , - new String[] { - "cp856", // JDK historical - "ibm-856", - "ibm856", - "856" - } ); - - aliasCheck("IBM857" , - new String[] { - "cp857", // JDK historical - "ibm857", - "ibm-857", - "857", - "csIBM857" - } ); - - aliasCheck("IBM860" , - new String[] { - "cp860", // JDK historical - "ibm860", - "ibm-860", - "860", - "csIBM860" - } ); - aliasCheck("IBM861" , - new String[] { - "cp861", // JDK historical - "ibm861", - "ibm-861", - "861", - "csIBM861" - } ); - - aliasCheck("IBM862" , - new String[] { - "cp862", // JDK historical - "ibm862", - "ibm-862", - "862", - "csIBM862" - } ); - - aliasCheck("IBM863" , - new String[] { - "cp863", // JDK historical - "ibm863", - "ibm-863", - "863", - "csIBM863" - } ); - - aliasCheck("IBM864" , - new String[] { - "cp864", // JDK historical - "ibm864", - "ibm-864", - "864", - "csIBM864" - } ); - - aliasCheck("IBM865" , - new String[] { - "cp865", // JDK historical - "ibm865", - "ibm-865", - "865", - "csIBM865" - } ); - - aliasCheck("IBM866" , new String[] { - "cp866", // JDK historical - "ibm866", - "ibm-866", - "866", - "csIBM866" - } ); - aliasCheck("IBM868" , - new String[] { - "cp868", // JDK historical - "ibm868", - "ibm-868", - "868", - "cp-ar", - "csIBM868" - } ); - - aliasCheck("IBM869" , - new String[] { - "cp869", // JDK historical - "ibm869", - "ibm-869", - "869", - "cp-gr", - "csIBM869" - } ); - - aliasCheck("IBM437" , - new String[] { - "cp437", // JDK historical - "ibm437", - "ibm-437", - "437", - "cspc8codepage437", - "windows-437" - } ); - - aliasCheck("x-IBM874" , - new String[] { - "cp874", // JDK historical - "ibm874", - "ibm-874", - "874" - } ); - aliasCheck("x-IBM737" , - new String[] { - "cp737", // JDK historical - "ibm737", - "ibm-737", - "737" - } ); - - aliasCheck("IBM775" , - new String[] { - "cp775", // JDK historical - "ibm775", - "ibm-775", - "775" - } ); - - aliasCheck("x-IBM921" , - new String[] { - "cp921", // JDK historical - "ibm921", - "ibm-921", - "921" - } ); - - aliasCheck("x-IBM1006" , - new String[] { - "cp1006", // JDK historical - "ibm1006", - "ibm-1006", - "1006" - } ); - - aliasCheck("x-IBM1046" , - new String[] { - "cp1046", // JDK historical - "ibm1046", - "ibm-1046", - "1046" - } ); - - aliasCheck("IBM1047" , - new String[] { - "cp1047", // JDK historical - "ibm-1047", - "1047" - } ); - - aliasCheck("x-IBM1098" , - new String[] { - "cp1098", // JDK historical - "ibm1098", - "ibm-1098", - "1098", - } ); - - aliasCheck("IBM037" , - new String[] { - "cp037", // JDK historical - "ibm037", - "csIBM037", - "cs-ebcdic-cp-us", - "cs-ebcdic-cp-ca", - "cs-ebcdic-cp-wt", - "cs-ebcdic-cp-nl", - "ibm-037", - "ibm-37", - "cpibm37", - "037" - } ); - - aliasCheck("x-IBM1025" , - new String[] { - "cp1025", // JDK historical - "ibm1025", - "ibm-1025", - "1025" - } ); - - aliasCheck("IBM1026" , - new String[] { - "cp1026", // JDK historical - "ibm1026", - "ibm-1026", - "1026" - } ); - - aliasCheck("x-IBM1112" , - new String[] { - "cp1112", // JDK historical - "ibm1112", - "ibm-1112", - "1112" - } ); - - aliasCheck("x-IBM1122" , - new String[] { - "cp1122", // JDK historical - "ibm1122", - "ibm-1122", - "1122" - } ); - - aliasCheck("x-IBM1123" , - new String[] { - "cp1123", // JDK historical - "ibm1123", - "ibm-1123", - "1123" - } ); - - aliasCheck("x-IBM1124" , - new String[] { - "cp1124", // JDK historical - "ibm1124", - "ibm-1124", - "1124" - } ); - - aliasCheck("x-IBM1129" , - new String[] { - "cp1129", // JDK historical - "ibm1129", - "ibm-1129", - "1129" - } ); - - aliasCheck("x-IBM1166" , - new String[] { - "cp1166", // JDK historical - "ibm1166", - "ibm-1166", - "1166" - } ); - - aliasCheck("IBM273" , - new String[] { - "cp273", // JDK historical - "ibm273", - "ibm-273", - "273" - } ); - - aliasCheck("IBM277" , - new String[] { - "cp277", // JDK historical - "ibm277", - "ibm-277", - "277" - } ); - - aliasCheck("IBM278" , - new String[] { - "cp278", // JDK historical - "ibm278", - "ibm-278", - "278", - "ebcdic-sv", - "ebcdic-cp-se", - "csIBM278" - } ); - - aliasCheck("IBM280" , - new String[] { - "cp280", // JDK historical - "ibm280", - "ibm-280", - "280" - } ); - - aliasCheck("IBM284" , - new String[] { - "cp284", // JDK historical - "ibm284", - "ibm-284", - "284", - "csIBM284", - "cpibm284" - } ); - - aliasCheck("IBM285" , - new String[] { - "cp285", // JDK historical - "ibm285", - "ibm-285", - "285", - "ebcdic-cp-gb", - "ebcdic-gb", - "csIBM285", - "cpibm285" - } ); - - aliasCheck("IBM297" , - new String[] { - "cp297", // JDK historical - "ibm297", - "ibm-297", - "297", - "ebcdic-cp-fr", - "cpibm297", - "csIBM297", - } ); - - aliasCheck("IBM420" , - new String[] { - "cp420", // JDK historical - "ibm420", - "ibm-420", - "ebcdic-cp-ar1", - "420", - "csIBM420" - } ); - - aliasCheck("IBM424" , - new String[] { - "cp424", // JDK historical - "ibm424", - "ibm-424", - "424", - "ebcdic-cp-he", - "csIBM424" - } ); - - aliasCheck("IBM500" , - new String[] { - "cp500", // JDK historical - "ibm500", - "ibm-500", - "500", - "ebcdic-cp-ch", - "ebcdic-cp-bh", - "csIBM500" - } ); - - aliasCheck("IBM-Thai" , - new String[] { - "cp838", // JDK historical - "ibm838", - "ibm-838", - "ibm838", - "838" - } ); - - aliasCheck("IBM870" , - new String[] { - "cp870", // JDK historical - "ibm870", - "ibm-870", - "870", - "ebcdic-cp-roece", - "ebcdic-cp-yu", - "csIBM870" - } ); - - aliasCheck("IBM871" , - new String[] { - "cp871", // JDK historical - "ibm871", - "ibm-871", - "871", - "ebcdic-cp-is", - "csIBM871" - } ); - - aliasCheck("x-IBM875" , - new String[] { - "cp875", // JDK historical - "ibm875", - "ibm-875", - "875" - } ); - - aliasCheck("IBM918" , - new String[] { - "cp918", // JDK historical - "ibm-918", - "918", - "ebcdic-cp-ar2" - } ); - - aliasCheck("x-IBM922" , - new String[] { - "cp922", // JDK historical - "ibm922", - "ibm-922", - "922" - } ); - - aliasCheck("x-IBM1097" , - new String[] { - "cp1097", // JDK historical - "ibm1097", - "ibm-1097", - "1097" - } ); - - aliasCheck("x-IBM949" , - new String[] { - "cp949", // JDK historical - "ibm949", - "ibm-949", - "949" - } ); - - aliasCheck("x-IBM949C" , - new String[] { - "cp949C", // JDK historical - "ibm949C", - "ibm-949C", - "949C" - } ); - - aliasCheck("x-IBM939" , - new String[] { - "cp939", // JDK historical - "ibm939", - "ibm-939", - "939" - } ); - - aliasCheck("x-IBM933" , - new String[] { - "cp933", // JDK historical - "ibm933", - "ibm-933", - "933" - } ); - - aliasCheck("x-IBM1381" , - new String[] { - "cp1381", // JDK historical - "ibm1381", - "ibm-1381", - "1381" - } ); - - aliasCheck("x-IBM1383" , - new String[] { - "cp1383", // JDK historical - "ibm1383", - "ibm-1383", - "1383" - } ); - - aliasCheck("x-IBM970" , - new String[] { - "cp970", // JDK historical - "ibm970", - "ibm-970", - "ibm-eucKR", - "970" - } ); - - aliasCheck("x-IBM964" , - new String[] { - "cp964", // JDK historical - "ibm964", - "ibm-964", - "964" - } ); - - aliasCheck("x-IBM33722" , - new String[] { - "cp33722", // JDK historical - "ibm33722", - "ibm-33722", - "ibm-5050", // from IBM alias list - "ibm-33722_vascii_vpua", // from IBM alias list - "33722" - } ); - - aliasCheck("IBM01140" , - new String[] { - "cp1140", // JDK historical - "ccsid01140", - "cp01140", - // "ebcdic-us-037+euro" - } ); - - aliasCheck("IBM01141" , - new String[] { - "cp1141", // JDK historical - "ccsid01141", - "cp01141", - // "ebcdic-de-273+euro" - } ); - - aliasCheck("IBM01142" , - new String[] { - "cp1142", // JDK historical - "ccsid01142", - "cp01142", - // "ebcdic-no-277+euro", - // "ebcdic-dk-277+euro" - } ); - - aliasCheck("IBM01143" , - new String[] { - "cp1143", // JDK historical - "ccsid01143", - "cp01143", - // "ebcdic-fi-278+euro", - // "ebcdic-se-278+euro" - } ); - - aliasCheck("IBM01144" , - new String[] { - "cp1144", // JDK historical - "ccsid01144", - "cp01144", - // "ebcdic-it-280+euro" - } ); - - aliasCheck("IBM01145" , - new String[] { - "cp1145", // JDK historical - "ccsid01145", - "cp01145", - // "ebcdic-es-284+euro" - } ); - - aliasCheck("IBM01146" , - new String[] { - "cp1146", // JDK historical - "ccsid01146", - "cp01146", - // "ebcdic-gb-285+euro" - } ); - - aliasCheck("IBM01147" , - new String[] { - "cp1147", // JDK historical - "ccsid01147", - "cp01147", - // "ebcdic-fr-277+euro" - } ); - - aliasCheck("IBM01148" , - new String[] { - "cp1148", // JDK historical - "ccsid01148", - "cp01148", - // "ebcdic-international-500+euro" - } ); - - aliasCheck("IBM01149" , - new String[] { - "cp1149", // JDK historical - "ccsid01149", - "cp01149", - // "ebcdic-s-871+euro" - } ); - - aliasCheck("IBM00858" , - new String[] { - "cp858", // JDK historical - "ccsid00858", - "cp00858", - // "PC-Multilingual-850+euro" - } ); - - aliasCheck("x-MacRoman", - new String[] { - "MacRoman" // JDK historical - }); - - aliasCheck("x-MacCentralEurope", - new String[] { - "MacCentralEurope" // JDK historical - }); - - aliasCheck("x-MacCroatian", - new String[] { - "MacCroatian" // JDK historical - }); - - - aliasCheck("x-MacCroatian", - new String[] { - "MacCroatian" // JDK historical - }); - - - aliasCheck("x-MacGreek", - new String[] { - "MacGreek" // JDK historical - }); - - aliasCheck("x-MacCyrillic", - new String[] { - "MacCyrillic" // JDK historical - }); - - aliasCheck("x-MacUkraine", - new String[] { - "MacUkraine" // JDK historical - }); - - aliasCheck("x-MacTurkish", - new String[] { - "MacTurkish" // JDK historical - }); - - aliasCheck("x-MacArabic", - new String[] { - "MacArabic" // JDK historical - }); - - aliasCheck("x-MacHebrew", - new String[] { - "MacHebrew" // JDK historical - }); - - aliasCheck("x-MacIceland", - new String[] { - "MacIceland" // JDK historical - }); - - aliasCheck("x-MacRomania", - new String[] { - "MacRomania" // JDK historical - }); - - aliasCheck("x-MacThai", - new String[] { - "MacThai" // JDK historical - }); - - aliasCheck("x-MacSymbol", - new String[] { - "MacSymbol" // JDK historical - }); - - aliasCheck("x-MacDingbat", - new String[] { - "MacDingbat" // JDK historical - }); - - // Check UnsupportedCharsetException is thrown for the name "default" - try { - Charset.forName("default"); - throw new RuntimeException("UnsupportedCharsetException was not thrown for Charset.forName(\"default\")"); - } catch (UnsupportedCharsetException uce) { - // success - } + return Stream.of( + Arguments.of("US-ASCII", + new String[] {"ascii","ANSI_X3.4-1968", + "iso-ir-6","ANSI_X3.4-1986", "ISO_646.irv:1991", + "ASCII", "ISO646-US","us","IBM367","cp367", + "csASCII"}), + + Arguments.of("UTF-8", + new String[] { + "UTF8", + "unicode-1-1-utf-8" + }), + + Arguments.of("UTF-16", + new String[] { + "UTF_16", + "utf16" + }), + + Arguments.of("UTF-16BE", + new String[] { + "UTF_16BE", + "ISO-10646-UCS-2", + "X-UTF-16BE", + "UnicodeBigUnmarked" + }), + + Arguments.of("UTF-16LE", + new String[] { + "UTF_16LE", + "X-UTF-16LE", + "UnicodeLittleUnmarked" + }), + + Arguments.of("Big5", + new String[] { + "csBig5" + }), + + Arguments.of("Big5-HKSCS", + new String[] { + "Big5_HKSCS", + "big5hk", + "big5-hkscs", + "big5hkscs" + }), + + Arguments.of("x-MS950-HKSCS", + new String[] { + "MS950_HKSCS" + }), + + Arguments.of("GB18030", + "2000".equals(System.getProperty("jdk.charset.GB18030")) ? + new String[] { + "gb18030-2000" + } : + new String[] { + "gb18030-2022" + }), + + Arguments.of("ISO-2022-KR", new String[] {"csISO2022KR"}), + Arguments.of("ISO-2022-JP", new String[] {"csISO2022JP"}), + Arguments.of("EUC-KR", new String[] { "csEUCKR"}), + Arguments.of("ISO-8859-1", + new String[] { + + // IANA aliases + "iso-ir-100", + "ISO_8859-1", + "latin1", + "l1", + "IBM819", + "cp819", + "csISOLatin1", + + // JDK historical aliases + "819", + "IBM-819", + "ISO8859_1", + "ISO_8859-1:1987", + "ISO_8859_1", + "8859_1", + "ISO8859-1", + + }), + + Arguments.of("ISO-8859-2", + new String[] { + "ISO_8859-2", + "ISO_8859-2:1987", + "iso-ir-101", + "latin2", + "l2", + "8859_2", + "iso_8859-2:1987", + "iso8859-2", + "ibm912", + "ibm-912", + "cp912", + "912", + "csISOLatin2"}), + + Arguments.of("ISO-8859-3", + new String[] {"latin3", + "ISO_8859-3:1988", + "iso-ir-109", + "l3", + "8859_3", + "iso_8859-3:1988", + "iso8859-3", + "ibm913", + "ibm-913", + "cp913", + "913", + "csISOLatin3"}), + + Arguments.of("ISO-8859-4", + new String[] {"csISOLatin4", + "ISO_8859-4:1988", + "iso-ir-110", + "latin4", + "8859_4", + "iso_8859-4:1988", + "iso8859-4", + "ibm914", + "ibm-914", + "cp914", + "914", + "l4"}), + + Arguments.of("ISO-8859-5", + new String[] { + "iso8859_5", // JDK historical + "8859_5", + "iso-ir-144", + "ISO_8859-5", + "ISO_8859-5:1988", + "ISO8859-5", + "cyrillic", + "ibm915", + "ibm-915", + "915", + "cp915", + "csISOLatinCyrillic" + }), + + Arguments.of("ISO-8859-6", + new String[] {"ISO_8859-6:1987", + "iso-ir-127", + "ISO_8859-6", + "ECMA-114", + "ASMO-708", + "arabic", + "8859_6", + "iso_8859-6:1987", + "iso8859-6", + "ibm1089", + "ibm-1089", + "cp1089", + "1089", + "csISOLatinArabic"}), + + Arguments.of("ISO-8859-7", + new String[] {"ISO_8859-7:1987", + "iso-ir-126", + "ISO_8859-7", + "ELOT_928", + "ECMA-118", + "greek", + "greek8", + "8859_7", + "iso_8859-7:1987", + "iso8859-7", + "ibm813", + "ibm-813", + "cp813", + "813", + "csISOLatinGreek"}), + + Arguments.of("ISO-8859-8", + new String[] { + "ISO_8859-8:1988", + "iso-ir-138", + "ISO_8859-8", + "hebrew", + "8859_8", + "iso_8859-8:1988", + "iso8859-8", + "ibm916", + "ibm-916", + "cp916", + "916", + "csISOLatinHebrew"}), + + Arguments.of("ISO-8859-9", + new String[] {"ISO_8859-9:1989", + "iso-ir-148", + "ISO_8859-9", + "latin5", + "l5", + "8859_9", + "iso8859-9", + "ibm920", + "ibm-920", + "cp920", + "920", + "csISOLatin5"}), + + Arguments.of("ISO-8859-13", + new String[] { + "iso8859_13", // JDK historical + "iso_8859-13", + "8859_13", + "ISO8859-13" + }), + + Arguments.of("ISO-8859-15", + new String[] { + // IANA alias + "ISO_8859-15", + "Latin-9", + "csISO885915", + // JDK historical aliases + "8859_15", + "ISO-8859-15", + "ISO_8859-15", + "ISO8859-15", + "ISO8859_15", + "IBM923", + "IBM-923", + "cp923", + "923", + "LATIN0", + "LATIN9", + "L9", + "csISOlatin0", + "csISOlatin9", + "ISO8859_15_FDIS" + }), + + Arguments.of("ISO-8859-16", + new String[] { + "iso-ir-226", + "ISO_8859-16:2001", + "ISO_8859-16", + "ISO8859_16", + "latin10", + "l10", + "csISO885916" + }), + + Arguments.of("JIS_X0212-1990", + new String[] { + "iso-ir-159", + "csISO159JISX02121990"}), + + Arguments.of("JIS_X0201", + new String[]{ + "X0201", + "csHalfWidthKatakana"}), + + Arguments.of("KOI8-R", + new String[] { + "KOI8_R", + "csKOI8R"}), + + Arguments.of("GBK", + new String[] { + "windows-936"}), + + Arguments.of("Shift_JIS", + new String[] { + "MS_Kanji", + "csShiftJIS"}), + + Arguments.of("EUC-JP", + new String[] { + "Extended_UNIX_Code_Packed_Format_for_Japanese", + "csEUCPkdFmtJapanese"}), + + Arguments.of("Big5", new String[] {"csBig5"}), + + Arguments.of("windows-31j", new String[] {"csWindows31J"}), + + Arguments.of("x-iso-8859-11", + new String[] { "iso-8859-11", "iso8859_11" }), + + Arguments.of("windows-1250", + new String[] { + "cp1250", + "cp5346" + }), + + Arguments.of("windows-1251", + new String[] { + "cp1251", + "cp5347", + "ansi-1251" + }), + + Arguments.of("windows-1252", + new String[] { + "cp1252", + "cp5348" + }), + + Arguments.of("windows-1253", + new String[] { + "cp1253", + "cp5349" + }), + + Arguments.of("windows-1254", + new String[] { + "cp1254", + "cp5350" + }), + + Arguments.of("windows-1255", + new String[] { + "cp1255" + }), + + Arguments.of("windows-1256", + new String[] { + "cp1256" + }), + + Arguments.of("windows-1257", + new String[] { + "cp1257", + "cp5353" + }), + + Arguments.of("windows-1258", + new String[] { + "cp1258" + }), + + Arguments.of("x-windows-874", + new String[] { + "ms874", "ms-874", "windows-874" }), + + Arguments.of("GB2312", + new String[] { + "x-EUC-CN", + "gb2312-80", + "gb2312-1980", + "euc-cn", + "euccn" }), + + Arguments.of("x-IBM942" , + new String[] { + "cp942", // JDK historical + "ibm942", + "ibm-942", + "942" + }), + + Arguments.of("x-IBM942C" , + new String[] { + "cp942C", // JDK historical + "ibm942C", + "ibm-942C", + "942C" + } ), + + Arguments.of("x-IBM943" , + new String[] { + "cp943", // JDK historical + "ibm943", + "ibm-943", + "943" + } ), + + Arguments.of("x-IBM943C" , + new String[] { + "cp943c", // JDK historical + "ibm943C", + "ibm-943C", + "943C" + } ), + + Arguments.of("x-IBM948" , + new String[] { + "cp948", // JDK historical + "ibm948", + "ibm-948", + "948" + } ), + + Arguments.of("x-IBM950" , + new String[] { + "cp950", // JDK historical + "ibm950", + "ibm-950", + "950" + } ), + + Arguments.of("x-IBM930" , + new String[] { + "cp930", // JDK historical + "ibm930", + "ibm-930", + "930" + } ), + + Arguments.of("x-IBM935" , + new String[] { + "cp935", // JDK historical + "ibm935", + "ibm-935", + "935" + } ), + + Arguments.of("x-IBM937" , + new String[] { + "cp937", // JDK historical + "ibm937", + "ibm-937", + "937" + } ), + + Arguments.of("IBM850" , + new String[] { + "cp850", // JDK historical + "ibm-850", + "ibm850", + "850", + "cspc850multilingual" + } ), + + Arguments.of("IBM852" , + new String[] { + "cp852", // JDK historical + "ibm852", + "ibm-852", + "852", + "csPCp852" + } ), + + Arguments.of("IBM855" , + new String[] { + "cp855", // JDK historical + "ibm-855", + "ibm855", + "855", + "cspcp855" + } ), + + Arguments.of("x-IBM856" , + new String[] { + "cp856", // JDK historical + "ibm-856", + "ibm856", + "856" + } ), + + Arguments.of("IBM857" , + new String[] { + "cp857", // JDK historical + "ibm857", + "ibm-857", + "857", + "csIBM857" + } ), + + Arguments.of("IBM860" , + new String[] { + "cp860", // JDK historical + "ibm860", + "ibm-860", + "860", + "csIBM860" + } ), + Arguments.of("IBM861" , + new String[] { + "cp861", // JDK historical + "ibm861", + "ibm-861", + "861", + "csIBM861" + } ), + + Arguments.of("IBM862" , + new String[] { + "cp862", // JDK historical + "ibm862", + "ibm-862", + "862", + "csIBM862" + } ), + + Arguments.of("IBM863" , + new String[] { + "cp863", // JDK historical + "ibm863", + "ibm-863", + "863", + "csIBM863" + } ), + + Arguments.of("IBM864" , + new String[] { + "cp864", // JDK historical + "ibm864", + "ibm-864", + "864", + "csIBM864" + } ), + + Arguments.of("IBM865" , + new String[] { + "cp865", // JDK historical + "ibm865", + "ibm-865", + "865", + "csIBM865" + } ), + + Arguments.of("IBM866" , new String[] { + "cp866", // JDK historical + "ibm866", + "ibm-866", + "866", + "csIBM866" + } ), + Arguments.of("IBM868" , + new String[] { + "cp868", // JDK historical + "ibm868", + "ibm-868", + "868", + "cp-ar", + "csIBM868" + } ), + + Arguments.of("IBM869" , + new String[] { + "cp869", // JDK historical + "ibm869", + "ibm-869", + "869", + "cp-gr", + "csIBM869" + } ), + + Arguments.of("IBM437" , + new String[] { + "cp437", // JDK historical + "ibm437", + "ibm-437", + "437", + "cspc8codepage437", + "windows-437" + } ), + + Arguments.of("x-IBM874" , + new String[] { + "cp874", // JDK historical + "ibm874", + "ibm-874", + "874" + } ), + Arguments.of("x-IBM737" , + new String[] { + "cp737", // JDK historical + "ibm737", + "ibm-737", + "737" + } ), + + Arguments.of("IBM775" , + new String[] { + "cp775", // JDK historical + "ibm775", + "ibm-775", + "775" + } ), + + Arguments.of("x-IBM921" , + new String[] { + "cp921", // JDK historical + "ibm921", + "ibm-921", + "921" + } ), + + Arguments.of("x-IBM1006" , + new String[] { + "cp1006", // JDK historical + "ibm1006", + "ibm-1006", + "1006" + } ), + + Arguments.of("x-IBM1046" , + new String[] { + "cp1046", // JDK historical + "ibm1046", + "ibm-1046", + "1046" + } ), + + Arguments.of("IBM1047" , + new String[] { + "cp1047", // JDK historical + "ibm-1047", + "1047" + } ), + + Arguments.of("x-IBM1098" , + new String[] { + "cp1098", // JDK historical + "ibm1098", + "ibm-1098", + "1098", + } ), + + Arguments.of("IBM037" , + new String[] { + "cp037", // JDK historical + "ibm037", + "csIBM037", + "cs-ebcdic-cp-us", + "cs-ebcdic-cp-ca", + "cs-ebcdic-cp-wt", + "cs-ebcdic-cp-nl", + "ibm-037", + "ibm-37", + "cpibm37", + "037" + } ), + + Arguments.of("x-IBM1025" , + new String[] { + "cp1025", // JDK historical + "ibm1025", + "ibm-1025", + "1025" + } ), + + Arguments.of("IBM1026" , + new String[] { + "cp1026", // JDK historical + "ibm1026", + "ibm-1026", + "1026" + } ), + + Arguments.of("x-IBM1112" , + new String[] { + "cp1112", // JDK historical + "ibm1112", + "ibm-1112", + "1112" + } ), + + Arguments.of("x-IBM1122" , + new String[] { + "cp1122", // JDK historical + "ibm1122", + "ibm-1122", + "1122" + } ), + + Arguments.of("x-IBM1123" , + new String[] { + "cp1123", // JDK historical + "ibm1123", + "ibm-1123", + "1123" + } ), + + Arguments.of("x-IBM1124" , + new String[] { + "cp1124", // JDK historical + "ibm1124", + "ibm-1124", + "1124" + } ), + + Arguments.of("x-IBM1129" , + new String[] { + "cp1129", // JDK historical + "ibm1129", + "ibm-1129", + "1129" + } ), + + Arguments.of("x-IBM1166" , + new String[] { + "cp1166", // JDK historical + "ibm1166", + "ibm-1166", + "1166" + } ), + + Arguments.of("IBM273" , + new String[] { + "cp273", // JDK historical + "ibm273", + "ibm-273", + "273" + } ), + + Arguments.of("IBM277" , + new String[] { + "cp277", // JDK historical + "ibm277", + "ibm-277", + "277" + } ), + + Arguments.of("IBM278" , + new String[] { + "cp278", // JDK historical + "ibm278", + "ibm-278", + "278", + "ebcdic-sv", + "ebcdic-cp-se", + "csIBM278" + } ), + + Arguments.of("IBM280" , + new String[] { + "cp280", // JDK historical + "ibm280", + "ibm-280", + "280" + } ), + + Arguments.of("IBM284" , + new String[] { + "cp284", // JDK historical + "ibm284", + "ibm-284", + "284", + "csIBM284", + "cpibm284" + } ), + + Arguments.of("IBM285" , + new String[] { + "cp285", // JDK historical + "ibm285", + "ibm-285", + "285", + "ebcdic-cp-gb", + "ebcdic-gb", + "csIBM285", + "cpibm285" + } ), + + Arguments.of("IBM297" , + new String[] { + "cp297", // JDK historical + "ibm297", + "ibm-297", + "297", + "ebcdic-cp-fr", + "cpibm297", + "csIBM297", + } ), + + Arguments.of("IBM420" , + new String[] { + "cp420", // JDK historical + "ibm420", + "ibm-420", + "ebcdic-cp-ar1", + "420", + "csIBM420" + } ), + + Arguments.of("IBM424" , + new String[] { + "cp424", // JDK historical + "ibm424", + "ibm-424", + "424", + "ebcdic-cp-he", + "csIBM424" + } ), + + Arguments.of("IBM500" , + new String[] { + "cp500", // JDK historical + "ibm500", + "ibm-500", + "500", + "ebcdic-cp-ch", + "ebcdic-cp-bh", + "csIBM500" + } ), + + Arguments.of("IBM-Thai" , + new String[] { + "cp838", // JDK historical + "ibm838", + "ibm-838", + "ibm838", + "838" + } ), + + Arguments.of("IBM870" , + new String[] { + "cp870", // JDK historical + "ibm870", + "ibm-870", + "870", + "ebcdic-cp-roece", + "ebcdic-cp-yu", + "csIBM870" + } ), + + Arguments.of("IBM871" , + new String[] { + "cp871", // JDK historical + "ibm871", + "ibm-871", + "871", + "ebcdic-cp-is", + "csIBM871" + } ), + + Arguments.of("x-IBM875" , + new String[] { + "cp875", // JDK historical + "ibm875", + "ibm-875", + "875" + } ), + + Arguments.of("IBM918" , + new String[] { + "cp918", // JDK historical + "ibm-918", + "918", + "ebcdic-cp-ar2" + } ), + + Arguments.of("x-IBM922" , + new String[] { + "cp922", // JDK historical + "ibm922", + "ibm-922", + "922" + } ), + + Arguments.of("x-IBM1097" , + new String[] { + "cp1097", // JDK historical + "ibm1097", + "ibm-1097", + "1097" + } ), + + Arguments.of("x-IBM949" , + new String[] { + "cp949", // JDK historical + "ibm949", + "ibm-949", + "949" + } ), + + Arguments.of("x-IBM949C" , + new String[] { + "cp949C", // JDK historical + "ibm949C", + "ibm-949C", + "949C" + } ), + + Arguments.of("x-IBM939" , + new String[] { + "cp939", // JDK historical + "ibm939", + "ibm-939", + "939" + } ), + + Arguments.of("x-IBM933" , + new String[] { + "cp933", // JDK historical + "ibm933", + "ibm-933", + "933" + } ), + + Arguments.of("x-IBM1381" , + new String[] { + "cp1381", // JDK historical + "ibm1381", + "ibm-1381", + "1381" + } ), + + Arguments.of("x-IBM1383" , + new String[] { + "cp1383", // JDK historical + "ibm1383", + "ibm-1383", + "1383" + } ), + + Arguments.of("x-IBM970" , + new String[] { + "cp970", // JDK historical + "ibm970", + "ibm-970", + "ibm-eucKR", + "970" + } ), + + Arguments.of("x-IBM964" , + new String[] { + "cp964", // JDK historical + "ibm964", + "ibm-964", + "964" + } ), + + Arguments.of("x-IBM33722" , + new String[] { + "cp33722", // JDK historical + "ibm33722", + "ibm-33722", + "ibm-5050", // from IBM alias list + "ibm-33722_vascii_vpua", // from IBM alias list + "33722" + } ), + + Arguments.of("IBM01140" , + new String[] { + "cp1140", // JDK historical + "ccsid01140", + "cp01140", + // "ebcdic-us-037+euro" + } ), + + Arguments.of("IBM01141" , + new String[] { + "cp1141", // JDK historical + "ccsid01141", + "cp01141", + // "ebcdic-de-273+euro" + } ), + + Arguments.of("IBM01142" , + new String[] { + "cp1142", // JDK historical + "ccsid01142", + "cp01142", + // "ebcdic-no-277+euro", + // "ebcdic-dk-277+euro" + } ), + + Arguments.of("IBM01143" , + new String[] { + "cp1143", // JDK historical + "ccsid01143", + "cp01143", + // "ebcdic-fi-278+euro", + // "ebcdic-se-278+euro" + } ), + + Arguments.of("IBM01144" , + new String[] { + "cp1144", // JDK historical + "ccsid01144", + "cp01144", + // "ebcdic-it-280+euro" + } ), + + Arguments.of("IBM01145" , + new String[] { + "cp1145", // JDK historical + "ccsid01145", + "cp01145", + // "ebcdic-es-284+euro" + } ), + + Arguments.of("IBM01146" , + new String[] { + "cp1146", // JDK historical + "ccsid01146", + "cp01146", + // "ebcdic-gb-285+euro" + } ), + + Arguments.of("IBM01147" , + new String[] { + "cp1147", // JDK historical + "ccsid01147", + "cp01147", + // "ebcdic-fr-277+euro" + } ), + + Arguments.of("IBM01148" , + new String[] { + "cp1148", // JDK historical + "ccsid01148", + "cp01148", + // "ebcdic-international-500+euro" + } ), + + Arguments.of("IBM01149" , + new String[] { + "cp1149", // JDK historical + "ccsid01149", + "cp01149", + // "ebcdic-s-871+euro" + } ), + + Arguments.of("IBM00858" , + new String[] { + "cp858", // JDK historical + "ccsid00858", + "cp00858", + // "PC-Multilingual-850+euro" + } ), + + Arguments.of("x-MacRoman", + new String[] { + "MacRoman" // JDK historical + }), + + Arguments.of("x-MacCentralEurope", + new String[] { + "MacCentralEurope" // JDK historical + }), + + Arguments.of("x-MacCroatian", + new String[] { + "MacCroatian" // JDK historical + }), + + + Arguments.of("x-MacCroatian", + new String[] { + "MacCroatian" // JDK historical + }), + + + Arguments.of("x-MacGreek", + new String[] { + "MacGreek" // JDK historical + }), + + Arguments.of("x-MacCyrillic", + new String[] { + "MacCyrillic" // JDK historical + }), + + Arguments.of("x-MacUkraine", + new String[] { + "MacUkraine" // JDK historical + }), + + Arguments.of("x-MacTurkish", + new String[] { + "MacTurkish" // JDK historical + }), + + Arguments.of("x-MacArabic", + new String[] { + "MacArabic" // JDK historical + }), + + Arguments.of("x-MacHebrew", + new String[] { + "MacHebrew" // JDK historical + }), + + Arguments.of("x-MacIceland", + new String[] { + "MacIceland" // JDK historical + }), + + Arguments.of("x-MacRomania", + new String[] { + "MacRomania" // JDK historical + }), + + Arguments.of("x-MacThai", + new String[] { + "MacThai" // JDK historical + }), + + Arguments.of("x-MacSymbol", + new String[] { + "MacSymbol" // JDK historical + }), + + Arguments.of("x-MacDingbat", + new String[] { + "MacDingbat" // JDK historical + }) + ); } } diff --git a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java index 2370dcd35c4..4de6598a0f4 100644 --- a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java +++ b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,12 +54,11 @@ import java.rmi.*; import java.rmi.server.*; -import sun.rmi.transport.*; -import sun.rmi.*; import java.util.Map; import java.io.*; import java.lang.reflect.*; import java.rmi.registry.*; +import sun.rmi.transport.*; public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak { public CheckLeaseLeak() throws RemoteException { } @@ -102,8 +101,6 @@ public static void main (String[] args) { System.err.println("Created client: " + i); JavaVM jvm = new JavaVM("LeaseLeakClient", - " -Djava.security.policy=" + - TestParams.defaultPolicy + " -Drmi.registry.port=" + registryPort, ""); @@ -128,8 +125,8 @@ public static void main (String[] args) { } } - /* numLeft should be 2 - if 11 there is a problem. */ - if (numLeft > 2) { + /* numLeft should be 4 - if 11 there is a problem. */ + if (numLeft > 4) { TestLibrary.bomb("Too many objects in DGCImpl.leaseTable: "+ numLeft); } else { @@ -156,57 +153,51 @@ private static int getDGCLeaseTableSize () { Field f; try { - f = (Field) java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public Object run() throws Exception { - - ObjID dgcID = new ObjID(DGC_ID); - - /* - * Construct an ObjectEndpoint containing DGC's - * ObjID. - */ - Class oeClass = - Class.forName("sun.rmi.transport.ObjectEndpoint"); - Class[] constrParams = - new Class[]{ ObjID.class, Transport.class }; - Constructor oeConstructor = - oeClass.getDeclaredConstructor(constrParams); - oeConstructor.setAccessible(true); - Object oe = - oeConstructor.newInstance( - new Object[]{ dgcID, null }); - - /* - * Get Target that contains DGCImpl in ObjectTable - */ - Class objTableClass = - Class.forName("sun.rmi.transport.ObjectTable"); - Class getTargetParams[] = new Class[] { oeClass }; - Method objTableGetTarget = - objTableClass.getDeclaredMethod("getTarget", - getTargetParams); - objTableGetTarget.setAccessible(true); - Target dgcTarget = (Target) - objTableGetTarget.invoke(null, new Object[]{ oe }); - - /* get the DGCImpl from its Target */ - Method targetGetImpl = - dgcTarget.getClass().getDeclaredMethod + ObjID dgcID = new ObjID(DGC_ID); + /* + * Construct an ObjectEndpoint containing DGC's + * ObjID. + */ + Class oeClass = + Class.forName("sun.rmi.transport.ObjectEndpoint"); + Class[] constrParams = + new Class[]{ ObjID.class, Transport.class }; + Constructor oeConstructor = + oeClass.getDeclaredConstructor(constrParams); + oeConstructor.setAccessible(true); + Object oe = + oeConstructor.newInstance( + new Object[]{ dgcID, null }); + + /* + * Get Target that contains DGCImpl in ObjectTable + */ + Class objTableClass = + Class.forName("sun.rmi.transport.ObjectTable"); + Class getTargetParams[] = new Class[] { oeClass }; + Method objTableGetTarget = + objTableClass.getDeclaredMethod("getTarget", + getTargetParams); + objTableGetTarget.setAccessible(true); + Target dgcTarget = (Target) + objTableGetTarget.invoke(null, new Object[]{ oe }); + + /* get the DGCImpl from its Target */ + Method targetGetImpl = + dgcTarget.getClass().getDeclaredMethod ("getImpl", null); - targetGetImpl.setAccessible(true); - dgcImpl[0] = - (Remote) targetGetImpl.invoke(dgcTarget, null); + targetGetImpl.setAccessible(true); + dgcImpl[0] = + (Remote) targetGetImpl.invoke(dgcTarget, null); - /* Get the lease table from the DGCImpl. */ - Field reflectedLeaseTable = - dgcImpl[0].getClass().getDeclaredField + /* Get the lease table from the DGCImpl. */ + Field reflectedLeaseTable = + dgcImpl[0].getClass().getDeclaredField ("leaseTable"); - reflectedLeaseTable.setAccessible(true); + reflectedLeaseTable.setAccessible(true); + + f = reflectedLeaseTable; - return reflectedLeaseTable; - } - }); /** * This is the leaseTable that will fill up with LeaseInfo @@ -217,9 +208,6 @@ public Object run() throws Exception { numLeaseInfosLeft = leaseTable.size(); } catch(Exception e) { - if (e instanceof java.security.PrivilegedActionException) - e = ((java.security.PrivilegedActionException) e). - getException(); TestLibrary.bomb(e); } diff --git a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java index d9cf9fa9e96..dd24b819146 100644 --- a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java +++ b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ public class LeaseLeakClient { public static void main(String args[]) { - TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager"); try { LeaseLeak leaseLeak = null; diff --git a/test/jdk/java/security/Security/SecurityPropFile/TEST.properties b/test/jdk/java/security/Security/SecurityPropFile/TEST.properties deleted file mode 100644 index 908b451f8ea..00000000000 --- a/test/jdk/java/security/Security/SecurityPropFile/TEST.properties +++ /dev/null @@ -1,2 +0,0 @@ -# disabled till JDK-8219408 is fixed -allowSmartActionArgs=false diff --git a/test/jdk/java/text/Format/ChoiceFormat/ParseTest.java b/test/jdk/java/text/Format/ChoiceFormat/ParseTest.java new file mode 100644 index 00000000000..17ead8f450c --- /dev/null +++ b/test/jdk/java/text/Format/ChoiceFormat/ParseTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8353585 + * @summary Basic parse tests. Enforce regular behavior, no match, and multi match. + * @run junit ParseTest + */ + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.text.ChoiceFormat; +import java.text.ParsePosition; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ParseTest { + + // Ensure that the parsed text produces the expected number + // i.e. return limit corresponding to format matched + @ParameterizedTest + @MethodSource + void parseTest(String pattern, String text, Double expected, int index) { + var pp = new ParsePosition(index); + var fmt = new ChoiceFormat(pattern); + assertEquals(expected, fmt.parse(text, pp), "Incorrect limit returned"); + if (expected.equals(Double.NaN)) { // AKA failed parse + assertEquals(index, pp.getErrorIndex(), + "Failed parse produced incorrect error index"); + } else { + assertEquals(-1, pp.getErrorIndex(), + "Error index should remain -1 on match"); + } + } + + private static Stream parseTest() { + return Stream.of( + Arguments.of("1#foo", "foo", Double.NaN, -1), + Arguments.of("1#baz", "foo bar baz", Double.NaN, 20), + Arguments.of("1#baz", "foo bar baz", 1d, 8), + Arguments.of("1#baz", "foo baz quux", Double.NaN, 8), + Arguments.of("1#a", "", Double.NaN, 0), + Arguments.of("1#a", "a", 1d, 0), + Arguments.of("1# ", " ", 1d, 0), + Arguments.of("1#a|2#a", "a", 1d, 0), + Arguments.of("1#a|2#aa", "aa", 2d, 0), + Arguments.of("1#a|2#aa", "aabb", 2d, 0), + Arguments.of("1#a|2#aa", "bbaa", Double.NaN, 0), + Arguments.of("1#aa|2#aaa", "a", Double.NaN, 0) + ); + } +} diff --git a/test/jdk/java/text/Format/DateFormat/DateFormatRegression.java b/test/jdk/java/text/Format/DateFormat/DateFormatRegression.java index a1851908ca9..7d8b2551c35 100644 --- a/test/jdk/java/text/Format/DateFormat/DateFormatRegression.java +++ b/test/jdk/java/text/Format/DateFormat/DateFormatRegression.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * 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,7 +34,7 @@ * @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 8305853 + * 4213086 4250359 4253490 4266432 4406615 4413980 8008577 8305853 8347841 * @library /java/text/testlib * @run junit/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRegression */ @@ -274,7 +274,7 @@ public void Test4065240() { try { Locale curLocale = Locale.GERMANY; Locale.setDefault(curLocale); - TimeZone.setDefault(TimeZone.getTimeZone("EST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Panama")); curDate = new Date(98, 0, 1); shortdate = DateFormat.getDateInstance(DateFormat.SHORT); fulldate = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG @@ -453,7 +453,7 @@ public void Test4413980() { TimeZone savedTimeZone = TimeZone.getDefault(); try { boolean pass = true; - String[] IDs = new String[] {"Undefined", "PST", "US/Pacific", + String[] IDs = new String[] {"Undefined", "America/Los_Angeles", "US/Pacific", "GMT+3:00", "GMT-01:30"}; for (int i = 0; i < IDs.length; i++) { TimeZone tz = TimeZone.getTimeZone(IDs[i]); @@ -543,7 +543,7 @@ public void Test4103340() { public void Test4103341() { TimeZone saveZone =TimeZone.getDefault(); try { - TimeZone.setDefault(TimeZone.getTimeZone("CST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago")); SimpleDateFormat simple = new SimpleDateFormat("MM/dd/yyyy HH:mm"); if (!simple.getTimeZone().equals(TimeZone.getDefault())) fail("Fail: SimpleDateFormat not using default zone"); @@ -794,7 +794,7 @@ public void Test4406615() { Locale savedLocale = Locale.getDefault(); TimeZone savedTimeZone = TimeZone.getDefault(); Locale.setDefault(Locale.US); - TimeZone.setDefault(TimeZone.getTimeZone("PST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); Date d1, d2; String dt = "Mon, 1 Jan 2001 00:00:00"; @@ -1096,7 +1096,7 @@ public void Test4261506() { // 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")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); SimpleDateFormat fmt = new SimpleDateFormat("yy/MM/dd hh:ss zzz", Locale.JAPAN); @SuppressWarnings("deprecation") String result = fmt.format(new Date(1999 - 1900, 0, 1)); diff --git a/test/jdk/java/text/Format/DateFormat/DateFormatTest.java b/test/jdk/java/text/Format/DateFormat/DateFormatTest.java index 5f02c12e80d..4dd98323f68 100644 --- a/test/jdk/java/text/Format/DateFormat/DateFormatTest.java +++ b/test/jdk/java/text/Format/DateFormat/DateFormatTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * 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,14 +24,16 @@ /** * @test * @bug 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571 - * 8190748 8216969 + * 8190748 8216969 8347841 * @summary test DateFormat and SimpleDateFormat. * @modules jdk.localedata * @run junit/othervm -Djava.locale.providers=COMPAT,SPI DateFormatTest */ -import java.util.*; +import java.time.ZoneId; import java.text.*; +import java.util.*; +import java.util.function.Predicate; import static java.util.GregorianCalendar.*; import org.junit.jupiter.api.Test; @@ -89,7 +91,9 @@ public void TestWallyWedel() /* * A String array for the time zone ids. */ - String[] ids = TimeZone.getAvailableIDs(); + String[] ids = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); /* * How many ids do we have? */ @@ -179,7 +183,7 @@ public void TestTwoDigitYearDSTParse() //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"); + TimeZone PST = TimeZone.getTimeZone("America/Los_Angeles"); String s = "03-Apr-04 2:20:47 o'clock AM PST"; int hour = 2; try { @@ -271,7 +275,7 @@ public void TestFieldPosition() "0034", "0012", "0513", "Pacific Daylight Time", }; Date someDate = new Date(871508052513L); - TimeZone PST = TimeZone.getTimeZone("PST"); + TimeZone PST = TimeZone.getTimeZone("America/Los_Angeles"); for (int j = 0, exp = 0; j < dateFormats.length; ++j) { DateFormat df = dateFormats[j]; if (!(df instanceof SimpleDateFormat)) { diff --git a/test/jdk/java/text/Format/DateFormat/SDFTCKZoneNamesTest.java b/test/jdk/java/text/Format/DateFormat/SDFTCKZoneNamesTest.java index a9f2e30a4d0..aea3706f70e 100644 --- a/test/jdk/java/text/Format/DateFormat/SDFTCKZoneNamesTest.java +++ b/test/jdk/java/text/Format/DateFormat/SDFTCKZoneNamesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * 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,12 +23,13 @@ /** * @test - * @bug 8218948 + * @bug 8218948 8347841 * @summary TCK tests that check the time zone names between DFS.getZoneStrings() * and SDF.format("z*") * @run main SDFTCKZoneNamesTest */ import java.text.*; +import java.time.ZoneId; import java.util.Calendar; import java.util.Date; import java.util.List; @@ -325,6 +326,9 @@ public void SimpleDateFormat0062() { SimpleDateFormat sdf = new SimpleDateFormat(); Date date = new Date(1234567890); for (String[] tz : sdf.getDateFormatSymbols().getZoneStrings()) { + if (ZoneId.SHORT_IDS.containsKey(tz[0])) { + continue; + } sdf.setTimeZone(TimeZone.getTimeZone(tz[0])); for (int i = 0; i < patterns.length && passed; i++) { StringBuffer result = new StringBuffer("qwerty"); diff --git a/test/jdk/java/text/Format/DateFormat/bug4358730.java b/test/jdk/java/text/Format/DateFormat/bug4358730.java index 445a6c23fcf..9b37f9f56be 100644 --- a/test/jdk/java/text/Format/DateFormat/bug4358730.java +++ b/test/jdk/java/text/Format/DateFormat/bug4358730.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ /** * @test - * @bug 4358730 + * @bug 4358730 8347841 * @summary test that confirms Zero-Padding on year. * @run junit bug4358730 */ @@ -56,7 +56,7 @@ public void Test4358730() { Locale saveLocale = Locale.getDefault(); try { - TimeZone.setDefault(TimeZone.getTimeZone("PST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); Locale.setDefault(Locale.US); SimpleDateFormat sdf = new SimpleDateFormat(); diff --git a/test/jdk/java/util/Calendar/CalendarRegression.java b/test/jdk/java/util/Calendar/CalendarRegression.java index 24d34533bde..93869e0af3b 100644 --- a/test/jdk/java/util/Calendar/CalendarRegression.java +++ b/test/jdk/java/util/Calendar/CalendarRegression.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * 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,7 +30,7 @@ * 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 + * 4973919 4980088 4965624 5013094 5006864 8152077 8347841 * @library /java/text/testlib * @run junit CalendarRegression */ @@ -42,6 +42,8 @@ import java.text.DateFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; @@ -50,6 +52,7 @@ import java.util.Map; import java.util.SimpleTimeZone; import java.util.TimeZone; +import java.util.function.Predicate; import static java.util.Calendar.*; @@ -75,7 +78,9 @@ public class CalendarRegression { 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(); + String[] ids = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); boolean bad = false; for (int i = 0; i < ids.length; ++i) { TimeZone zone = TimeZone.getTimeZone(ids[i]); @@ -489,7 +494,7 @@ public void Test4095407() { @Test public void Test4096231() { TimeZone GMT = TimeZone.getTimeZone("GMT"); - TimeZone PST = TimeZone.getTimeZone("PST"); + TimeZone PST = TimeZone.getTimeZone("America/Los_Angeles"); int sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997; Calendar cal1 = new GregorianCalendar(PST); @@ -838,7 +843,7 @@ public void Test4114578() { TimeZone saveZone = TimeZone.getDefault(); boolean fail = false; try { - TimeZone.setDefault(TimeZone.getTimeZone("PST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); Calendar cal = Calendar.getInstance(); long onset = new Date(98, APRIL, 5, 1, 0).getTime() + ONE_HOUR; long cease = new Date(98, OCTOBER, 25, 0, 0).getTime() + 2 * ONE_HOUR; @@ -1163,8 +1168,8 @@ public void Test4147269() { @Test public void Test4149677() { TimeZone[] zones = {TimeZone.getTimeZone("GMT"), - TimeZone.getTimeZone("PST"), - TimeZone.getTimeZone("EAT")}; + TimeZone.getTimeZone("America/Los_Angeles"), + TimeZone.getTimeZone("Africa/Addis_Ababa")}; for (int i = 0; i < zones.length; ++i) { GregorianCalendar calendar = new GregorianCalendar(zones[i]); @@ -1197,7 +1202,7 @@ public void Test4149677() { @Test public void Test4162587() { TimeZone savedTz = TimeZone.getDefault(); - TimeZone tz = TimeZone.getTimeZone("PST"); + TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); TimeZone.setDefault(tz); GregorianCalendar cal = new GregorianCalendar(tz); Date d; @@ -1511,8 +1516,8 @@ public void Test4174361() { */ @Test public void Test4177484() { - TimeZone PST = TimeZone.getTimeZone("PST"); - TimeZone EST = TimeZone.getTimeZone("EST"); + TimeZone PST = TimeZone.getTimeZone("America/Los_Angeles"); + TimeZone EST = TimeZone.getTimeZone("America/Panama"); Calendar cal = Calendar.getInstance(PST, Locale.US); cal.clear(); @@ -1770,7 +1775,7 @@ public void Test4413980() { TimeZone savedTimeZone = TimeZone.getDefault(); try { boolean pass = true; - String[] IDs = new String[]{"Undefined", "PST", "US/Pacific", + String[] IDs = new String[]{"Undefined", "America/Los_Angeles", "US/Pacific", "GMT+3:00", "GMT-01:30"}; for (int i = 0; i < IDs.length; i++) { TimeZone tz = TimeZone.getTimeZone(IDs[i]); diff --git a/test/jdk/java/util/Calendar/JavatimeTest.java b/test/jdk/java/util/Calendar/JavatimeTest.java index 8f32801a307..115b1e4e8b8 100644 --- a/test/jdk/java/util/Calendar/JavatimeTest.java +++ b/test/jdk/java/util/Calendar/JavatimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * 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 8007520 8008254 + *@bug 8007520 8008254 8347841 *@summary Test those bridge methods to/from java.time date/time classes * @key randomness */ @@ -107,23 +107,22 @@ public static void main(String[] args) throws Throwable { ///////////// java.util.TimeZone ///////////////////////// for (String zidStr : TimeZone.getAvailableIDs()) { - // TBD: tzdt intergration + if (ZoneId.SHORT_IDS.containsKey(zidStr)) { + continue; + } + // TBD: tzdt integration if (zidStr.startsWith("SystemV") || zidStr.contains("Riyadh8") - || zidStr.equals("US/Pacific-New") - || zidStr.equals("EST") - || zidStr.equals("HST") - || zidStr.equals("MST")) { + || zidStr.equals("US/Pacific-New")) { continue; } - ZoneId zid = ZoneId.of(zidStr, ZoneId.SHORT_IDS); + ZoneId zid = ZoneId.of(zidStr); if (!zid.equals(TimeZone.getTimeZone(zid).toZoneId())) { throw new RuntimeException("FAILED: zid -> tz -> zid :" + zidStr); } TimeZone tz = TimeZone.getTimeZone(zidStr); // no round-trip for alias and "GMT" if (!tz.equals(TimeZone.getTimeZone(tz.toZoneId())) - && !ZoneId.SHORT_IDS.containsKey(zidStr) && !zidStr.startsWith("GMT")) { throw new RuntimeException("FAILED: tz -> zid -> tz :" + zidStr); } diff --git a/test/jdk/java/util/Calendar/bug4316678.java b/test/jdk/java/util/Calendar/bug4316678.java index f6bd4b87cae..b1c24a6a0c4 100644 --- a/test/jdk/java/util/Calendar/bug4316678.java +++ b/test/jdk/java/util/Calendar/bug4316678.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4316678 + * @bug 4316678 8347841 * @summary test that Calendar's Serialization works correctly. * @run junit bug4316678 */ @@ -53,7 +53,7 @@ public class bug4316678 { // Set custom JVM default TimeZone @BeforeAll static void initAll() { - TimeZone.setDefault(TimeZone.getTimeZone("PST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); } // Restore JVM default Locale and TimeZone diff --git a/test/jdk/java/util/Calendar/bug4372743.java b/test/jdk/java/util/Calendar/bug4372743.java index 193ad53d813..d3d2b39b5fc 100644 --- a/test/jdk/java/util/Calendar/bug4372743.java +++ b/test/jdk/java/util/Calendar/bug4372743.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4372743 + * @bug 4372743 8347841 * @summary test that checks transitions of ERA and YEAR which are caused by add(MONTH). * @run junit bug4372743 */ @@ -67,7 +67,7 @@ public class bug4372743 { // Set custom JVM default timezone @BeforeAll static void initAll() { - TimeZone.setDefault(TimeZone.getTimeZone("PST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); } // Restore JVM default timezone diff --git a/test/jdk/java/util/Date/Bug4955000.java b/test/jdk/java/util/Date/Bug4955000.java index 4339f848f58..f05e6ccd3f8 100644 --- a/test/jdk/java/util/Date/Bug4955000.java +++ b/test/jdk/java/util/Date/Bug4955000.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4955000 + * @bug 4955000 8347841 * @summary Make sure that a Date and a GregorianCalendar produce the * same date/time. Both are new implementations in 1.5. */ @@ -42,7 +42,7 @@ public class Bug4955000 { public static void main(String[] args) { TimeZone defaultTZ = TimeZone.getDefault(); try { - TimeZone.setDefault(TimeZone.getTimeZone("NST")); + TimeZone.setDefault(TimeZone.getTimeZone("Pacific/Auckland")); GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("UTC")); // Date1025 int[] years1 = { diff --git a/test/jdk/java/util/Date/DateRegression.java b/test/jdk/java/util/Date/DateRegression.java index 8fe89d9d59b..eda575743e3 100644 --- a/test/jdk/java/util/Date/DateRegression.java +++ b/test/jdk/java/util/Date/DateRegression.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ /* * @test - * @bug 4023247 4027685 4032037 4072029 4073003 4118010 4120606 4133833 4136916 6274757 6314387 + * @bug 4023247 4027685 4032037 4072029 4073003 4118010 4120606 4133833 + * 4136916 6274757 6314387 8347841 * @run junit DateRegression */ @@ -106,7 +107,7 @@ public void Test4072029() { TimeZone saveZone = TimeZone.getDefault(); try { - TimeZone.setDefault(TimeZone.getTimeZone("PST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); Date now = new Date(); String s = now.toString(); Date now2 = new Date(now.toString()); diff --git a/test/jdk/java/util/Date/DateTest.java b/test/jdk/java/util/Date/DateTest.java index 6740cb16faa..7dbb19409d3 100644 --- a/test/jdk/java/util/Date/DateTest.java +++ b/test/jdk/java/util/Date/DateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4143459 + * @bug 4143459 8347841 * @summary test Date * @run junit DateTest */ @@ -56,7 +56,7 @@ public void TestDefaultZoneLite() { d.setMonth(Calendar.JANUARY); d.setDate(1); d.setHours(6); - TimeZone.setDefault(TimeZone.getTimeZone("PST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); if (d.getHours() != 22) { fail("Fail: Date.setHours()/getHours() ignoring default zone"); } @@ -79,7 +79,7 @@ public void TestDefaultZone() { 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"); + TimeZone PST = TimeZone.getTimeZone("America/Los_Angeles"); String[] names = { "year", "month", "date", "day of week", "hour", "offset" }; int[] GMT_EXP = { 98, Calendar.JANUARY, 1, Calendar.THURSDAY - Calendar.SUNDAY, 6, 0 }; @@ -207,7 +207,7 @@ public void TestDate480() { TimeZone save = TimeZone.getDefault(); try { - TimeZone.setDefault(TimeZone.getTimeZone("PST")); + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); Date d1=new java.util.Date(97,8,13,10,8,13); System.out.println("d = "+d1); Date d2=new java.util.Date(97,8,13,30,8,13); // 20 hours later diff --git a/test/jdk/java/util/Locale/UserRegionTest.java b/test/jdk/java/util/Locale/UserRegionTest.java new file mode 100644 index 00000000000..72a7106b267 --- /dev/null +++ b/test/jdk/java/util/Locale/UserRegionTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8342582 + * @summary Test if "user.region" system property successfully overrides + * other locale related system properties at startup + * @modules jdk.localedata + * @run junit/othervm + * -Duser.region=DE + * -Duser.language=en + * -Duser.script=Latn + * -Duser.country=US + * -Duser.variant=FOO UserRegionTest + * @run junit/othervm + * -Duser.region=DE_POSIX + * -Duser.language=en + * -Duser.script=Latn + * -Duser.country=US + * -Duser.variant=FOO UserRegionTest + * @run junit/othervm + * -Duser.region=_POSIX + * -Duser.language=en + * -Duser.script=Latn + * -Duser.country=US + * -Duser.variant=FOO UserRegionTest + */ + +import java.util.Locale; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class UserRegionTest { + @Test + public void testDefaultLocale() { + var region = System.getProperty("user.region").split("_"); + var expected = Locale.of(System.getProperty("user.language"), + region[0], region.length > 1 ? region[1] : ""); + assertEquals(expected, Locale.getDefault()); + assertEquals(expected, Locale.getDefault(Locale.Category.FORMAT)); + assertEquals(expected, Locale.getDefault(Locale.Category.DISPLAY)); + } + + @Test + public void testNumberFormat() { + if (System.getProperty("user.region").startsWith("DE")) { + assertEquals("0,50000", String.format("%.5f", 0.5f)); + } else { + assertEquals("0.50000", String.format("%.5f", 0.5f)); + } + } +} diff --git a/test/jdk/java/util/PluggableLocale/LocaleNameProviderTest.java b/test/jdk/java/util/PluggableLocale/LocaleNameProviderTest.java index 6e9badede8a..1de2839fe04 100644 --- a/test/jdk/java/util/PluggableLocale/LocaleNameProviderTest.java +++ b/test/jdk/java/util/PluggableLocale/LocaleNameProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4052440 8000273 8062588 8210406 + * @bug 4052440 8000273 8062588 8210406 8356040 * @summary LocaleNameProvider tests * @library providersrc/foobarutils * providersrc/barprovider @@ -31,97 +31,112 @@ * java.base/sun.util.resources * @build com.foobar.Utils * com.bar.* - * @run main/othervm -Djava.locale.providers=JRE,SPI LocaleNameProviderTest + * @run junit/othervm -Djava.locale.providers=JRE,SPI LocaleNameProviderTest */ +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; +import java.util.ResourceBundle; import com.bar.LocaleNameProviderImpl; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import sun.util.locale.provider.LocaleProviderAdapter; import sun.util.locale.provider.ResourceBundleBasedAdapter; import sun.util.resources.OpenListResourceBundle; public class LocaleNameProviderTest extends ProviderTest { - public static void main(String[] s) { - new LocaleNameProviderTest(); - } + private static final LocaleNameProviderImpl LNP = new LocaleNameProviderImpl(); + + /* + * This is not an exhaustive test. Such a test would require iterating (1000x1000)+ + * inputs. Instead, we check against Japanese lang locales which guarantees + * we will run into cases where the CLDR is not the preferred provider as the + * SPI has defined variants of the Japanese locale (E.g. osaka). + * See LocaleNameProviderImpl and LocaleNames ResourceBundle. + */ + @ParameterizedTest + @MethodSource + void checkAvailLocValidityTest(Locale target, Locale test, ResourceBundle rb, + boolean jreSupports, boolean spiSupports) { + // codes + String lang = test.getLanguage(); + String ctry = test.getCountry(); + String vrnt = test.getVariant(); + + // the localized name + String langresult = test.getDisplayLanguage(target); + String ctryresult = test.getDisplayCountry(target); + String vrntresult = test.getDisplayVariant(target); + + // provider's name (if any) + String providerslang = null; + String providersctry = null; + String providersvrnt = null; + if (spiSupports) { + providerslang = LNP.getDisplayLanguage(lang, target); + providersctry = LNP.getDisplayCountry(ctry, target); + providersvrnt = LNP.getDisplayVariant(vrnt, target); + } - LocaleNameProviderTest() { - checkAvailLocValidityTest(); - variantFallbackTest(); - } + // JRE's name + String jreslang = null; + String jresctry = null; + String jresvrnt = null; + if (!lang.isEmpty()) { + try { + jreslang = rb.getString(lang); + } catch (MissingResourceException mre) {} + } + if (!ctry.isEmpty()) { + try { + jresctry = rb.getString(ctry); + } catch (MissingResourceException mre) {} + } + if (!vrnt.isEmpty()) { + try { + jresvrnt = rb.getString("%%"+vrnt); + } catch (MissingResourceException mre) {} + } - void checkAvailLocValidityTest() { - LocaleNameProviderImpl lnp = new LocaleNameProviderImpl(); - Locale[] availloc = Locale.getAvailableLocales(); - Locale[] testloc = availloc.clone(); - List jreimplloc = Arrays.asList(LocaleProviderAdapter.forJRE().getLocaleNameProvider().getAvailableLocales()); - List providerloc = Arrays.asList(lnp.getAvailableLocales()); + checkValidity(target, jreslang, providerslang, langresult, + jreSupports && jreslang != null); + checkValidity(target, jresctry, providersctry, ctryresult, + jreSupports && jresctry != null); + checkValidity(target, jresvrnt, providersvrnt, vrntresult, + jreSupports && jresvrnt != null); + } - for (Locale target: availloc) { + public static List checkAvailLocValidityTest() { + var args = new ArrayList(); + Locale[] availloc = Locale.availableLocales() + .filter(l -> l.getLanguage().equals("ja")) + .toArray(Locale[]::new); + List jreimplloc = Arrays.stream(LocaleProviderAdapter.forJRE().getLocaleNameProvider().getAvailableLocales()) + .filter(l -> l.getLanguage().equals("ja")) + .toList(); + List providerloc = Arrays.asList(LNP.getAvailableLocales()); + + for (Locale target : availloc) { // pure JRE implementation - OpenListResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getLocaleNames(target); + OpenListResourceBundle rb = ((ResourceBundleBasedAdapter) LocaleProviderAdapter.forJRE()).getLocaleData().getLocaleNames(target); boolean jreSupportsTarget = jreimplloc.contains(target); - - for (Locale test: testloc) { - // codes - String lang = test.getLanguage(); - String ctry = test.getCountry(); - String vrnt = test.getVariant(); - - // the localized name - String langresult = test.getDisplayLanguage(target); - String ctryresult = test.getDisplayCountry(target); - String vrntresult = test.getDisplayVariant(target); - - // provider's name (if any) - String providerslang = null; - String providersctry = null; - String providersvrnt = null; - if (providerloc.contains(target)) { - providerslang = lnp.getDisplayLanguage(lang, target); - providersctry = lnp.getDisplayCountry(ctry, target); - providersvrnt = lnp.getDisplayVariant(vrnt, target); - } - - // JRE's name - String jreslang = null; - String jresctry = null; - String jresvrnt = null; - if (!lang.equals("")) { - try { - jreslang = rb.getString(lang); - } catch (MissingResourceException mre) {} - } - if (!ctry.equals("")) { - try { - jresctry = rb.getString(ctry); - } catch (MissingResourceException mre) {} - } - if (!vrnt.equals("")) { - try { - jresvrnt = rb.getString("%%"+vrnt); - } catch (MissingResourceException mre) {} - } - - System.out.print("For key: "+lang+" "); - checkValidity(target, jreslang, providerslang, langresult, - jreSupportsTarget && jreslang != null); - System.out.print("For key: "+ctry+" "); - checkValidity(target, jresctry, providersctry, ctryresult, - jreSupportsTarget && jresctry != null); - System.out.print("For key: "+vrnt+" "); - checkValidity(target, jresvrnt, providersvrnt, vrntresult, - jreSupportsTarget && jresvrnt != null); + boolean providerSupportsTarget = providerloc.contains(target); + for (Locale test : availloc) { + args.add(Arguments.of(target, test, rb, jreSupportsTarget, providerSupportsTarget)); } } + return args; } + @Test void variantFallbackTest() { Locale YY = Locale.of("yy", "YY", "YYYY"); Locale YY_suffix = Locale.of("yy", "YY", "YYYY_suffix"); diff --git a/test/jdk/java/util/PluggableLocale/TimeZoneNameProviderTest.java b/test/jdk/java/util/PluggableLocale/TimeZoneNameProviderTest.java index 48de90b4a16..4871dc27e27 100644 --- a/test/jdk/java/util/PluggableLocale/TimeZoneNameProviderTest.java +++ b/test/jdk/java/util/PluggableLocale/TimeZoneNameProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4052440 8003267 8062588 8210406 + * @bug 4052440 8003267 8062588 8210406 8327434 8347841 * @summary TimeZoneNameProvider tests * @library providersrc/foobarutils * providersrc/barprovider @@ -37,6 +37,7 @@ import java.text.DateFormatSymbols; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.ZoneId; import java.time.format.TextStyle; import java.util.Arrays; import java.util.Calendar; @@ -45,6 +46,8 @@ import java.util.Locale; import java.util.MissingResourceException; import java.util.TimeZone; +import java.util.function.Predicate; +import java.util.stream.Stream; import com.bar.TimeZoneNameProviderImpl; @@ -69,12 +72,14 @@ public static void main(String[] s) { } void test1() { - Locale[] available = Locale.getAvailableLocales(); List jreimplloc = Arrays.asList(LocaleProviderAdapter.forJRE().getTimeZoneNameProvider().getAvailableLocales()); List providerLocales = Arrays.asList(tznp.getAvailableLocales()); - String[] ids = TimeZone.getAvailableIDs(); + String[] ids = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); - for (Locale target: available) { + // Sampling relevant locales + Stream.concat(Stream.of(Locale.ROOT, Locale.US, Locale.JAPAN), providerLocales.stream()).forEach(target -> { // pure JRE implementation OpenListResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getTimeZoneNames(target); boolean jreSupportsTarget = jreimplloc.contains(target); @@ -111,7 +116,7 @@ void test1() { jreSupportsTarget && jresname != null); } } - } + }); } final String pattern = "z"; @@ -175,7 +180,7 @@ void test2() { df.parse(DISPLAY_NAMES_KYOTO[i]); } } catch (ParseException pe) { - throw new RuntimeException("parse error occured" + pe); + throw new RuntimeException("parse error occurred" + pe); } finally { // restore the reserved locale and time zone Locale.setDefault(defaultLocale); @@ -185,8 +190,8 @@ void test2() { void test3() { final String[] TZNAMES = { - LATIME, PST, PST8PDT, US_PACIFIC, - TOKYOTIME, JST, JAPAN, + LATIME, PST8PDT, US_PACIFIC, + TOKYOTIME, JAPAN, }; for (String tzname : TZNAMES) { TimeZone tz = TimeZone.getTimeZone(tzname); @@ -207,17 +212,13 @@ void test3() { } final String LATIME = "America/Los_Angeles"; - final String PST = "PST"; final String PST8PDT = "PST8PDT"; final String US_PACIFIC = "US/Pacific"; final String LATIME_IN_OSAKA = tznp.getDisplayName(LATIME, false, TimeZone.LONG, OSAKA); final String TOKYOTIME = "Asia/Tokyo"; - final String JST = "JST"; final String JAPAN = "Japan"; - final String JST_IN_OSAKA = - tznp.getDisplayName(JST, false, TimeZone.LONG, OSAKA); void aliasTest() { // Check that provider's name for a standard id (America/Los_Angeles) is @@ -227,32 +228,10 @@ void aliasTest() { throw new RuntimeException("Could not get provider's localized name. result: "+latime+" expected: "+LATIME_IN_OSAKA); } - String pst = TimeZone.getTimeZone(PST).getDisplayName(OSAKA); - if (!LATIME_IN_OSAKA.equals(pst)) { - throw new RuntimeException("Provider's localized name is not available for an alias ID: "+PST+". result: "+pst+" expected: "+LATIME_IN_OSAKA); - } - String us_pacific = TimeZone.getTimeZone(US_PACIFIC).getDisplayName(OSAKA); if (!LATIME_IN_OSAKA.equals(us_pacific)) { throw new RuntimeException("Provider's localized name is not available for an alias ID: "+US_PACIFIC+". result: "+us_pacific+" expected: "+LATIME_IN_OSAKA); } - - // Check that provider's name for an alias id (JST) is - // propagated to its standard id and alias ids. - String jstime = TimeZone.getTimeZone(JST).getDisplayName(OSAKA); - if (!JST_IN_OSAKA.equals(jstime)) { - throw new RuntimeException("Could not get provider's localized name. result: "+jstime+" expected: "+JST_IN_OSAKA); - } - - String tokyotime = TimeZone.getTimeZone(TOKYOTIME).getDisplayName(OSAKA); - if (!JST_IN_OSAKA.equals(tokyotime)) { - throw new RuntimeException("Provider's localized name is not available for a standard ID: "+TOKYOTIME+". result: "+tokyotime+" expected: "+JST_IN_OSAKA); - } - - String japan = TimeZone.getTimeZone(JAPAN).getDisplayName(OSAKA); - if (!JST_IN_OSAKA.equals(japan)) { - throw new RuntimeException("Provider's localized name is not available for an alias ID: "+JAPAN+". result: "+japan+" expected: "+JST_IN_OSAKA); - } } /* diff --git a/test/jdk/java/util/Properties/StoreDeadlock.java b/test/jdk/java/util/Properties/StoreDeadlock.java index d59a4445251..0eb3e930a81 100644 --- a/test/jdk/java/util/Properties/StoreDeadlock.java +++ b/test/jdk/java/util/Properties/StoreDeadlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * 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 6199320 + * @bug 6199320 8347841 * @summary Properties.store() causes deadlock when concurrently calling TimeZone apis * @run main/timeout=20 StoreDeadlock * @author Xueming Shen @@ -59,7 +59,7 @@ public void run() { } class Thread2 extends Thread { public void run() { - System.out.println("tz=" + TimeZone.getTimeZone("PST")); + System.out.println("tz=" + TimeZone.getTimeZone("America/Los_Angeles")); } } } diff --git a/test/jdk/java/util/TimeZone/Bug5097350.java b/test/jdk/java/util/TimeZone/Bug5097350.java index ff0894bf3d7..862d7f90a15 100644 --- a/test/jdk/java/util/TimeZone/Bug5097350.java +++ b/test/jdk/java/util/TimeZone/Bug5097350.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * 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,16 +23,19 @@ /* * @test - * @bug 5097350 + * @bug 5097350 8347841 * @summary Make sure that TimeZone.getTimeZone returns a clone of a cached TimeZone instance. */ +import java.time.ZoneId; import java.util.*; -import java.text.*; +import java.util.function.Predicate; public class Bug5097350 { public static void main(String[] args) { - String[] tzids = TimeZone.getAvailableIDs(); + String[] tzids = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); List ids = new ArrayList<>(tzids.length + 10); ids.addAll(Arrays.asList(tzids)); // add some custom ids diff --git a/test/jdk/java/util/TimeZone/Bug6329116.java b/test/jdk/java/util/TimeZone/Bug6329116.java index 6e85fe8cb5b..f005b634464 100644 --- a/test/jdk/java/util/TimeZone/Bug6329116.java +++ b/test/jdk/java/util/TimeZone/Bug6329116.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * 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,14 +25,16 @@ * @test * @bug 6329116 6756569 6757131 6758988 6764308 6796489 6834474 6609737 6507067 * 7039469 7090843 7103108 7103405 7158483 8008577 8059206 8064560 8072042 - * 8077685 8151876 8166875 8169191 8170316 8176044 + * 8077685 8151876 8166875 8169191 8170316 8176044 8347841 * @summary Make sure that timezone short display names are idenical to Olson's data. * @run junit/othervm -Djava.locale.providers=COMPAT,SPI Bug6329116 */ import java.io.*; import java.text.*; +import java.time.ZoneId; import java.util.*; +import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -41,7 +43,9 @@ public class Bug6329116 { static Locale[] locales = Locale.getAvailableLocales(); - static String[] timezones = TimeZone.getAvailableIDs(); + static String[] timezones = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); @Test public void bug6329116() throws IOException { @@ -98,6 +102,9 @@ public void bug6329116() throws IOException { tzs[0] = timezoneID; for (int j = 0; j < tzs.length; j++) { + if (ZoneId.SHORT_IDS.containsKey(tzs[j])) { + continue; + } tz = TimeZone.getTimeZone(tzs[j]); if (!tzs[j].equals(tz.getID())) { diff --git a/test/jdk/java/util/TimeZone/Bug6772689.java b/test/jdk/java/util/TimeZone/Bug6772689.java index f730567013d..b2ce085fc22 100644 --- a/test/jdk/java/util/TimeZone/Bug6772689.java +++ b/test/jdk/java/util/TimeZone/Bug6772689.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 +23,18 @@ /* * @test - * @bug 6772689 + * @bug 6772689 8347841 * @summary Test for standard-to-daylight transitions at midnight: * date stays on the given day. */ +import java.time.ZoneId; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; +import java.util.function.Predicate; import static java.util.GregorianCalendar.*; public class Bug6772689 { @@ -43,7 +46,9 @@ public static void main(String[] args) { int errors = 0; Calendar cal = new GregorianCalendar(BEGIN_YEAR, MARCH, 1); - String[] tzids = TimeZone.getAvailableIDs(); + String[] tzids = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); try { for (String id : tzids) { TimeZone tz = TimeZone.getTimeZone(id); diff --git a/test/jdk/java/util/TimeZone/DaylightTimeTest.java b/test/jdk/java/util/TimeZone/DaylightTimeTest.java index 4b637136f96..006f03424ee 100644 --- a/test/jdk/java/util/TimeZone/DaylightTimeTest.java +++ b/test/jdk/java/util/TimeZone/DaylightTimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * 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,21 @@ /* * @test - * @bug 6936350 + * @bug 6936350 8347841 * @summary Test case for TimeZone.observesDaylightTime() */ +import java.time.ZoneId; import java.util.*; +import java.util.function.Predicate; import static java.util.GregorianCalendar.*; public class DaylightTimeTest { private static final int ONE_HOUR = 60 * 60 * 1000; // one hour private static final int INTERVAL = 24 * ONE_HOUR; // one day - private static final String[] ZONES = TimeZone.getAvailableIDs(); + private static final String[] ZONES = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); private static int errors = 0; public static void main(String[] args) { diff --git a/test/jdk/java/util/TimeZone/IDTest.java b/test/jdk/java/util/TimeZone/IDTest.java index d5396b619b8..97bf971abc9 100644 --- a/test/jdk/java/util/TimeZone/IDTest.java +++ b/test/jdk/java/util/TimeZone/IDTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * 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,24 +23,30 @@ /* * @test - * @bug 4509255 5055567 6176318 7090844 + * @bug 4509255 5055567 6176318 7090844 8347841 * @summary Tests consistencies of time zone IDs. */ +import java.time.ZoneId; import java.util.Arrays; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TimeZone; import java.util.TreeMap; +import java.util.function.Predicate; 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(); + String[] tzs = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); + String[] tzs2 = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); if (tzs.length != tzs2.length) { throw new RuntimeException("tzs.length(" + tzs.length + ") != tzs2.length(" + tzs2.length + ")"); @@ -83,8 +89,12 @@ public static void main(String[] args) { // Check the getAvailableIDs(int) call to return the same // set of IDs int offset = key.intValue(); - tzs = TimeZone.getAvailableIDs(offset); - tzs2 = TimeZone.getAvailableIDs(offset); + tzs = Arrays.stream(TimeZone.getAvailableIDs(offset)) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); + tzs2 = Arrays.stream(TimeZone.getAvailableIDs(offset)) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); if (!Arrays.equals(tzs, tzs2)) { throw new RuntimeException("inconsistent tzs from getAvailableIDs("+offset+")"); } diff --git a/test/jdk/java/util/TimeZone/ListTimeZones.java b/test/jdk/java/util/TimeZone/ListTimeZones.java index 7dd309473e6..dad59a91a95 100644 --- a/test/jdk/java/util/TimeZone/ListTimeZones.java +++ b/test/jdk/java/util/TimeZone/ListTimeZones.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * 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,21 @@ /** * @test - * @bug 6851214 + * @bug 6851214 8347841 * @summary Allow 24:00 as a valid end/start DST time stamp * @run main ListTimeZones */ +import java.time.ZoneId; import java.util.*; +import java.util.function.Predicate; public class ListTimeZones{ public static void main(String[] args){ Date date = new Date(); - String TimeZoneIds[] = TimeZone.getAvailableIDs(); + String[] TimeZoneIds = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); for(int i = 0; i < TimeZoneIds.length; i++){ TimeZone tz = TimeZone.getTimeZone(TimeZoneIds[i]); Calendar calendar = new GregorianCalendar(tz); diff --git a/test/jdk/java/util/TimeZone/NegativeDSTTest.java b/test/jdk/java/util/TimeZone/NegativeDSTTest.java index b237f0fd4ee..eb46b8d4b29 100644 --- a/test/jdk/java/util/TimeZone/NegativeDSTTest.java +++ b/test/jdk/java/util/TimeZone/NegativeDSTTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ /** * @test - * @bug 8212970 + * @bug 8212970 8324065 * @summary Test whether the savings are positive in time zones that have * negative savings in the source TZ files. * @run testng NegativeDSTTest @@ -81,7 +81,10 @@ private Object[][] negativeDST () { {CASABLANCA, LocalDate.of(2019, 5, 6), 0, false}, {CASABLANCA, LocalDate.of(2037, 10, 5), 0, false}, {CASABLANCA, LocalDate.of(2037, 11, 16), ONE_HOUR, true}, + {CASABLANCA, LocalDate.of(2038, 9, 27), 0, false}, {CASABLANCA, LocalDate.of(2038, 11, 1), ONE_HOUR, true}, + {CASABLANCA, LocalDate.of(2087, 3, 31), 0, false}, + {CASABLANCA, LocalDate.of(2087, 5, 12), ONE_HOUR, true}, }; } diff --git a/test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java b/test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java new file mode 100644 index 00000000000..586c7bdf5cc --- /dev/null +++ b/test/jdk/java/util/TimeZone/SimpleTimeZoneEqualsHashCodeTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8369184 + * @summary Checks if equals()/hashCode() of SimpleTimeZone works correctly + * @run junit SimpleTimeZoneEqualsHashCodeTest + */ + +import java.util.SimpleTimeZone; +import static java.util.Calendar.MARCH; +import static java.util.Calendar.NOVEMBER; +import static java.util.Calendar.SUNDAY; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SimpleTimeZoneEqualsHashCodeTest { + private static final SimpleTimeZone STZ_WITH_DST = + new SimpleTimeZone(-288_000_000, "America/Los_Angeles", + MARCH, 8, -SUNDAY, 7_200_000, + NOVEMBER, 1, -SUNDAY, 7_200_000); + private static final SimpleTimeZone STZ_WITHOUT_DST = + new SimpleTimeZone(0, "foo"); + + @Test + void withDSTTest() { + var stz = (SimpleTimeZone)STZ_WITH_DST.clone(); + assertEquals(STZ_WITH_DST, stz); + assertEquals(STZ_WITH_DST.hashCode(), stz.hashCode()); + + stz.setEndRule(NOVEMBER, 8, -SUNDAY, 7_200_000); + assertNotEquals(STZ_WITH_DST, stz); + // From the contract point, hash codes may be the same. + // This tests the implementation which considers DST + // related fields for calculating the hash code. + assertNotEquals(STZ_WITH_DST.hashCode(), stz.hashCode()); + } + + @Test + void withoutDSTTest() { + var stz = (SimpleTimeZone)STZ_WITHOUT_DST.clone(); + + // Only setting start rule. Still considered non-DST zone + stz.setStartRule(MARCH, 8, -SUNDAY, 7_200_000); + assertTrue(!stz.useDaylightTime()); + assertEquals(STZ_WITHOUT_DST, stz); + assertEquals(STZ_WITHOUT_DST.hashCode(), stz.hashCode()); + + // Setting end rule as well. Now it is considered DST zone + stz.setEndRule(NOVEMBER, 8, -SUNDAY, 7_200_000); + assertTrue(stz.useDaylightTime()); + assertNotEquals(STZ_WITHOUT_DST, stz); + // From the contract point, hash codes may be the same. + // This tests the implementation which considers DST + // related fields for calculating the hash code. + assertNotEquals(STZ_WITHOUT_DST.hashCode(), stz.hashCode()); + } +} diff --git a/test/jdk/java/util/TimeZone/TimeZoneBoundaryTest.java b/test/jdk/java/util/TimeZone/TimeZoneBoundaryTest.java index c70ccc204de..9e4ca02731d 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneBoundaryTest.java +++ b/test/jdk/java/util/TimeZone/TimeZoneBoundaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * 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 8347841 * @summary test Time Zone Boundary * @run junit TimeZoneBoundaryTest */ @@ -251,7 +252,7 @@ void verifyDST(Date d, TimeZone time_zone, @Test public void TestBoundaries() { - TimeZone pst = TimeZone.getTimeZone("PST"); + TimeZone pst = TimeZone.getTimeZone("America/Los_Angeles"); TimeZone save = TimeZone.getDefault(); try { TimeZone.setDefault(pst); @@ -410,11 +411,8 @@ else if (!z.useDaylightTime()) @Test 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("Australia/Darwin"), 0); + findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Pacific/Honolulu"), 0); 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); diff --git a/test/jdk/java/util/TimeZone/TimeZoneRegression.java b/test/jdk/java/util/TimeZone/TimeZoneRegression.java index 6343279689f..bb191a47cd9 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneRegression.java +++ b/test/jdk/java/util/TimeZone/TimeZoneRegression.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429 * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960 - * 4966229 6433179 6851214 8007520 8008577 + * 4966229 6433179 6851214 8007520 8008577 8347841 * @library /java/text/testlib * @run junit/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression */ @@ -42,8 +42,8 @@ public class TimeZoneRegression { @Test public void Test4073209() { - TimeZone z1 = TimeZone.getTimeZone("PST"); - TimeZone z2 = TimeZone.getTimeZone("PST"); + TimeZone z1 = TimeZone.getTimeZone("America/Los_Angeles"); + TimeZone z2 = TimeZone.getTimeZone("America/Los_Angeles"); if (z1 == z2) { fail("Fail: TimeZone should return clones"); } @@ -81,7 +81,7 @@ public void Test4084933() { // test both SimpleTimeZone and ZoneInfo objects. // @since 1.4 sub4084933(getPST()); - sub4084933(TimeZone.getTimeZone("PST")); + sub4084933(TimeZone.getTimeZone("America/Los_Angeles")); } private void sub4084933(TimeZone tz) { @@ -122,7 +122,7 @@ private void sub4084933(TimeZone tz) { @Test public void Test4096952() { - String[] ZONES = { "GMT", "MET", "IST" }; + String[] ZONES = { "GMT", "MET", "Asia/Kolkata" }; boolean pass = true; try { for (int i=0; i executorAndQueuedTaskCounts() { .mapToObj(i -> Arguments.of(s, i))); } + private static Stream shutdownMethods() { + return Stream.>of( + e -> e.shutdown(), + e -> e.shutdownNow() + ).map(Arguments::of); + } + /** * SingleThreadExecutor with no worker threads. */ @@ -110,6 +126,28 @@ void testActiveWorker(Supplier supplier,int queuedTaskCount) th assertEquals(ntasks, completedTaskCount.get()); } + @ParameterizedTest + @MethodSource("shutdownMethods") + void testShutdownUnlinksCleaner(Consumer shutdown) throws Exception { + ClassLoader classLoader = + Utils.getTestClassPathURLClassLoader(ClassLoader.getPlatformClassLoader()); + + ReferenceQueue queue = new ReferenceQueue<>(); + Reference reference = new PhantomReference(classLoader, queue); + try { + Class isolatedClass = classLoader.loadClass("AutoShutdown$IsolatedClass"); + assertSame(isolatedClass.getClassLoader(), classLoader); + isolatedClass.getDeclaredMethod("shutdown", Consumer.class).invoke(null, shutdown); + + isolatedClass = null; + classLoader = null; + + assertTrue(ForceGC.wait(() -> queue.poll() != null)); + } finally { + Reference.reachabilityFence(reference); + } + } + /** * Returns the delegate for the given ExecutorService. The given ExecutorService * must be a Executors$DelegatedExecutorService. @@ -132,5 +170,22 @@ private void gcAndAwaitTermination(ExecutorService executor) throws Exception { terminated = executor.awaitTermination(100, TimeUnit.MILLISECONDS); } } -} + public static class IsolatedClass { + + private static final ExecutorService executor = + Executors.newSingleThreadExecutor(new IsolatedThreadFactory()); + + public static void shutdown(Consumer shutdown) { + shutdown.accept(executor); + } + } + + public static class IsolatedThreadFactory implements ThreadFactory { + + @Override + public Thread newThread(Runnable r) { + return new Thread(r); + } + } +} diff --git a/test/jdk/java/util/jar/Manifest/ValueUtf8Coding.java b/test/jdk/java/util/jar/Manifest/ValueUtf8Coding.java index 533007dcf7a..28921bba868 100644 --- a/test/jdk/java/util/jar/Manifest/ValueUtf8Coding.java +++ b/test/jdk/java/util/jar/Manifest/ValueUtf8Coding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ /** * @test - * @bug 8066619 + * @bug 8066619 8351567 * @run testng ValueUtf8Coding * @summary Tests encoding and decoding manifest header values to and from * UTF-8 with the complete Unicode character set. @@ -201,10 +201,6 @@ static Manifest writeAndRead(Manifest mf) throws IOException { mf.write(out); byte[] mfBytes = out.toByteArray(); - System.out.println("-".repeat(72)); - System.out.print(new String(mfBytes, UTF_8)); - System.out.println("-".repeat(72)); - ByteArrayInputStream in = new ByteArrayInputStream(mfBytes); return new Manifest(in); } diff --git a/test/jdk/java/util/logging/LocalizedLevelName.java b/test/jdk/java/util/logging/LocalizedLevelName.java index aaaf6f22a54..157e965f1a9 100644 --- a/test/jdk/java/util/logging/LocalizedLevelName.java +++ b/test/jdk/java/util/logging/LocalizedLevelName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 +52,7 @@ public class LocalizedLevelName { public static void main(String args[]) throws Exception { Locale defaultLocale = Locale.getDefault(); for (int i=0; i list = new ArrayList<>(); byte[] buf1 = new byte[1024]; @@ -84,16 +92,17 @@ private static void testDeInflater() throws Throwable { } } - int n = 10; - long cnt = list.size(); - while (n-- > 0 && cnt != 0) { - Thread.sleep(100); - System.gc(); - cnt = list.stream().filter(o -> addrOf(o) != 0).count(); + final AtomicLong numNotYetCleaned = new AtomicLong(); + // trigger GC + final boolean resourcesCleaned = ForceGC.wait(() -> { + final long remaining = list.stream().filter(o -> addrOf(o) != 0).count(); + numNotYetCleaned.set(remaining); + return remaining == 0; + }); + if (!resourcesCleaned) { + throw new RuntimeException(numNotYetCleaned.get() + + " resources haven't yet been cleaned"); } - if (cnt != 0) - throw new RuntimeException("cleaner failed to clean : " + cnt); - } @DontInline @@ -139,17 +148,18 @@ private static void testZipFile() throws Throwable { if (zsrc != null) { Field zfileField = zsrc.getClass().getDeclaredField("zfile"); if (!zfileField.trySetAccessible()) { - throw new RuntimeException("'ZipFile.Source.zfile' is not accesible"); - } - //System.out.println("zffile: " + zfileField.get(zsrc)); - int n = 10; - while (n-- > 0 && zfileField.get(zsrc) != null) { - System.out.println("waiting gc ... " + n); - System.gc(); - Thread.sleep(100); + throw new RuntimeException("'ZipFile.Source.zfile' is not accessible"); } - if (zfileField.get(zsrc) != null) { - throw new RuntimeException("cleaner failed to clean zipfile."); + final boolean resourceCleaned = ForceGC.wait(() -> { + try { + return zfileField.get(zsrc) == null; + } catch (IllegalAccessException e) { + // shouldn't happen + throw new RuntimeException(e); + } + }); + if (!resourceCleaned) { + throw new RuntimeException("cleaner failed to clean zipfile " + zip); } } } diff --git a/test/jdk/javax/management/security/SecurityTest.java b/test/jdk/javax/management/security/SecurityTest.java index 835c340dd99..7212aea883f 100644 --- a/test/jdk/javax/management/security/SecurityTest.java +++ b/test/jdk/javax/management/security/SecurityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,6 +142,9 @@ static void setTrustStoreProperties(Map map) { * map (argName, value) format, then calls original test's run method. */ public static void main(String args[]) throws Exception { + // Disable default KeyManager's certificate checking so we can use + // a certificate signed with MD5withRSA algorithm. + System.setProperty("jdk.tls.SunX509KeyManager.certChecking", "false"); System.out.println("================================================="); @@ -529,6 +532,10 @@ private static class ClientSide { private MBeanServerConnection mbsc = null; public static void main(String args[]) throws Exception { + // Disable default KeyManager's certificate checking so we can use + // a certificate signed with MD5withRSA algorithm. + System.setProperty("jdk.tls.SunX509KeyManager.certChecking", + "false"); // Parses parameters Utils.parseDebugProperties(); diff --git a/test/jdk/javax/net/ssl/DTLS/CipherSuite.java b/test/jdk/javax/net/ssl/DTLS/CipherSuite.java index 7ad8206a37e..b96032fd781 100644 --- a/test/jdk/javax/net/ssl/DTLS/CipherSuite.java +++ b/test/jdk/javax/net/ssl/DTLS/CipherSuite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * 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,16 +33,16 @@ * jdk.crypto.ec * @library /test/lib * @build DTLSOverDatagram - * @run main/othervm CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA re-enable * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * @run main/othervm CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA256 + * @run main/othervm CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA256 re-enable * @run main/othervm CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA * @run main/othervm CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA re-enable * @run main/othervm CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * @run main/othervm CipherSuite TLS_RSA_WITH_AES_128_GCM_SHA256 + * @run main/othervm CipherSuite TLS_RSA_WITH_AES_128_GCM_SHA256 re-enable * @run main/othervm CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 re-enable * @run main/othervm CipherSuite TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 * @run main/othervm CipherSuite TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java b/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java index e9165fa391c..1fc4f962675 100644 --- a/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java +++ b/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -140,4 +140,3 @@ private static void runTest(String[] serverNamedGroups, } } } - diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java b/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java index 1820dbe5423..9780586cd57 100644 --- a/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java +++ b/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 @@ */ public class DTLSOverDatagram { - private static final int SOCKET_TIMEOUT = 10 * 1000; // in millis private static final int BUFFER_SIZE = 1024; private static final int MAXIMUM_PACKET_SIZE = 1024; @@ -78,6 +77,7 @@ public class DTLSOverDatagram { private final AtomicBoolean exceptionOccurred = new AtomicBoolean(false); private final CountDownLatch serverStarted = new CountDownLatch(1); + private int socketTimeout = 10 * 1000; // in millis /* * ============================================================= * The test case @@ -476,6 +476,10 @@ static DatagramPacket getPacket( return null; } + public void setSocketTimeout(int socketTimeout) { + this.socketTimeout = socketTimeout; + } + // run delegated tasks void runDelegatedTasks(SSLEngine engine) throws Exception { Runnable runnable; @@ -529,8 +533,8 @@ public final void runTest(DTLSOverDatagram testCase) throws Exception { try (DatagramSocket serverSocket = new DatagramSocket(serverSocketAddress); DatagramSocket clientSocket = new DatagramSocket(clientSocketAddress)) { - serverSocket.setSoTimeout(SOCKET_TIMEOUT); - clientSocket.setSoTimeout(SOCKET_TIMEOUT); + serverSocket.setSoTimeout(socketTimeout); + clientSocket.setSoTimeout(socketTimeout); InetSocketAddress serverSocketAddr = new InetSocketAddress( InetAddress.getLoopbackAddress(), serverSocket.getLocalPort()); diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java b/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java index 5dd897b1bd7..9c1c64f7fa0 100644 --- a/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java +++ b/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,4 +134,3 @@ private static void runTest(String[] serverSignatureSchemes, } } } - diff --git a/test/jdk/javax/net/ssl/DTLS/FragmentedFinished.java b/test/jdk/javax/net/ssl/DTLS/FragmentedFinished.java new file mode 100644 index 00000000000..2b6fd16005c --- /dev/null +++ b/test/jdk/javax/net/ssl/DTLS/FragmentedFinished.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8367133 + * @summary Verify that handshake succeeds when Finished message is fragmented + * @modules java.base/sun.security.util + * @library /test/lib + * @build DTLSOverDatagram + * @run main/othervm FragmentedFinished + */ + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import java.net.DatagramPacket; +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.List; + +public class FragmentedFinished extends DTLSOverDatagram { + private SSLEngine serverSSLEngine; + public static void main(String[] args) throws Exception { + FragmentedFinished testCase = new FragmentedFinished(); + testCase.runTest(testCase); + } + + @Override + SSLEngine createSSLEngine(boolean isClient) throws Exception { + SSLEngine sslEngine = super.createSSLEngine(isClient); + if (!isClient) { + serverSSLEngine = sslEngine; + } + return sslEngine; + } + + @Override + DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) { + if (ba.length < 30) { // detect ChangeCipherSpec + // Reduce the maximumPacketSize to force fragmentation + // of the Finished message + SSLParameters params = serverSSLEngine.getSSLParameters(); + params.setMaximumPacketSize(53); + serverSSLEngine.setSSLParameters(params); + } + + return super.createHandshakePacket(ba, socketAddr); + } +} diff --git a/test/jdk/javax/net/ssl/DTLS/PacketLossRetransmission.java b/test/jdk/javax/net/ssl/DTLS/PacketLossRetransmission.java index 24a12600087..2dd0de830f1 100644 --- a/test/jdk/javax/net/ssl/DTLS/PacketLossRetransmission.java +++ b/test/jdk/javax/net/ssl/DTLS/PacketLossRetransmission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * 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,37 +32,16 @@ * @library /test/lib * @build DTLSOverDatagram * - * @run main/othervm PacketLossRetransmission client 0 hello_request * @run main/othervm PacketLossRetransmission client 1 client_hello - * @run main/othervm PacketLossRetransmission client 2 server_hello - * @run main/othervm PacketLossRetransmission client 3 hello_verify_request - * @run main/othervm -Djdk.tls.client.enableSessionTicketExtension=false PacketLossRetransmission client 4 new_session_ticket - * @run main/othervm PacketLossRetransmission client 11 certificate - * @run main/othervm PacketLossRetransmission client 12 server_key_exchange - * @run main/othervm PacketLossRetransmission client 13 certificate_request - * @run main/othervm PacketLossRetransmission client 14 server_hello_done - * @run main/othervm PacketLossRetransmission client 15 certificate_verify * @run main/othervm PacketLossRetransmission client 16 client_key_exchange * @run main/othervm PacketLossRetransmission client 20 finished - * @run main/othervm PacketLossRetransmission client 21 certificate_url - * @run main/othervm PacketLossRetransmission client 22 certificate_status - * @run main/othervm PacketLossRetransmission client 23 supplemental_data * @run main/othervm PacketLossRetransmission client -1 change_cipher_spec - * @run main/othervm PacketLossRetransmission server 0 hello_request - * @run main/othervm PacketLossRetransmission server 1 client_hello * @run main/othervm PacketLossRetransmission server 2 server_hello * @run main/othervm PacketLossRetransmission server 3 hello_verify_request - * @run main/othervm -Djdk.tls.client.enableSessionTicketExtension=false PacketLossRetransmission server 4 new_session_ticket * @run main/othervm PacketLossRetransmission server 11 certificate * @run main/othervm PacketLossRetransmission server 12 server_key_exchange - * @run main/othervm PacketLossRetransmission server 13 certificate_request * @run main/othervm PacketLossRetransmission server 14 server_hello_done - * @run main/othervm PacketLossRetransmission server 15 certificate_verify - * @run main/othervm PacketLossRetransmission server 16 client_key_exchange * @run main/othervm PacketLossRetransmission server 20 finished - * @run main/othervm PacketLossRetransmission server 21 certificate_url - * @run main/othervm PacketLossRetransmission server 22 certificate_status - * @run main/othervm PacketLossRetransmission server 23 supplemental_data * @run main/othervm PacketLossRetransmission server -1 change_cipher_spec */ @@ -79,6 +58,7 @@ public class PacketLossRetransmission extends DTLSOverDatagram { private static boolean isClient; private static byte handshakeType; + private static final int TIMEOUT = 500; private boolean needPacketLoss = true; @@ -87,6 +67,7 @@ public static void main(String[] args) throws Exception { handshakeType = Byte.parseByte(args[1]); PacketLossRetransmission testCase = new PacketLossRetransmission(); + testCase.setSocketTimeout(TIMEOUT); testCase.runTest(testCase); } @@ -102,7 +83,7 @@ boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, if (packet != null) { needPacketLoss = false; - System.out.println("Loss a packet of handshake messahe"); + System.out.println("Loss a packet of handshake message"); packets.remove(packet); } } diff --git a/test/jdk/javax/net/ssl/SSLEngine/Basics.java b/test/jdk/javax/net/ssl/SSLEngine/Basics.java index 3239bfd4ce9..0ee7bfd7738 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/Basics.java +++ b/test/jdk/javax/net/ssl/SSLEngine/Basics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,8 @@ public class Basics { "/" + TRUSTSTORE_FILE; public static void main(String[] args) throws Exception { - SecurityUtils.removeFromDisabledTlsAlgs("TLSv1.1"); + // Re-enable TLSv1.1 and TLS_RSA_* since test depends on it. + SecurityUtils.removeFromDisabledTlsAlgs("TLSv1.1", "TLS_RSA_*"); runTest("TLSv1.3", "TLS_AES_256_GCM_SHA384"); runTest("TLSv1.2", "TLS_RSA_WITH_AES_256_GCM_SHA384"); diff --git a/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java b/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java index 7a4f71d8171..57eda1c2a42 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java +++ b/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * 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 @@ * @bug 8133632 * @summary javax.net.ssl.SSLEngine does not properly handle received * SSL fatal alerts - * @run main EngineCloseOnAlert + * @library /test/lib + * @run main/othervm EngineCloseOnAlert */ import java.io.FileInputStream; @@ -36,6 +37,7 @@ import java.util.*; import java.security.*; import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; +import jdk.test.lib.security.SecurityUtils; public class EngineCloseOnAlert { @@ -61,6 +63,8 @@ public interface TestCase { } public static void main(String[] args) throws Exception { + // Re-enable TLS_RSA_* since test depends on it. + SecurityUtils.removeFromDisabledTlsAlgs("TLS_RSA_*"); int failed = 0; List testMatrix = new LinkedList() {{ add(clientReceivesAlert); diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java index 4c8aba3de44..4ba3e906597 100644 --- a/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java index dcd62fcf8e7..2d271236de1 100644 --- a/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java index 04184e99306..1d37271ed53 100644 --- a/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java index 3f62fac8f77..c1bd53e21e9 100644 --- a/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java b/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java index fc5001e89b8..25f73606b96 100644 --- a/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java +++ b/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java b/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java index 9146e7b5f7b..0d910ccfb67 100644 --- a/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java +++ b/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java b/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java index 7dadeff5703..7f41cb1af79 100644 --- a/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java +++ b/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java b/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java index bac110aa033..5438f429455 100644 --- a/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java +++ b/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,4 +248,3 @@ protected void runClientApplication(SSLSocket socket) throws Exception { sslIS.read(); } } - diff --git a/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java b/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java index 12de3c0e096..1b3aef8b0fe 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java +++ b/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * 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,91 +50,91 @@ * @test * @bug 8205111 * @summary Test TLS with different types of supported keys. - * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 ec_rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 ecdsa_sha1 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 ecdsa_secp384r1_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ec_rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_sha1 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_secp384r1_sha384 * TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 ecdsa_secp521r1_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_secp521r1_sha512 * TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha256 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha384 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha512 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha256 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha384 TLS_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha512 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha256 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha384 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha512 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha256 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha384 TLS_AES_128_GCM_SHA256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha512 TLS_AES_128_GCM_SHA256 * - * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 ec_rsa_pkcs1_sha256 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 ecdsa_sha1 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 ecdsa_secp384r1_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ec_rsa_pkcs1_sha256 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_sha1 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_secp384r1_sha384 * TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 ecdsa_secp521r1_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_secp521r1_sha512 * TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha256 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha384 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha512 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha256 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha384 TLS_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha512 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha256 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha384 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha512 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha256 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha384 TLS_AES_256_GCM_SHA384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha512 TLS_AES_256_GCM_SHA384 * - * @run main/othervm TLSTest TLSv1.2 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm TLSTest TLSv1.2 rsa_pkcs1_sha256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pkcs1_sha256 * TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm TLSTest TLSv1.2 rsa_pkcs1_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pkcs1_sha384 * TLS_RSA_WITH_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.2 rsa_pkcs1_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pkcs1_sha512 * TLS_RSA_WITH_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.2 ec_rsa_pkcs1_sha256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 ec_rsa_pkcs1_sha256 * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * @run main/othervm TLSTest TLSv1.2 ecdsa_sha1 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 ecdsa_sha1 * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.2 ecdsa_secp384r1_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 ecdsa_secp384r1_sha384 * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * @run main/othervm TLSTest TLSv1.2 ecdsa_secp521r1_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 ecdsa_secp521r1_sha512 * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * @run main/othervm TLSTest TLSv1.2 rsa_pss_rsae_sha256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_rsae_sha256 * TLS_RSA_WITH_AES_256_CBC_SHA256 - * @run main/othervm TLSTest TLSv1.2 rsa_pss_rsae_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_rsae_sha384 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm TLSTest TLSv1.2 rsa_pss_rsae_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_rsae_sha512 * TLS_RSA_WITH_AES_128_CBC_SHA256 - * @run main/othervm TLSTest TLSv1.2 rsa_pss_pss_sha256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_pss_sha256 * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * @run main/othervm TLSTest TLSv1.2 rsa_pss_pss_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_pss_sha384 * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * @run main/othervm TLSTest TLSv1.2 rsa_pss_pss_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_pss_sha512 * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * - * @run main/othervm TLSTest TLSv1.1 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm TLSTest TLSv1.1 rsa_pkcs1_sha256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pkcs1_sha256 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm TLSTest TLSv1.1 rsa_pkcs1_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pkcs1_sha384 * TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm TLSTest TLSv1.1 rsa_pkcs1_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pkcs1_sha512 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm TLSTest TLSv1.1 rsa_pss_rsae_sha256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pss_rsae_sha256 * TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm TLSTest TLSv1.1 rsa_pss_rsae_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pss_rsae_sha384 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm TLSTest TLSv1.1 rsa_pss_rsae_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pss_rsae_sha512 * TLS_RSA_WITH_AES_128_CBC_SHA * - * @run main/othervm TLSTest TLSv1 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm TLSTest TLSv1 rsa_pkcs1_sha256 TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm TLSTest TLSv1 rsa_pkcs1_sha384 TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm TLSTest TLSv1 rsa_pkcs1_sha512 TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm TLSTest TLSv1 rsa_pss_rsae_sha256 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pkcs1_sha256 TLS_RSA_WITH_AES_256_CBC_SHA + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pkcs1_sha384 TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pkcs1_sha512 TLS_RSA_WITH_AES_256_CBC_SHA + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pss_rsae_sha256 * TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm TLSTest TLSv1 rsa_pss_rsae_sha384 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pss_rsae_sha384 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm TLSTest TLSv1 rsa_pss_rsae_sha512 + * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pss_rsae_sha512 * TLS_RSA_WITH_AES_128_CBC_SHA */ public class TLSTest { @@ -279,7 +279,7 @@ void doClientSide() throws Exception { keyType.getTrustedCert(), null, null, keyType.getKeyType()); SSLSocketFactory sslsf = ctx.getSocketFactory(); try (SSLSocket sslSocket - = (SSLSocket) sslsf.createSocket("localhost", serverPort)) { + = (SSLSocket) sslsf.createSocket(InetAddress.getLoopbackAddress(), serverPort)) { // Specify the client cipher suites sslSocket.setEnabledCipherSuites(new String[]{this.cipher}); sslSocket.setEnabledProtocols(new String[]{this.tlsProtocol}); diff --git a/test/jdk/javax/net/ssl/TLSv11/GenericBlockCipher.java b/test/jdk/javax/net/ssl/TLSv11/GenericBlockCipher.java index cb67903287e..a634424b3d7 100644 --- a/test/jdk/javax/net/ssl/TLSv11/GenericBlockCipher.java +++ b/test/jdk/javax/net/ssl/TLSv11/GenericBlockCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,8 +172,8 @@ void doClientSide() throws Exception { volatile Exception clientException = null; public static void main(String[] args) throws Exception { - // Re-enable TLSv1.1 since test depends on it. - SecurityUtils.removeFromDisabledTlsAlgs("TLSv1.1"); + // Re-enable TLSv1.1 and TLS_RSA_* since test depends on it. + SecurityUtils.removeFromDisabledTlsAlgs("TLSv1.1", "TLS_RSA_*"); String keyFilename = System.getProperty("test.src", ".") + "/" + pathToStores + diff --git a/test/jdk/javax/net/ssl/TLSv12/ProtocolFilter.java b/test/jdk/javax/net/ssl/TLSv12/ProtocolFilter.java index ec58bc74d0c..3291096af48 100644 --- a/test/jdk/javax/net/ssl/TLSv12/ProtocolFilter.java +++ b/test/jdk/javax/net/ssl/TLSv12/ProtocolFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * 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 @@ * @test * @bug 8052406 * @summary SSLv2Hello protocol may be filter out unexpectedly + * @library /test/lib * @run main/othervm ProtocolFilter */ @@ -35,6 +36,8 @@ import java.net.*; import javax.net.ssl.*; +import jdk.test.lib.security.SecurityUtils; + public class ProtocolFilter { /* @@ -156,6 +159,8 @@ void doClientSide() throws Exception { volatile Exception clientException = null; public static void main(String[] args) throws Exception { + // Re-enable TLS_RSA_* since test depends on it. + SecurityUtils.removeFromDisabledTlsAlgs("TLS_RSA_*"); String keyFilename = System.getProperty("test.src", ".") + "/" + pathToStores + "/" + keyStoreFile; diff --git a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java index 994169a7182..8db1dfdeac8 100644 --- a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java +++ b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * 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 8076221 8211883 8163327 8279164 + * @bug 8076221 8211883 8163327 8279164 8245545 * @summary Check if weak cipher suites are disabled * @library /javax/net/ssl/templates * @modules jdk.crypto.ec @@ -124,7 +124,13 @@ public class DisabledAlgorithms { "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" + "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA" }; public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java b/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java index caa96cdb224..847c69112a0 100644 --- a/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java +++ b/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * 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 4750141 4895631 8217579 8163326 8279164 + * @bug 4750141 4895631 8217579 8163326 8279164 8245545 * @summary Check enabled and supported ciphersuites are correct * @run main/othervm CheckCipherSuites default * @run main/othervm CheckCipherSuites limited @@ -99,12 +99,6 @@ public class CheckCipherSuites { "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", // deprecated - "TLS_RSA_WITH_AES_256_GCM_SHA384", - "TLS_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_CBC_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_256_CBC_SHA", - "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" }; @@ -124,9 +118,6 @@ public class CheckCipherSuites { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", - "TLS_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" }; @@ -194,12 +185,6 @@ public class CheckCipherSuites { "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", // deprecated - "TLS_RSA_WITH_AES_256_GCM_SHA384", - "TLS_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_CBC_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_256_CBC_SHA", - "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" }; @@ -219,9 +204,6 @@ public class CheckCipherSuites { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", - "TLS_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" }; diff --git a/test/jdk/javax/net/ssl/sanity/ciphersuites/SystemPropCipherSuitesOrder.java b/test/jdk/javax/net/ssl/sanity/ciphersuites/SystemPropCipherSuitesOrder.java index 2817e3400ab..6492e6508de 100644 --- a/test/jdk/javax/net/ssl/sanity/ciphersuites/SystemPropCipherSuitesOrder.java +++ b/test/jdk/javax/net/ssl/sanity/ciphersuites/SystemPropCipherSuitesOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ import java.util.Arrays; +import java.util.stream.Stream; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; @@ -86,8 +87,20 @@ public static void main(String[] args) { clientcipherSuites = toArray(System.getProperty("jdk.tls.client.cipherSuites")); System.out.printf("SYSTEM PROPERTIES: ServerProp:%s - ClientProp:%s%n", - Arrays.deepToString(servercipherSuites), - Arrays.deepToString(clientcipherSuites)); + Arrays.deepToString(servercipherSuites), + Arrays.deepToString(clientcipherSuites)); + + // Re-enable TLS_RSA_* cipher suites if needed since test depends on it. + if (Stream.concat( + Arrays.stream( + servercipherSuites == null + ? new String[0] : servercipherSuites), + Arrays.stream( + clientcipherSuites == null + ? new String[0] : clientcipherSuites)) + .anyMatch(s -> s.startsWith("TLS_RSA_"))) { + SecurityUtils.removeFromDisabledTlsAlgs("TLS_RSA_*"); + } try { new SystemPropCipherSuitesOrder(args[0]).run(); diff --git a/test/jdk/javax/net/ssl/sanity/ciphersuites/TLSCipherSuitesOrder.java b/test/jdk/javax/net/ssl/sanity/ciphersuites/TLSCipherSuitesOrder.java index c2171d80889..2ce46eb8471 100644 --- a/test/jdk/javax/net/ssl/sanity/ciphersuites/TLSCipherSuitesOrder.java +++ b/test/jdk/javax/net/ssl/sanity/ciphersuites/TLSCipherSuitesOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,8 @@ public class TLSCipherSuitesOrder extends SSLSocketTemplate { private final String[] clientcipherSuites; public static void main(String[] args) { + // Re-enable TLS_RSA_* since test depends on it. + SecurityUtils.removeFromDisabledTlsAlgs("TLS_RSA_*"); PROTOCOL protocol = PROTOCOL.valueOf(args[0]); try { new TLSCipherSuitesOrder(protocol.getProtocol(), diff --git a/test/jdk/javax/net/ssl/templates/SSLExampleCert.java b/test/jdk/javax/net/ssl/templates/SSLExampleCert.java index 0b82aed3b7b..46f69a62e41 100644 --- a/test/jdk/javax/net/ssl/templates/SSLExampleCert.java +++ b/test/jdk/javax/net/ssl/templates/SSLExampleCert.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java index ce1a99a7f1e..0891523ac11 100644 --- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java @@ -168,7 +168,7 @@ protected void configureServerSocket(SSLServerSocket socket) { /* * What's the server address? null means binding to the wildcard. */ - protected volatile InetAddress serverAddress = null; + protected volatile InetAddress serverAddress = InetAddress.getLoopbackAddress(); /* * Define the server side of the test. @@ -177,13 +177,8 @@ protected void doServerSide() throws Exception { // kick start the server side service SSLContext context = createServerSSLContext(); SSLServerSocketFactory sslssf = context.getServerSocketFactory(); - InetAddress serverAddress = this.serverAddress; - SSLServerSocket sslServerSocket = serverAddress == null ? - (SSLServerSocket)sslssf.createServerSocket(serverPort) - : (SSLServerSocket)sslssf.createServerSocket(); - if (serverAddress != null) { - sslServerSocket.bind(new InetSocketAddress(serverAddress, serverPort)); - } + SSLServerSocket sslServerSocket = (SSLServerSocket)sslssf.createServerSocket( + serverPort, 0, serverAddress); configureServerSocket(sslServerSocket); serverPort = sslServerSocket.getLocalPort(); @@ -271,10 +266,8 @@ protected void doClientSide() throws Exception { try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { try { configureClientSocket(sslSocket); - InetAddress serverAddress = this.serverAddress; - InetSocketAddress connectAddress = serverAddress == null - ? new InetSocketAddress(InetAddress.getLoopbackAddress(), serverPort) - : new InetSocketAddress(serverAddress, serverPort); + InetSocketAddress connectAddress = new InetSocketAddress(serverAddress, + serverPort); sslSocket.connect(connectAddress, 15000); } catch (IOException ioe) { // The server side may be impacted by naughty test cases or diff --git a/test/jdk/javax/print/PrintServiceLookup/CountPrintServices.java b/test/jdk/javax/print/PrintServiceLookup/CountPrintServices.java index 5be9f0297d2..4da1ed59a27 100644 --- a/test/jdk/javax/print/PrintServiceLookup/CountPrintServices.java +++ b/test/jdk/javax/print/PrintServiceLookup/CountPrintServices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * 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,25 +25,21 @@ import java.io.InputStreamReader; import javax.print.PrintService; import javax.print.PrintServiceLookup; -import javax.print.attribute.AttributeSet; -import javax.print.attribute.HashAttributeSet; -import javax.print.attribute.standard.PrinterName; +import java.io.IOException; + +import jtreg.SkippedException; /* * @test * @bug 8032693 * @key printer + * @library /test/lib/ + * @requires (os.family == "linux") * @summary Test that lpstat and JDK agree whether there are printers. */ public class CountPrintServices { public static void main(String[] args) throws Exception { - String os = System.getProperty("os.name").toLowerCase(); - System.out.println("OS is " + os); - if (!os.equals("linux")) { - System.out.println("Linux specific test. No need to continue"); - return; - } PrintService services[] = PrintServiceLookup.lookupPrintServices(null, null); if (services.length > 0) { @@ -51,7 +47,16 @@ public static void main(String[] args) throws Exception { return; } String[] lpcmd = { "lpstat", "-a" }; - Process proc = Runtime.getRuntime().exec(lpcmd); + Process proc; + try { + proc = Runtime.getRuntime().exec(lpcmd); + } catch (IOException e) { + if (e.getMessage().contains("No such file or directory")) { + throw new SkippedException("Cannot find lpstat"); + } else { + throw e; + } + } proc.waitFor(); InputStreamReader ir = new InputStreamReader(proc.getInputStream()); BufferedReader br = new BufferedReader(ir); @@ -66,4 +71,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java b/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java index 8f68773398c..6d500fea656 100644 --- a/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java +++ b/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * 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,4 +55,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java b/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java index ea8b1d1c145..64db7de2b18 100644 --- a/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java +++ b/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,4 +49,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/javax/security/auth/login/TEST.properties b/test/jdk/javax/security/auth/login/TEST.properties deleted file mode 100644 index 908b451f8ea..00000000000 --- a/test/jdk/javax/security/auth/login/TEST.properties +++ /dev/null @@ -1,2 +0,0 @@ -# disabled till JDK-8219408 is fixed -allowSmartActionArgs=false diff --git a/test/jdk/javax/sound/midi/BulkSoundBank/BulkSoundBank.java b/test/jdk/javax/sound/midi/BulkSoundBank/BulkSoundBank.java new file mode 100644 index 00000000000..259b5b5283c --- /dev/null +++ b/test/jdk/javax/sound/midi/BulkSoundBank/BulkSoundBank.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiSystem; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +/** + * @test + * @bug 8350813 + * @summary Rendering of bulky sound bank from MIDI sequence can cause OutOfMemoryError. + * @run main/othervm -Xmx1g BulkSoundBank + */ + +public class BulkSoundBank { + static final byte[] midi = {77, 84, 104, 100, 0, 0, 0, 6, 0, 0, 0, 1, 1, + -32, 77, 84, 114, 107, 0, 0, 0, 50, 0, -1, 88, 4, 4, 2, 24, 8, 0, -1, + 81, 3, 7, -95, 32, 0, -112, 60, 64, -125, 96, -128, 60, 64, -125, -44, + -51, 32, -112, 48, 64, 1, -128, 48, 64, -127, -64, -45, 127, -112, 60, + 64, 1, -128, 60, 64, 0, -1, 47, 0}; + + public static void main(String[] args) throws IOException { + try (ByteArrayInputStream bis = new ByteArrayInputStream(midi)) { + MidiSystem.getSoundbank(bis); + throw new RuntimeException("Test should throw InvalidMidiDataException" + + " but it did not."); + } catch (InvalidMidiDataException imda) { + System.out.println("Caught InvalidMidiDataException as expected"); + } + } +} + diff --git a/test/jdk/javax/swing/JButton/bug4151763.java b/test/jdk/javax/swing/JButton/bug4151763.java new file mode 100644 index 00000000000..d04b623ec4e --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4151763.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4151763 + * @summary Tests that button icon is not drawn upon button border + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException + * @run main/manual bug4151763 + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; +import jtreg.SkippedException; + +public class bug4151763 { + private static final int IMAGE_SIZE = 150; + private static final String INSTRUCTIONS = """ + Verify that image icon is NOT painted outside + the black rectangle. + + If above is true press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4151763::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception e) { + throw new SkippedException("Unsupported LaF", e); + } + + JFrame frame = new JFrame("bug4151763"); + final JButton b = new JButton(createImageIcon()); + b.setBorder(new CompoundBorder( + new EmptyBorder(20, 20, 20, 20), + new LineBorder(Color.BLACK))); + b.setPreferredSize(new Dimension(100, 100)); + + frame.setLayout(new FlowLayout()); + frame.add(b); + frame.setSize(400, 300); + return frame; + } + + private static ImageIcon createImageIcon() { + BufferedImage redImg = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE, + BufferedImage.TYPE_INT_RGB); + Graphics2D g = redImg.createGraphics(); + g.setColor(Color.RED); + g.fillRect(0, 0, IMAGE_SIZE, IMAGE_SIZE); + g.dispose(); + return new ImageIcon(redImg); + } +} diff --git a/test/jdk/javax/swing/JButton/bug4415505.java b/test/jdk/javax/swing/JButton/bug4415505.java new file mode 100644 index 00000000000..58ba56e1b74 --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4415505.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4415505 + * @requires (os.family == "windows") + * @summary Tests JButton appearance under Windows LAF + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4415505 + */ + +import java.awt.FlowLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToggleButton; +import javax.swing.UIManager; + +public class bug4415505 { + private static final String INSTRUCTIONS = """ + +

This test is for Windows LaF. + Press the button named "Button" using mouse and check that it has + "pressed" look. It should look like the selected toggle button + near it.

+ +

If above is true press PASS else FAIL.

+ + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .rows(5) + .columns(40) + .testUI(bug4415505::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JButton button = new JButton("Button"); + button.setFocusPainted(false); + JToggleButton tbutton = new JToggleButton("ToggleButton"); + tbutton.setSelected(true); + + JFrame jFrame = new JFrame("bug4415505"); + jFrame.setLayout(new FlowLayout(FlowLayout.CENTER)); + jFrame.add(button); + jFrame.add(tbutton); + jFrame.setSize(300, 100); + return jFrame; + } +} diff --git a/test/jdk/javax/swing/JButton/bug4978274.java b/test/jdk/javax/swing/JButton/bug4978274.java new file mode 100644 index 00000000000..6b152259caa --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4978274.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4978274 + * @summary Tests that JButton is painted with same visible height + * as toggle buttons + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4978274 + */ + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JToggleButton; +import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.OceanTheme; + +public class bug4978274 { + private static final String INSTRUCTIONS = """ + The toggle buttons must be painted to the same visible + height as button. In addition to that verify the following: + + a) All three buttons - "Button", "Toggle Btn" and + "Selected Toggle Btn" have the same border. + + b) Verify that when "Button" is pressed and moused over + it has the EXACT same border as "Toggle Btn" and + "Selected Toggle Btn" on press & mouse over. + + c) Click to the test window (panel) to disable/enable all + three buttons. In disabled state verify that all three + buttons have the exact same border. + + If all of the above conditions are true press PASS, else FAIL. + """; + + public static void main(String[] args) throws Exception { + MetalLookAndFeel.setCurrentTheme(new OceanTheme()); + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(createAndShowUI()) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4978274"); + frame.setLayout(new BorderLayout()); + + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + panel.setBorder(new EmptyBorder(12, 12, 12, 12)); + JButton jButton = new JButton("Button"); + JToggleButton jToggleButton = new JToggleButton("Selected Toggle Btn"); + jToggleButton.setSelected(true); + + panel.add(jButton); + panel.add(new JToggleButton("Toggle Btn")); + panel.add(jToggleButton); + + panel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent event) { + jButton.setEnabled(!jButton.isEnabled()); + jToggleButton.setEnabled(jButton.isEnabled()); + for(int i = 0; i < panel.getComponentCount(); i++) { + panel.getComponent(i).setEnabled(jButton.isEnabled()); + } + } + }); + + frame.add(panel); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java b/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java index 1efcfe58a31..d854961ea06 100644 --- a/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java +++ b/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 @@ /* @test * @bug 4449413 * @summary Tests that checkbox and radiobuttons' check marks are visible when background is black - * @author Ilya Boyandin * @run main/manual bug4449413 */ @@ -56,8 +55,16 @@ public class bug4449413 extends JFrame { + private static boolean isWindowsLF; + + private static String INSTRUCTIONS_WINDOWSLF = + "There are eight controls, JCheckBox/JRadioButton with black background\n" + + "and JRadioButtonMenuItem/JCheckboxMenuItem with gray background\n"; + private static final String INSTRUCTIONS = - "There are eight controls with black backgrounds.\n" + + "There are eight controls with black backgrounds.\n"; + + private static final String INSTRUCTIONS_COMMON = "Four enabled (on the left side) and four disabled (on the right side)\n" + "checkboxes and radiobuttons.\n\n" + "1. If at least one of the controls' check marks is not visible:\n" + @@ -82,6 +89,8 @@ boolean isMetalLookAndFeel() { } public static void main(String[] args) throws Exception { + isWindowsLF = "Windows".equals(UIManager.getLookAndFeel().getID()); + SwingUtilities.invokeLater(() -> { instance = new bug4449413(); instance.createAndShowGUI(); @@ -150,8 +159,10 @@ public void addComponentsToPane() { JTextArea instructionArea = new JTextArea( isMetalLookAndFeel() - ? INSTRUCTIONS + INSTRUCTIONS_ADDITIONS_METAL - : INSTRUCTIONS + ? INSTRUCTIONS + INSTRUCTIONS_COMMON + INSTRUCTIONS_ADDITIONS_METAL + : isWindowsLF + ? (INSTRUCTIONS_WINDOWSLF + INSTRUCTIONS_COMMON) + : (INSTRUCTIONS + INSTRUCTIONS_COMMON) ); instructionArea.setEditable(false); @@ -189,7 +200,13 @@ static AbstractButton createButton(int enabled, int type) { }; b.setOpaque(true); - b.setBackground(Color.black); + if (isWindowsLF + && ((b instanceof JRadioButtonMenuItem) + || (b instanceof JCheckBoxMenuItem))) { + b.setBackground(Color.lightGray); + } else { + b.setBackground(Color.black); + } b.setForeground(Color.white); b.setEnabled(enabled == 1); b.setSelected(true); diff --git a/test/jdk/javax/swing/JComboBox/bug4139900.java b/test/jdk/javax/swing/JComboBox/bug4139900.java new file mode 100644 index 00000000000..a9ed685d5ab --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4139900.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4139900 + * @summary height of combobox may differ + * @key headful + * @run main bug4139900 +*/ + +import java.awt.Dimension; +import java.awt.Robot; +import java.awt.event.ActionListener; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +public class bug4139900 { + static JButton button; + static JFrame frame; + static JComboBox comboBox; + static int initialHeight; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(bug4139900::init); + test(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + SwingUtilities.invokeAndWait(() -> initialHeight = comboBox.getHeight()); + + for (int i = 0; i < 10; i++) { + SwingUtilities.invokeAndWait(() -> button.doClick()); + robot.waitForIdle(); + robot.delay(200); + SwingUtilities.invokeAndWait(() -> { + if (comboBox.getHeight() != initialHeight) { + throw new RuntimeException( + "Test failed: height differs from initial %d != %d" + .formatted(comboBox.getHeight(), initialHeight) + ); + } + }); + } + } + + public static void init() { + frame = new JFrame("bug4139900"); + + DefaultComboBoxModel model = + new DefaultComboBoxModel<>(new String[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea" + }); + + comboBox = new JComboBox<>(); + comboBox.setEditable(true); + + button = new JButton("Add/Remove Items"); + + ActionListener actionListener = e -> { + if (comboBox.getModel() == model) { + comboBox.setModel(new DefaultComboBoxModel<>()); + } else { + comboBox.setModel(model); + } + }; + + button.addActionListener(actionListener); + + JPanel panel = new JPanel(); + panel.setPreferredSize(new Dimension(300, 100)); + panel.add(comboBox); + panel.add(button); + + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4174876.java b/test/jdk/javax/swing/JComboBox/bug4174876.java new file mode 100644 index 00000000000..349dfa4b159 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4174876.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4174876 + * @summary JComboBox tooltips do not work properly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4174876 + */ + +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JPanel; + +public class bug4174876 { + private static final String INSTRUCTIONS = """ + Hold the mouse over both combo boxes. + A tool tip should appear over every area of both of them. + Notably, if you hold the mouse over the button on the right one, + a tool tip should appear. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("TransparentTitleTest Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .splitUIBottom(bug4174876::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + JComboBox comboBox1 = new JComboBox<>(new String[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea" + }); + JComboBox comboBox2 = new JComboBox<>(new String[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea" + }); + + comboBox1.setToolTipText("Combo Box #1"); + comboBox2.setToolTipText("Combo Box #2"); + comboBox2.setEditable(true); + + JPanel panel = new JPanel(); + panel.add(comboBox1); + panel.add(comboBox2); + return panel; + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4474400.java b/test/jdk/javax/swing/JComboBox/bug4474400.java new file mode 100644 index 00000000000..ea52d0c71b5 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4474400.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4474400 + * @summary Tests JTextArea wrapping with font change + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4474400 + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTextArea; + +public class bug4474400 { + private static final String INSTRUCTIONS = """ + Press the "Change Font" button. The two lines of text should be + properly drawn using the larger font, there should be empty line + between them. If display is garbled, test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4474400 Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .splitUIRight(bug4474400::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + Font smallFont = new Font("SansSerif", Font.PLAIN, 12); + Font largeFont = new Font("SansSerif", Font.PLAIN, 36); + + JTextArea textArea = new JTextArea("This is the first line\n\nThis is the third line"); + textArea.setFont(smallFont); + textArea.setEditable(false); + textArea.setLineWrap(true); + textArea.setWrapStyleWord(true); + + JButton b = new JButton("Change Font"); + b.addActionListener((e) -> textArea.setFont(largeFont)); + + JPanel panel = new JPanel(new BorderLayout()); + panel.setPreferredSize(new Dimension(200, 300)); + panel.add(textArea, BorderLayout.CENTER); + panel.add(b, BorderLayout.SOUTH); + + return panel; + } +} diff --git a/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/ScrollToReferenceTest.java b/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/ScrollToReferenceTest.java new file mode 100644 index 00000000000..5d96dd70dd1 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/ScrollToReferenceTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4194428 + * @summary Checks that scrolling an href to visible scrolls it to the top of the page. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollToReferenceTest + */ + +import java.awt.Container; +import java.awt.Dimension; +import java.io.IOException; +import java.net.URL; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; + +public class ScrollToReferenceTest { + + static final String INSTRUCTIONS = """ + Wait for the html document to finish loading, click on the anchor + with text 'CLICK ME'. If 'should be at top of editor pane' is + scrolled to the top of the visible region of the text, click PASS, + otherwise click FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(ScrollToReferenceTest::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("ScrollToReferenceTest"); + JEditorPane pane = new JEditorPane(); + + try { + pane.setPage(ScrollToReferenceTest.class.getResource("test.html")); + } catch (IOException ioe) { + PassFailJFrame.forceFail("Couldn't find html file"); + } + + + pane.addHyperlinkListener(new HyperlinkListener() { + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED && + e.getURL() != null) { + try { + pane.setPage(e.getURL()); + } catch (IOException ioe) { + pane.setText("error finding url, click fail!"); + } + } + } + }); + pane.setEditable(false); + JScrollPane sp = new JScrollPane(pane); + sp.setPreferredSize(new Dimension(400, 400)); + frame.add(sp); + frame.setSize(400, 400); + return frame; + } +} diff --git a/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/test.html b/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/test.html new file mode 100644 index 00000000000..d7e82e516db --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/test.html @@ -0,0 +1,93 @@ + + +

Click ME! +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

should be at top of editor pane +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

TEST! +

a + + diff --git a/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java b/test/jdk/javax/swing/JFileChooser/FileFilterDescription.java similarity index 100% rename from test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java rename to test/jdk/javax/swing/JFileChooser/FileFilterDescription.java diff --git a/test/jdk/javax/swing/JFileChooser/HTMLFileName.java b/test/jdk/javax/swing/JFileChooser/HTMLFileName.java new file mode 100644 index 00000000000..a8bc9525cca --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/HTMLFileName.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.util.List; +import javax.swing.Icon; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.filechooser.FileSystemView; + +/* + * @test id=metal + * @bug 8139228 + * @summary JFileChooser should not render Directory names in HTML format + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual HTMLFileName metal + */ + +/* + * @test id=system + * @bug 8139228 8358532 + * @summary JFileChooser should not render Directory names in HTML format + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual HTMLFileName system + */ + +public class HTMLFileName { + private static final String INSTRUCTIONS = """ + +

    +
  1. JFileChooser shows a virtual directory. + The first file in the list has the following name: + <html><h1 color=#ff00ff><font + face="Serif">Swing Rocks! +
    +
    +
  2. In HTML disabled frame: +
      +
    1. Verify that the first file name displays + as plain text, + that is you see the HTML tags in the file name. +
    2. If the file name in the file pane and + in the navigation combo box above is displayed + as HTML, that is in large font and magenta color, + then press Fail. +
    + +
  3. In HTML enabled frame: +
      +
    1. Verify that the first file name displays as HTML, + that is Swing Rocks! in large font + and magenta color.
      + Note: On macOS in Aqua L&F, the file name with + HTML displays as an empty file name. It is not an error. +
    2. If the file name in the file pane and + in the navigation combo box above is displayed + as HTML, then press Pass.
      + If it is in plain text, then press Fail. +
    +
+ + """; + + public static void main(String[] args) throws Exception { + if (args.length < 1) { + throw new IllegalArgumentException("Look-and-Feel keyword is required"); + } + + final String lafClassName; + switch (args[0]) { + case "metal" -> lafClassName = UIManager.getCrossPlatformLookAndFeelClassName(); + case "system" -> lafClassName = UIManager.getSystemLookAndFeelClassName(); + default -> throw new IllegalArgumentException("Unsupported Look-and-Feel keyword: " + args[0]); + } + + SwingUtilities.invokeAndWait(() -> { + try { + UIManager.setLookAndFeel(lafClassName); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + System.out.println("Test for LookAndFeel " + lafClassName); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .rows(20) + .testUI(HTMLFileName::initialize) + .positionTestUIBottomRowCentered() + .build() + .awaitAndCheck(); + System.out.println("Test passed for LookAndFeel " + lafClassName); + } + + private static List initialize() { + return List.of(createFileChooser(true), createFileChooser(false)); + } + + private static JFrame createFileChooser(boolean htmlDisabled) { + JFileChooser jfc = new JFileChooser(new VirtualFileSystemView()); + jfc.putClientProperty("html.disable", htmlDisabled); + jfc.setControlButtonsAreShown(false); + + JFrame frame = new JFrame(htmlDisabled ? "HTML disabled" : "HTML enabled"); + frame.add(jfc); + frame.pack(); + return frame; + } + + private static class VirtualFileSystemView extends FileSystemView { + private final File[] files = { + new File("/", "

Swing Rocks!"), + new File("/", "virtualFile1.txt"), + new File("/", "virtualFile2.log") + }; + + @Override + public File createNewFolder(File containingDir) { + return null; + } + + @Override + public File[] getRoots() { + return files; + } + + @Override + public File getHomeDirectory() { + return new File("/"); + } + + @Override + public File getDefaultDirectory() { + return new File("/"); + } + + @Override + public File[] getFiles(File dir, boolean useFileHiding) { + // Simulate a virtual folder structure + return files; + } + + @Override + public Icon getSystemIcon(File f) { + return null; + } + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4357012.java b/test/jdk/javax/swing/JFileChooser/bug4357012.java new file mode 100644 index 00000000000..2dfdcd336d5 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4357012.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4357012 + * @requires (os.family == "windows") + * @summary JFileChooser.showSaveDialog inconsistent with Windows Save Dialog + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4357012 + */ + +import java.io.File; +import java.io.IOException; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class bug4357012 { + private static File workDir = null; + private static File dir = null; + private static File file = null; + private static final String INSTRUCTIONS = """ + + Test is for Windows LAF only +

In JFileChooser's files list : +

    +
  1. Select directory. Verify that the directory name doesn't + appear in "file name" field.
  2. +
  3. Select file. Verify that the file name appears in + "file name" field.
  4. +
  5. Select directory again. Verify that the previous file name + remains in file name field.
  6. +
+

+ + """; + + public static void main(String[] argv) throws Exception { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + createTestDir(); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .rows(10) + .columns(40) + .testUI(bug4357012::createTestUI) + .build() + .awaitAndCheck(); + } finally { + if (workDir != null) { + System.out.println("Deleting '" + file + "': " + file.delete()); + System.out.println("Deleting '" + dir + "': " + dir.delete()); + System.out.println("Deleting '" + workDir + "': " + workDir.delete()); + } + } + } + + private static void createTestDir() throws IOException { + String tempDir = "."; + String fs = System.getProperty("file.separator"); + + workDir = new File(tempDir + fs + "bug4357012"); + System.out.println("Creating '" + workDir + "': " + workDir.mkdir()); + + dir = new File(workDir + fs + "Directory"); + System.out.println("Creating '" + dir + "': " + dir.mkdir()); + + file = new File(workDir + fs + "File.txt"); + System.out.println("Creating '" + file + "': " + file.createNewFile()); + } + + private static JComponent createTestUI() { + JFileChooser fc = new JFileChooser(workDir); + fc.setDialogType(JFileChooser.SAVE_DIALOG); + return fc; + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4464774.java b/test/jdk/javax/swing/JFileChooser/bug4464774.java new file mode 100644 index 00000000000..368063e46cd --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4464774.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4464774 + * @requires (os.family == "windows") + * @summary JFileChooser: selection of left-side folder buttons shown incorrectly + in Windows L&F + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4464774 + */ + +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class bug4464774 { + private static final String INSTRUCTIONS = """ + Click any button from the buttons to the left + ("Documents", "Desktop", "My Computer" etc.) in FileChooser dialog. + When the button is toggled, it should be lowered and + should NOT have focus painted inside it (black dotted frame). + + If the above is true, press PASS else FAIL. + """; + + public static void main(String[] argv) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(65) + .rows(10) + .testUI(() -> { + JFileChooser jfc = new JFileChooser(); + jfc.setControlButtonsAreShown(false); + return jfc; + }) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4522756.java b/test/jdk/javax/swing/JFileChooser/bug4522756.java new file mode 100644 index 00000000000..87c430cfb1d --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4522756.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4522756 + * @requires (os.family == "windows") + * @summary Verifies that the Desktop icon is not missing when + JFileChooser is opened for the first time. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4522756 + */ + +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class bug4522756 { + private static final String INSTRUCTIONS = """ + Verify the following: + + 1. If Desktop icon image is present on the Desktop button + on the left panel of JFileChooser. + 2. Press Desktop button. Check that you actually + go up to the desktop. + + If the above is true, press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .rows(12) + .testUI(() -> { + JFileChooser jfc = new JFileChooser(); + jfc.setControlButtonsAreShown(false); + return jfc; + }) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4759934.java b/test/jdk/javax/swing/JFileChooser/bug4759934.java new file mode 100644 index 00000000000..08ccdebfb2b --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4759934.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key headful + * @bug 4759934 + * @summary windows activation problem + * @library /javax/swing/regtesthelpers + * @build Util + * @run main bug4759934 + */ + +import java.awt.Dialog; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class bug4759934 { + private static JFrame fr; + private static Dialog dlg; + private static JFileChooser jfc; + + private static JButton frameBtn; + private static JButton dialogBtn; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(bug4759934::createTestUI); + robot.waitForIdle(); + robot.delay(1000); + + Point frameBtnLoc = Util.getCenterPoint(frameBtn); + robot.mouseMove(frameBtnLoc.x, frameBtnLoc.y); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(500); + + Point dlgBtnLoc = Util.getCenterPoint(dialogBtn); + robot.mouseMove(dlgBtnLoc.x , dlgBtnLoc.y); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(500); + + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(500); + + SwingUtilities.invokeAndWait(() -> { + if (frameBtn.hasFocus() && !dialogBtn.hasFocus()) { + throw new RuntimeException("Test failed! Focus was passed back" + + " to Frame instead of Dialog"); + } + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (dlg != null) { + dlg.dispose(); + } + if (fr != null) { + fr.dispose(); + } + }); + } + } + + private static void createTestUI() { + fr = new JFrame("bug4759934 - JFrame"); + + frameBtn = new JButton("Show Dialog"); + frameBtn.addActionListener(e -> createDialog()); + fr.add(frameBtn); + + fr.setSize(300, 200); + fr.setLocationRelativeTo(null); + fr.setVisible(true); + } + + private static void createDialog() { + dlg = new JDialog(fr, "bug4759934 - JDialog"); + + dialogBtn = new JButton("Show FileChooser"); + dlg.add(dialogBtn); + + dialogBtn.addActionListener(e -> { + jfc = new JFileChooser(); + jfc.showOpenDialog(dlg); + }); + + dlg.setSize(300, 200); + dlg.setLocation(fr.getX() + fr.getWidth() + 10, fr.getY()); + dlg.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4926884.java b/test/jdk/javax/swing/JFileChooser/bug4926884.java new file mode 100644 index 00000000000..29d6c4e9134 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4926884.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4926884 + * @requires (os.family == "windows") + * @summary Win L&F: JFileChooser problems with "My Documents" folder + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4926884 + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class bug4926884 { + private static final String INSTRUCTIONS = """ + Validate next statements step by step: + + 1. In the file list there are several dirs and files (like "ski", + "Snowboard" etc.) + 2. Select "Details" view mode. + 3. Make file list in focus (e.g. by pressing mouse button) + 4. Press key "w" several times with delay LESS than 1 second. + Selection should be changed across files started with letter "w" + (without case sensitive). + 5. Press key "w" several times with delay MORE than 1 second. + Selection should be changed across files started with letter "w" + (without case sensitive). + 6. Type "winnt" (with delay less than 1 second between letters) - + directory "winnt" should be selected. + 7. Change conditions: + - Move column "Name" to the second position + - Change sort mode by clicking column "Size" + 8. Repeat items 4-6 + + If above is true press PASS else FAIL + """; + + private static final String[] DIRS = {"www", "winnt", "ski"}; + private static final String[] FILES = {"Window", "weel", "mice", + "Wall", "Snowboard", "wood"}; + private static final File testDir = new File("."); + + public static void main(String[] argv) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + try { + createTestDir(); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(() -> new JFileChooser(testDir)) + .build() + .awaitAndCheck(); + } finally { + deleteTempDir(); + } + } + + private static void createTestDir() throws IOException { + testDir.mkdir(); + + for (String dir : DIRS) { + new File(testDir, dir).mkdir(); + } + + for (int i = 0; i < FILES.length; i++) { + + try (OutputStream outputStream = new FileOutputStream( + new File(testDir, FILES[i]))) { + for (int j = 0; j < i * 1024; j++) { + outputStream.write('#'); + } + } + } + } + + private static void deleteTempDir() { + File[] files = testDir.listFiles(); + + for (File file : files) { + if (file != null) { + file.delete(); + } + } + + testDir.delete(); + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4943900.java b/test/jdk/javax/swing/JFileChooser/bug4943900.java new file mode 100644 index 00000000000..0cea17e764c --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4943900.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4943900 + * @summary Tests that FileFilter combo box is shown in FileChooser + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4943900 + */ + +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.filechooser.FileFilter; + +public class bug4943900 { + private static final String INSTRUCTIONS = """ + +
    +
  1. When the test runs, a JFileChooser will be displayed. +
  2. Ensure that there is a filter combo box with these two items: +
      +
    • Text Files (*.txt) + — [must be selected when the dialog opens] +
    • All Files +
    +
  3. Leave the Text files item selected and check that the + filter works: only *.txt files can appear in the file list. + You can navigate directories in the file chooser and find one + that contains some *.txt files to ensure they are shown in + the file list. On macOS when the text filter is applied verify + that the non-text files are greyed out. +
  4. Try switching the filters and ensure that the file list + is updated properly. +
  5. If the FileFilter works correctly, + press Pass else press Fail. +
+ + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + + PassFailJFrame.builder() + .title("bug4943900 Test Instructions") + .instructions(INSTRUCTIONS) + .rows(14) + .columns(50) + .testUI(bug4943900::createAndShowUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createAndShowUI() { + JFileChooser fc = new JFileChooser(); + fc.setControlButtonsAreShown(false); + TextFileFilter filter = new TextFileFilter(); + fc.setFileFilter(filter); + + JFrame frame = new JFrame("bug4943900 - JFileChooser"); + frame.add(fc); + frame.pack(); + return frame; + } + + private static final class TextFileFilter extends FileFilter { + @Override + public boolean accept(File f) { + if (f != null) { + if (f.isDirectory()) { + return true; + } + String extension = getExtension(f); + return extension != null && extension.equals("txt"); + } + return false; + } + + @Override + public String getDescription() { + return "Text Files (*.txt)"; + } + + private static String getExtension(File f) { + if (f != null) { + String filename = f.getName(); + int i = filename.lastIndexOf('.'); + if (i > 0 && i < filename.length() - 1) { + return filename.substring(i + 1).toLowerCase(); + } + } + return null; + } + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug5045464.java b/test/jdk/javax/swing/JFileChooser/bug5045464.java new file mode 100644 index 00000000000..0fbeedcec6b --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug5045464.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 5045464 + * @requires (os.family == "linux") + * @summary Regression: GTK L&F, JFileChooser shows "null/" in folder list + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug5045464 + */ + +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug5045464 { + private static final String INSTRUCTIONS = """ + When the filechooser appears check the directory list (the left list). + If it starts with two items: "./" (current directory) + and "../" (parent directory) press PASS. + If something else is here (e.g. "null/" instead of "./") + press FAIL. + """; + + public static void main(String[] argv) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug5045464::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + JFileChooser fc = new JFileChooser(); + fc.setControlButtonsAreShown(false); + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch (Exception ex) { + throw new RuntimeException("Test Failed!", ex); + } + SwingUtilities.updateComponentTreeUI(fc); + return fc; + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug6515169.java b/test/jdk/javax/swing/JFileChooser/bug6515169.java new file mode 100644 index 00000000000..98cd813eefb --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug6515169.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 6515169 + * @requires (os.family == "windows") + * @summary wrong grid header in JFileChooser + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6515169 + */ + +import javax.swing.ButtonGroup; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug6515169 { + private static JFrame frame; + private static final String INSTRUCTIONS = """ + This test is to verify JFileChooser on Windows and Metal LAF. + Use the "Change LaF" menu to switch between the 2 LaF + and verify the following. + + a. Change view mode to "Details" + b. Check that 4 columns appear: Name, Size, Type and Date Modified + c. Change current directory by pressing any available subdirectory + or by pressing button "Up One Level". + d. Check that still four columns exist. + + Change LaF and repeat the steps a-d. + If all conditions are true press PASS, else FAIL. + """; + + public static void main(String[] argv) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug6515169::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + frame = new JFrame("bug6515169"); + JMenuBar bar = new JMenuBar(); + JMenu lafMenu = new JMenu("Change LaF"); + ButtonGroup lafGroup = new ButtonGroup(); + JCheckBoxMenuItem lafItem1 = new JCheckBoxMenuItem("Window LaF"); + lafItem1.addActionListener(e -> + setLaF(UIManager.getSystemLookAndFeelClassName())); + lafGroup.add(lafItem1); + lafMenu.add(lafItem1); + + JCheckBoxMenuItem lafItem2 = new JCheckBoxMenuItem("Metal LaF"); + lafItem2.addActionListener(e -> + setLaF(UIManager.getCrossPlatformLookAndFeelClassName())); + lafGroup.add(lafItem2); + lafMenu.add(lafItem2); + + bar.add(lafMenu); + frame.setJMenuBar(bar); + + String dir = "."; + JFileChooser fc = new JFileChooser(dir); + fc.setControlButtonsAreShown(false); + frame.add(fc); + frame.pack(); + + return frame; + } + + private static void setLaF(String laf) { + try { + UIManager.setLookAndFeel(laf); + SwingUtilities.updateComponentTreeUI(frame); + } catch (Exception e) { + throw new RuntimeException("Test Failed!", e); + } + } +} diff --git a/test/jdk/javax/swing/JFileChooser/6798062/bug6798062.java b/test/jdk/javax/swing/JFileChooser/bug6798062.java similarity index 100% rename from test/jdk/javax/swing/JFileChooser/6798062/bug6798062.java rename to test/jdk/javax/swing/JFileChooser/bug6798062.java diff --git a/test/jdk/javax/swing/JFrame/bug4419914.java b/test/jdk/javax/swing/JFrame/bug4419914.java index 4574b1ac3d6..f87dcc8c468 100644 --- a/test/jdk/javax/swing/JFrame/bug4419914.java +++ b/test/jdk/javax/swing/JFrame/bug4419914.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * 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,55 +28,141 @@ * @library /java/awt/regtesthelpers * @build PassFailJFrame * @run main/manual bug4419914 -*/ + */ import java.awt.BorderLayout; import java.awt.ComponentOrientation; +import java.awt.Frame; +import java.awt.Window; +import java.util.List; +import java.util.Locale; import javax.swing.JButton; +import javax.swing.JDialog; import javax.swing.JFrame; -import java.util.Locale; +import javax.swing.JLabel; +import javax.swing.JWindow; public class bug4419914 { + private static JFrame frame; private static final String INSTRUCTIONS = """ - 1. You will see a frame with five buttons. - 2. Confirm that each button is placed as follows: - NORTH - END CENTER START - SOUTH - 3. Press the "NORTH" button and confirm the button is focused. - 4. Press TAB repeatedly and confirm that the TAB focus moves from right to left. - (NORTH - START - CENTER - END - SOUTH - NORTH - START - CENTER - ...) + This test verifies tab movement on RTL component orientation + in JWindow, JFrame and JDialog. + + When test starts 3 test windows are displayed - JFrame, JWindow and JDialog. + Follow the instructions below and if any condition does not hold + press FAIL. + + 1. Confirm that each button in the child window is placed as follows: + + For JFrame: + NORTH + END CENTER START + SOUTH + + For JWindow: + END CENTER START + QUIT + + For JDialog: + END CENTER START + + 3. Press on the "START" button in case of JWindow & JDialog and "NORTH" + in case of JFrame, confirm that the respective button is focused. + + 4. Press TAB repeatedly and confirm that the TAB focus moves + from right to left. + + For JFrame: + (NORTH - START - CENTER - END - SOUTH - NORTH - START - CENTER - ...) - If there's anything different from the above items, click Fail else click Pass."""; + For JWindow: + (START - CENTER - END - QUIT - START - CENTER - END - QUIT - ...) + + For JDialog: + (START - CENTER - END - START - CENTER - END - ...) + + If all of the above conditions are true press PASS else FAIL. + """; public static void main(String[] args) throws Exception { PassFailJFrame.builder() - .title("Tab movement Instructions") .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) - .columns(48) - .testUI(bug4419914::createTestUI) + .columns(45) + .testTimeOut(10) + .testUI(bug4419914::createAndShowUI) + .positionTestUI(WindowLayouts::rightOneColumn) .build() .awaitAndCheck(); } - private static JFrame createTestUI() { - JFrame frame = new JFrame("bug4419914"); + private static List createAndShowUI() { + return List.of(createJFrame(), createJWindow(), createJDialog()); + } + + private static JFrame createJFrame() { + frame = new JFrame("bug4419914 JFrame"); frame.setFocusCycleRoot(true); + // Tab movement set to RTL frame.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); frame.setLocale(Locale.ENGLISH); frame.enableInputMethods(false); + // Component placement within content pane set to RTL frame.getContentPane().setComponentOrientation( - ComponentOrientation.RIGHT_TO_LEFT); + ComponentOrientation.RIGHT_TO_LEFT); frame.getContentPane().setLocale(Locale.ENGLISH); - frame.getContentPane().setLayout(new BorderLayout()); + frame.setLayout(new BorderLayout()); frame.add(new JButton("SOUTH"), BorderLayout.SOUTH); frame.add(new JButton("CENTER"), BorderLayout.CENTER); frame.add(new JButton("END"), BorderLayout.LINE_END); frame.add(new JButton("START"), BorderLayout.LINE_START); frame.add(new JButton("NORTH"), BorderLayout.NORTH); - frame.setSize(300, 150); + frame.setSize(300, 160); return frame; } + + private static JWindow createJWindow() { + JWindow window = new JWindow(frame); + window.setFocusableWindowState(true); + // Tab movement set to RTL + window.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + window.setLocale(new Locale("en")); + window.enableInputMethods(false); + + // Component placement within content pane set to RTL + window.getContentPane().setComponentOrientation( + ComponentOrientation.RIGHT_TO_LEFT); + window.getContentPane().setLocale(new Locale("en")); + window.setLayout(new BorderLayout()); + window.add(new JLabel("bug4419914 JWindow"), BorderLayout.NORTH); + window.add(new JButton("START"), BorderLayout.LINE_START); + window.add(new JButton("CENTER"), BorderLayout.CENTER); + window.add(new JButton("END"), BorderLayout.LINE_END); + + JButton quitButton = new JButton("QUIT"); + quitButton.addActionListener(e1 -> window.dispose()); + window.add(quitButton, BorderLayout.SOUTH); + window.setSize(300, 153); + window.requestFocus(); + return window; + } + + private static JDialog createJDialog() { + JDialog dialog = new JDialog((Frame) null, "bug4419914 JDialog"); + // Tab movement set to RTL + dialog.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + dialog.setLocale(new Locale("en")); + dialog.enableInputMethods(false); + + // Component placement within content pane set to RTL + dialog.getContentPane().setComponentOrientation( + ComponentOrientation.RIGHT_TO_LEFT); + dialog.getContentPane().setLocale(new Locale("en")); + dialog.setLayout(new BorderLayout()); + dialog.add(new JButton("CENTER"), BorderLayout.CENTER); + dialog.add(new JButton("END"), BorderLayout.LINE_END); + dialog.add(new JButton("START"), BorderLayout.LINE_START); + dialog.setSize(300, 160); + return dialog; + } } diff --git a/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java b/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java index 81f5e0d0802..7c3732925be 100644 --- a/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java +++ b/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +import java.io.File; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Point; @@ -28,6 +29,7 @@ import java.awt.Robot; import java.awt.event.InputEvent; import java.awt.image.BufferedImage; +import javax.imageio.ImageIO; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; @@ -51,6 +53,7 @@ public class JInternalFrameDraggingTest { private static JInternalFrame internalFrame; private static int FRAME_SIZE = 500; private static Color BACKGROUND_COLOR = Color.ORANGE; + private static final int tolerance = 10; public static void main(String[] args) throws Exception { try { @@ -69,14 +72,24 @@ public static void main(String[] args) throws Exception { BufferedImage img = robot.createScreenCapture(rect); int testRGB = BACKGROUND_COLOR.getRGB(); + Color testColor = new Color(testRGB); for (int i = 1; i < size; i++) { int rgbCW = img.getRGB(i, size / 2); int rgbCH = img.getRGB(size / 2, i); - if (rgbCW != testRGB || rgbCH != testRGB) { + Color rgbCWColor = new Color(rgbCW); + Color rgbCHColor = new Color(rgbCH); + + if (Math.abs(rgbCWColor.getRed() - testColor.getRed()) > tolerance + || Math.abs(rgbCWColor.getGreen() - testColor.getGreen()) > tolerance + || Math.abs(rgbCWColor.getBlue() - testColor.getBlue()) > tolerance + || Math.abs(rgbCHColor.getRed() - testColor.getRed()) > tolerance + || Math.abs(rgbCHColor.getGreen() - testColor.getGreen()) > tolerance + || Math.abs(rgbCHColor.getBlue() - testColor.getBlue()) > tolerance) { System.out.println("i " + i + " rgbCW " + Integer.toHexString(rgbCW) + " testRGB " + Integer.toHexString(testRGB) + " rgbCH " + Integer.toHexString(rgbCH)); + ImageIO.write(img, "png", new File("JInternalFrameDraggingTest.png")); throw new RuntimeException("Background color is wrong!"); } } diff --git a/test/jdk/javax/swing/JInternalFrame/InternalFrameTitleButtonTest.java b/test/jdk/javax/swing/JInternalFrame/InternalFrameTitleButtonTest.java new file mode 100644 index 00000000000..55ea19de00f --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/InternalFrameTitleButtonTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8140527 + * @key headful + * @requires (os.family == "windows") + * @summary InternalFrame has incorrect title button width + * @run main InternalFrameTitleButtonTest + */ + +import java.awt.Component; +import java.awt.Robot; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.basic.BasicInternalFrameUI; + +public class InternalFrameTitleButtonTest { + + private static JFrame frame; + private static JInternalFrame iframe; + + public static void main(String[] args) throws Exception { + String osName = System.getProperty("os.name"); + if (!osName.toLowerCase().contains("win")) { + System.out.println("The test is applicable only for Windows."); + return; + } + + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"); + try { + test(2); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + try { + test(14); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + System.out.println("ok"); + } + + private static void test(final int widthAdd) throws Exception { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + + JDesktopPane pane = new JDesktopPane(); + frame.setContentPane(pane); + frame.setSize(400, 400); + frame.setVisible(true); + + iframe = new JInternalFrame("Mail Reader", true, + true, true, true); + iframe.setSize(200, 200); + pane.add(iframe); + iframe.setVisible(true); + }); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + JComponent title = ((BasicInternalFrameUI) iframe.getUI()).getNorthPane(); + for (int i = 0; i < title.getComponentCount(); i++) { + Component c = title.getComponent(i); + if (c instanceof JButton button + && !testButtonSize(button, widthAdd)) { + throw new RuntimeException("Wrong title icon size"); + } + } + }); + } + + private static boolean testButtonSize(final JButton button, + final int widthAdd) { + int height = UIManager.getInt("InternalFrame.titleButtonHeight") - 4; + Icon icon = button.getIcon(); + return height == button.getHeight() + && (height + widthAdd) == button.getWidth() + && height == icon.getIconHeight() + && (height + widthAdd) == icon.getIconWidth(); + } +} + diff --git a/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.java b/test/jdk/javax/swing/JInternalFrame/bug6726866.java similarity index 100% rename from test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.java rename to test/jdk/javax/swing/JInternalFrame/bug6726866.java diff --git a/test/jdk/javax/swing/JLabel/bug4106007.java b/test/jdk/javax/swing/JLabel/bug4106007.java new file mode 100644 index 00000000000..b78813809c1 --- /dev/null +++ b/test/jdk/javax/swing/JLabel/bug4106007.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4106007 + * @summary Multi-line JLabel is now supported for HTML labels. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4106007 + * */ + +import java.awt.BorderLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; + +public class bug4106007 { + + static final String INSTRUCTIONS = """ + The test window should have a label spanning multiple lines. + If it is press PASS, else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4106007::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Bug4106007"); + frame.setLayout(new BorderLayout()); + String str = ""; + String longLine = + "I hope multi-line JLabel is now supported and you can see several lines instead of one long line. "; + str += longLine; + str += longLine; + str += ""; + JLabel lab = new JLabel(str); + frame.add(lab, BorderLayout.NORTH); + frame.setSize(400, 400); + return frame; + } +} diff --git a/test/jdk/javax/swing/JLabel/bug4945795.java b/test/jdk/javax/swing/JLabel/bug4945795.java new file mode 100644 index 00000000000..56f6e0eb60f --- /dev/null +++ b/test/jdk/javax/swing/JLabel/bug4945795.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4945795 + * @summary With mnemonic hiding turned on, Java does not display all mnemonics with ALT key + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4945795 + * */ + +import java.awt.BorderLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.UIManager; + +public class bug4945795 { + + static final String INSTRUCTIONS = """ + This test is for the Swing Windows Look And Feel. + A test window will be displayed with the label 'Mnemonic Test' + Click the mouse in the test window to make sure it has keyboard focus. + Now press and hold the 'Alt' key. + An underline should be displayed below the initial 'M' character. + If it is press PASS, else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4945795::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame mainFrame = new JFrame("Bug4945795"); + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception ex) { + throw new RuntimeException("Can not set system look and feel"); + } + mainFrame.setLayout(new BorderLayout()); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JLabel label = new JLabel("Mnemonic test"); + label.setDisplayedMnemonic('M'); + mainFrame.add(label, BorderLayout.NORTH); + mainFrame.setSize(400, 300); + return mainFrame; + } +} diff --git a/test/jdk/javax/swing/JList/bug4193267.java b/test/jdk/javax/swing/JList/bug4193267.java new file mode 100644 index 00000000000..cb447644d15 --- /dev/null +++ b/test/jdk/javax/swing/JList/bug4193267.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4193267 + * @summary Tests that JList first and last visible indices are + * updated properly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4193267 + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.GridLayout; +import java.util.List; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +public class bug4193267 { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + Resize the frame "JList" with a different ways and scroll the list + (if it possible). The indices of first and last visible elements + should be indicated in the corresponding fields in "Index" frame. + If the indicated indices is not right then test fails. + + Note: + - the first and last visible indices should be -1 if nothing + is visible; + - the first or last visible cells may only be partially visible. + """; + PassFailJFrame.builder() + .title("bug4193267 Instructions") + .instructions(INSTRUCTIONS) + .positionTestUI(WindowLayouts::rightOneRow) + .columns(35) + .testUI(bug4193267::initialize) + .build() + .awaitAndCheck(); + } + + private static List initialize() { + String[] data = {"000000000000000", "111111111111111", + "222222222222222", "333333333333333", + "444444444444444", "555555555555555", + "666666666666666", "777777777777777", + "888888888888888", "999999999999999"}; + + JFrame[] fr = new JFrame[2]; + fr[0] = new JFrame("JList"); + JList lst = new JList(data); + lst.setLayoutOrientation(JList.VERTICAL_WRAP); + lst.setVisibleRowCount(4); + JScrollPane jsp = new JScrollPane(lst); + fr[0].add(jsp); + fr[0].setSize(400, 200); + + JPanel pL = new JPanel(); + pL.setLayout(new GridLayout(2, 1)); + pL.add(new JLabel("First Visible Index")); + pL.add(new JLabel("Last Visible Index")); + + JPanel p = new JPanel(); + p.setLayout(new GridLayout(2, 1)); + JTextField first = new JTextField("0", 2); + first.setEditable(false); + first.setBackground(Color.white); + p.add(first); + JTextField last = new JTextField("9", 2); + last.setEditable(false); + last.setBackground(Color.white); + p.add(last); + + fr[1] = new JFrame("Index"); + fr[1].setSize(200, 200); + fr[1].setLayout(new FlowLayout()); + fr[1].add(pL); + fr[1].add(p); + + jsp.getViewport().addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + first.setText(String.valueOf(lst.getFirstVisibleIndex())); + last.setText(String.valueOf(lst.getLastVisibleIndex())); + } + }); + List frameList = List.of(fr[0], fr[1]); + return frameList; + } +} diff --git a/test/jdk/javax/swing/JList/bug4249161.java b/test/jdk/javax/swing/JList/bug4249161.java new file mode 100644 index 00000000000..09bdd93600f --- /dev/null +++ b/test/jdk/javax/swing/JList/bug4249161.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4249161 + * @summary Tests that JList.setComponentOrientation() works correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4249161 + */ + +import java.awt.BorderLayout; +import java.awt.ComponentOrientation; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; + +public class bug4249161 { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. With a scroll bar, confirm that all words ("one" - "twenty") are + aligned at the left side of a list. + 2. Press "Change!" button. All words on the list should be moved + to the right side. + 3. Press the same button again. All words should be moved to the + left side. + + If all items in a list are moved as soon as "Change!" button is + pressed, test passes. + """; + PassFailJFrame.builder() + .title("bug4249161 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4249161::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + JFrame fr = new JFrame("bug4249161"); + + String[] data = {"one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", + "eleven", "twelve", "thirteen", "fourteen", "fifteen", + "sixteen", "seventeen", "eighteen", "nineteen", "twenty" + }; + final JList list = new JList(data); + list.setSize(200, 200); + list.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + JScrollPane pane = new JScrollPane(list); + fr.add(pane); + + JButton button = new JButton("Change!"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (list.getComponentOrientation() != + ComponentOrientation.RIGHT_TO_LEFT) { + list.setComponentOrientation + (ComponentOrientation.RIGHT_TO_LEFT); + } else { + list.setComponentOrientation + (ComponentOrientation.LEFT_TO_RIGHT); + } + } + }); + fr.add(button, BorderLayout.SOUTH); + fr.setSize(200, 300); + fr.setAlwaysOnTop(true); + return fr; + } +} diff --git a/test/jdk/javax/swing/JList/bug4618767.java b/test/jdk/javax/swing/JList/bug4618767.java new file mode 100644 index 00000000000..f01e20f365c --- /dev/null +++ b/test/jdk/javax/swing/JList/bug4618767.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4618767 + * @summary First letter navigation in JList interferes with mnemonics + * @key headful + * @run main bug4618767 + */ + +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingUtilities; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +public class bug4618767 { + private static JFrame f; + private static final JList list = new + JList(new String[] {"one", "two", "three", "four"}); + private static boolean menuSelected; + private static volatile boolean failed; + private static CountDownLatch listGainedFocusLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + try { + createUI(); + runTest(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } + + private static void createUI() throws Exception { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4618767"); + JMenu menu = new JMenu("File"); + menu.setMnemonic('F'); + JMenuItem menuItem = new JMenuItem("item"); + menu.add(menuItem); + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + f.setJMenuBar(menuBar); + + menu.addMenuListener(new MenuListener() { + public void menuCanceled(MenuEvent e) {} + public void menuDeselected(MenuEvent e) {} + public void menuSelected(MenuEvent e) { + menuSelected = true; + } + }); + + list.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + listGainedFocusLatch.countDown(); + } + }); + f.add(list); + f.pack(); + f.setLocationRelativeTo(null); + f.setAlwaysOnTop(true); + f.setVisible(true); + }); + } + + private static void runTest() throws Exception { + if (!listGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't gain" + + " focus for list"); + } + Robot robot = new Robot(); + robot.setAutoDelay(200); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_O); + robot.keyRelease(KeyEvent.VK_O); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_ALT); + + SwingUtilities.invokeAndWait(() -> { + if (menuSelected && list.getSelectedIndex()!= 0) { + failed = true; + } + }); + if (failed) { + throw new RuntimeException("Mnemonics interferes with Jlist" + + " item selection using KeyEvent"); + } + } +} diff --git a/test/jdk/javax/swing/JMenuBar/RightLeftOrientation.java b/test/jdk/javax/swing/JMenuBar/RightLeftOrientation.java index 80779c9ce1d..8308034d060 100644 --- a/test/jdk/javax/swing/JMenuBar/RightLeftOrientation.java +++ b/test/jdk/javax/swing/JMenuBar/RightLeftOrientation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * 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,75 +20,76 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + /* * @test * @bug 4211731 4214512 * @summary * This test checks if menu bars lay out correctly when their - * ComponentOrientation property is set to RIGHT_TO_LEFT. This test is - * manual. The tester is asked to compare left-to-right and - * right-to-left menu bars and judge whether they are mirror images of each - * other. + * ComponentOrientation property is set to RIGHT_TO_LEFT. + * The tester is asked to compare left-to-right and + * right-to-left menu bars and decide whether they are mirror + * images of each other. * @library /test/jdk/java/awt/regtesthelpers * @build PassFailJFrame * @run main/manual RightLeftOrientation */ import java.awt.ComponentOrientation; -import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.List; + import javax.swing.ButtonGroup; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.SwingUtilities; import javax.swing.UIManager; -public class RightLeftOrientation { +public final class RightLeftOrientation { - static JFrame ltrFrame; - static JFrame rtlFrame; + private static List frames; private static final String INSTRUCTIONS = """ - This test checks menu bars for correct Right-To-Left Component Orientation. - - You should see two frames, each containing a menu bar. + This test checks menu bars for correct Right-To-Left component orientation. - One frame will be labelled "Left To Right" and will contain + You should see two frames, each contains a menu bar. + One frame is labelled "Left To Right" and contains a menu bar with menus starting on its left side. - The other frame will be labelled "Right To Left" and will - contain a menu bar with menus starting on its right side. + The other frame is labelled "Right To Left" and + contains a menu bar with menus starting on its right side. - The test will also contain radio buttons that can be used to set - the look and feel of the menu bars. - For each look and feel, you should compare the two menu - bars and make sure they are mirror images of each other. """; + The test also displays a frame with radio buttons + to change the look and feel of the menu bars. + For each look and feel, compare the two menu bars + in LTR and RTL orientation and make sure they are mirror + images of each other."""; public static void main(String[] args) throws Exception { PassFailJFrame.builder() - .title("RTL test Instructions") + .title("Menu Bar RTL Instructions") .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) .columns(30) .testUI(RightLeftOrientation::createTestUI) + .positionTestUIRightColumn() .build() .awaitAndCheck(); } - private static JFrame createTestUI() { - JFrame frame = new JFrame("RightLeftOrientation"); + private static JFrame createPlafChangerFrame() { + JFrame frame = new JFrame("Change Look and Feel"); JPanel panel = new JPanel(); ButtonGroup group = new ButtonGroup(); - JRadioButton rb; ActionListener plafChanger = new PlafChanger(); UIManager.LookAndFeelInfo[] lafInfos = UIManager.getInstalledLookAndFeels(); for (int i = 0; i < lafInfos.length; i++) { - rb = new JRadioButton(lafInfos[i].getName()); + JRadioButton rb = new JRadioButton(lafInfos[i].getName()); rb.setActionCommand(lafInfos[i].getClassName()); rb.addActionListener(plafChanger); group.add(rb); @@ -99,33 +100,39 @@ private static JFrame createTestUI() { } frame.add(panel); + frame.pack(); + return frame; + } - ltrFrame = new JFrame("Left To Right"); + private static List createTestUI() { + JFrame plafFrame = createPlafChangerFrame(); + + JFrame ltrFrame = new JFrame("Left To Right"); ltrFrame.setJMenuBar(createMenuBar(ComponentOrientation.LEFT_TO_RIGHT)); ltrFrame.setSize(400, 100); - ltrFrame.setLocation(new Point(10, 10)); - ltrFrame.setVisible(true); - rtlFrame = new JFrame("Right To Left"); + JFrame rtlFrame = new JFrame("Right To Left"); rtlFrame.setJMenuBar(createMenuBar(ComponentOrientation.RIGHT_TO_LEFT)); rtlFrame.setSize(400, 100); - rtlFrame.setLocation(new Point(10, 120)); - rtlFrame.setVisible(true); - frame.pack(); - return frame; + + return (frames = List.of(plafFrame, ltrFrame, rtlFrame)); } - static class PlafChanger implements ActionListener { + private static final class PlafChanger implements ActionListener { + @Override public void actionPerformed(ActionEvent e) { String lnfName = e.getActionCommand(); try { UIManager.setLookAndFeel(lnfName); - SwingUtilities.updateComponentTreeUI(ltrFrame); - SwingUtilities.updateComponentTreeUI(rtlFrame); - } - catch (Exception exc) { - System.err.println("Could not load LookAndFeel: " + lnfName); + frames.forEach(SwingUtilities::updateComponentTreeUI); + } catch (Exception exc) { + String message = "Could not set Look and Feel to " + lnfName; + System.err.println(message); + JOptionPane.showMessageDialog(frames.get(0), + message, + "Look and Feel Error", + JOptionPane.ERROR_MESSAGE); } } diff --git a/test/jdk/javax/swing/JMenuItem/MenuItemTest/MenuItemTestHelper.java b/test/jdk/javax/swing/JMenuItem/MenuItemTest/MenuItemTestHelper.java new file mode 100644 index 00000000000..16b87490585 --- /dev/null +++ b/test/jdk/javax/swing/JMenuItem/MenuItemTest/MenuItemTestHelper.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.Graphics; +import java.awt.event.KeyEvent; +import javax.swing.Icon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; +import javax.swing.UIManager; + +final class MenuItemTestHelper { + + public static JFrame getMenuItemTestFrame(boolean isLeft, String lafName) { + boolean applyLookAndFeel = lafName != null; + if (applyLookAndFeel) { + try { + UIManager.setLookAndFeel(lafName); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + Icon myIcon = new ColoredIcon(Color.RED, 10, 10); + Icon myIcon2 = new ColoredIcon(Color.GREEN, 15, 10); + + JMenuBar menuBar = new JMenuBar(); + menuBar.add(createViewMenu(myIcon, myIcon2)); + menuBar.add(createNoNothingMenu()); + menuBar.add(createSomeIconsMenu(myIcon, myIcon2)); + + String title = (isLeft ? "(Left-to-right)" : "(Right-to-left)") + " - Menu Item Test"; + JFrame frame = new JFrame(title); + frame.setJMenuBar(menuBar); + frame.applyComponentOrientation(isLeft + ? ComponentOrientation.LEFT_TO_RIGHT + : ComponentOrientation.RIGHT_TO_LEFT); + + if (applyLookAndFeel) { + String shortName = lafName.substring(lafName.lastIndexOf('.') + 1); + JLabel label = new JLabel("

" + shortName + "

"); + frame.setLayout(new BorderLayout()); + frame.add(label, BorderLayout.CENTER); + } + + frame.setSize(300, 300); + return frame; + } + + public static JFrame getMenuItemTestFrame(boolean isLeft) { + return getMenuItemTestFrame(isLeft, null); + } + + private static JMenu createViewMenu(Icon myIcon, Icon myIcon2) { + JMenu menu = new JMenu("View"); + menu.setMnemonic('V'); + menu.add(new JMenuItem("Refresh")); + menu.add(new JMenuItem("Customize...")); + menu.add(new JCheckBoxMenuItem("Show Toolbar")); + menu.addSeparator(); + menu.add(new JRadioButtonMenuItem("List")); + menu.add(new JRadioButtonMenuItem("Icons")); + + JRadioButtonMenuItem rm2 = new JRadioButtonMenuItem("And icon."); + rm2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, KeyEvent.SHIFT_DOWN_MASK)); + rm2.setIcon(myIcon2); + menu.add(rm2); + + JRadioButtonMenuItem mi3 = new JRadioButtonMenuItem("Radio w/icon"); + mi3.setIcon(myIcon); + menu.add(mi3); + + menu.add(new JMenuItem(myIcon2)); + + JMenuItem mi4 = new JMenuItem("Item with icon"); + mi4.setIcon(myIcon); + menu.addSeparator(); + menu.add(mi4); + + return menu; + } + + private static JMenu createNoNothingMenu() { + final JMenu noMenu = new JMenu("No nothing"); + + for (String label : new String[]{"One", "Two", "Threeee"}) { + JMenuItem item = new JMenuItem(label); + item.addActionListener((e) -> + PassFailJFrame.log("menu.width = " + + noMenu.getPopupMenu().getWidth())); + noMenu.add(item); + } + + return noMenu; + } + + private static JMenu createSomeIconsMenu(Icon myIcon, Icon myIcon2) { + JMenu someIcons = new JMenu("Some icons"); + + JMenuItem imi1 = new JMenuItem("Icon!"); + imi1.setIcon(myIcon); + someIcons.add(imi1); + + JMenuItem imi2 = new JMenuItem("Wide icon!"); + imi2.setIcon(myIcon2); + someIcons.add(imi2); + + someIcons.add(new JCheckBoxMenuItem("CheckBox")); + someIcons.add(new JRadioButtonMenuItem("RadioButton")); + + return someIcons; + } + + private record ColoredIcon(Color color, int width, int height) + implements Icon { + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Color oldColor = g.getColor(); + g.setColor(color); + g.fillRect(x, y, width, height); + g.setColor(oldColor); + } + + @Override + public int getIconWidth() { + return width; + } + + @Override + public int getIconHeight() { + return height; + } + } +} diff --git a/test/jdk/javax/swing/JMenuItem/MenuItemTest/bug4729669.java b/test/jdk/javax/swing/JMenuItem/MenuItemTest/bug4729669.java new file mode 100644 index 00000000000..6518b6b8fae --- /dev/null +++ b/test/jdk/javax/swing/JMenuItem/MenuItemTest/bug4729669.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4729669 + * @summary 1.4 REGRESSION: Text edge of different types of JMenuItems are not aligned + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4729669 + */ + +import java.util.List; +import javax.swing.JFrame; + +public class bug4729669 { + + private static final String INSTRUCTIONS = """ + Two windows should appear: Left-to-right and Right-to-left. + Check that text on all the menu items of all menus + is properly vertically aligned."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4729669 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4729669::createTestUI) + .positionTestUIRightColumn() + .logArea() + .build() + .awaitAndCheck(); + } + + private static List createTestUI() { + JFrame f1 = MenuItemTestHelper.getMenuItemTestFrame(true); + JFrame f2 = MenuItemTestHelper.getMenuItemTestFrame(false); + return List.of(f1, f2); + } +} + diff --git a/test/jdk/javax/swing/JMenuItem/MenuItemTest/bug6197830.java b/test/jdk/javax/swing/JMenuItem/MenuItemTest/bug6197830.java new file mode 100644 index 00000000000..afb1c7bb33f --- /dev/null +++ b/test/jdk/javax/swing/JMenuItem/MenuItemTest/bug6197830.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 6197830 + * @requires (os.family == "linux") + * @summary Fix for 4729669 does not work on Motif and GTK look and feels + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6197830 + */ + +import java.util.List; +import javax.swing.JFrame; + +public class bug6197830 { + + private static final String INSTRUCTIONS = """ + Four windows should appear: Left-to-right and Right-to-left for + the two different Look and Feels (Motif and GTK). + Check that text on all the menu items of all menus is properly + vertically aligned."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug6197830 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug6197830::createTestUI) + .positionTestUIBottomRowCentered() + .build() + .awaitAndCheck(); + } + + private static List createTestUI() { + JFrame frame1 = MenuItemTestHelper.getMenuItemTestFrame(true, + "com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + JFrame frame2 = MenuItemTestHelper.getMenuItemTestFrame(false, + "com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + JFrame frame3 = MenuItemTestHelper.getMenuItemTestFrame(true, + "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + JFrame frame4 = MenuItemTestHelper.getMenuItemTestFrame(false, + "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + return List.of(frame1, frame2, frame3, frame4); + } +} diff --git a/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java b/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java index 6c7185b547a..7080f03ad2a 100644 --- a/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java +++ b/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java @@ -22,18 +22,36 @@ */ /* - * @test + * @test id=metal * @bug 4211052 * @requires (os.family == "windows") - * @summary - * This test checks if menu items lay out correctly when their + * @summary Verifies if menu items lay out correctly when their * ComponentOrientation property is set to RIGHT_TO_LEFT. - * The tester is asked to compare left-to-right and - * right-to-left menus and judge whether they are mirror images of each - * other. * @library /java/awt/regtesthelpers * @build PassFailJFrame - * @run main/manual RightLeftOrientation + * @run main/manual RightLeftOrientation metal + */ + +/* + * @test id=motif + * @bug 4211052 + * @requires (os.family == "windows") + * @summary Verifies if menu items lay out correctly when their + * ComponentOrientation property is set to RIGHT_TO_LEFT. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RightLeftOrientation motif + */ + +/* + * @test id=windows + * @bug 4211052 + * @requires (os.family == "windows") + * @summary Verifies if menu items lay out correctly when their + * ComponentOrientation property is set to RIGHT_TO_LEFT. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RightLeftOrientation windows */ import java.awt.Color; @@ -52,29 +70,47 @@ import javax.swing.JMenuItem; import javax.swing.JRadioButtonMenuItem; import javax.swing.KeyStroke; -import javax.swing.LookAndFeel; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import javax.swing.UIManager; public class RightLeftOrientation { private static final String INSTRUCTIONS = """ - A menu bar is shown containing a menu for each look and feel. - A disabled menu means that the look and feel is not available for - testing in this environment. - Every effort should be made to run this test - in an environment that covers all look and feels. + A menu bar is shown with a menu. - Each menu is divided into two halves. The upper half is oriented + The menu is divided into two halves. The upper half is oriented left-to-right and the lower half is oriented right-to-left. - For each menu, ensure that the lower half mirrors the upper half. + Ensure that the lower half mirrors the upper half. Note that when checking the positioning of the sub-menus, it helps to position the frame away from the screen edges."""; public static void main(String[] args) throws Exception { + if (args.length < 1) { + throw new IllegalArgumentException("Look-and-Feel keyword is required"); + } + + final String lafClassName; + switch (args[0]) { + case "metal" -> lafClassName = UIManager.getCrossPlatformLookAndFeelClassName(); + case "motif" -> lafClassName = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + case "windows" -> lafClassName = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; + default -> throw new IllegalArgumentException( + "Unsupported Look-and-Feel keyword for this test: " + args[0]); + } + + SwingUtilities.invokeAndWait(() -> { + try { + UIManager.setLookAndFeel(lafClassName); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + System.out.println("Test for LookAndFeel " + lafClassName); + PassFailJFrame.builder() - .title("RightLeftOrientation Instructions") .instructions(INSTRUCTIONS) .columns(35) .testUI(RightLeftOrientation::createTestUI) @@ -86,32 +122,19 @@ private static JFrame createTestUI() { JFrame frame = new JFrame("RightLeftOrientation"); JMenuBar menuBar = new JMenuBar(); - menuBar.add(createMenu("javax.swing.plaf.metal.MetalLookAndFeel", - "Metal")); - menuBar.add(createMenu("com.sun.java.swing.plaf.motif.MotifLookAndFeel", - "Motif")); - menuBar.add(createMenu("com.sun.java.swing.plaf.windows.WindowsLookAndFeel", - "Windows")); + menuBar.add(createMenu()); frame.setJMenuBar(menuBar); - frame.pack(); + frame.setSize(250, 70); return frame; } - static JMenu createMenu(String laf, String name) { - JMenu menu = new JMenu(name); - try { - LookAndFeel save = UIManager.getLookAndFeel(); - UIManager.setLookAndFeel(laf); - addMenuItems(menu, ComponentOrientation.LEFT_TO_RIGHT); - menu.addSeparator(); - addMenuItems(menu, ComponentOrientation.RIGHT_TO_LEFT); - UIManager.setLookAndFeel(save); - } catch (Exception e) { - menu = new JMenu(name); - menu.setEnabled(false); - } + static JMenu createMenu() { + JMenu menu = new JMenu(UIManager.getLookAndFeel().getID()); + addMenuItems(menu, ComponentOrientation.LEFT_TO_RIGHT); + menu.addSeparator(); + addMenuItems(menu, ComponentOrientation.RIGHT_TO_LEFT); return menu; } diff --git a/test/jdk/javax/swing/JMenuItem/bug4207339.java b/test/jdk/javax/swing/JMenuItem/bug4207339.java new file mode 100644 index 00000000000..e2e3ef4e3cd --- /dev/null +++ b/test/jdk/javax/swing/JMenuItem/bug4207339.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4207339 + * @summary Verifies HTML label support for MenuItems + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4207339 + */ + +import javax.swing.JPanel; +import javax.swing.JMenuItem; + +public class bug4207339 { + + private static final String INSTRUCTIONS = """ + This tests html support in menuItem. + A MenuItem will be shown. + If the MenuItem is showing "big" text bigger than rest + and "red" text in red color and the text are in multiple lines, + and text "Yo" in blue color, + then press Pass else press Fail."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4207339 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .splitUI(bug4207339::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JPanel createTestUI() { + JPanel panel = new JPanel(); + JMenuItem mi = new JMenuItem("
Is this text big" + + "and red?" + + "
And on multiple lines?

" + + "Yo!" + + "Then press PASS!
"); + panel.add(mi); + return panel; + } + +} diff --git a/test/jdk/javax/swing/JMenuItem/bug4327146.java b/test/jdk/javax/swing/JMenuItem/bug4327146.java new file mode 100644 index 00000000000..88d2b9618f0 --- /dev/null +++ b/test/jdk/javax/swing/JMenuItem/bug4327146.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4327146 + * @summary Tests menu width after removeAll() + * @key headful + * @run main bug4327146 + */ + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingUtilities; + +public class bug4327146 { + private static JButton b; + private static JMenu m; + private static JFrame frame; + private static volatile Point loc; + private static volatile Dimension dim; + private static volatile Rectangle old_popupBounds; + private static volatile Rectangle new_popupBounds; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4327146"); + m = new JMenu("Menu"); + m.add(new JMenuItem("I'm an ugly bug, fix me right now please!")); + + JMenuBar mbar = new JMenuBar(); + mbar.add(m); + frame.setJMenuBar(mbar); + + b = new JButton("Cut"); + b.addActionListener(e -> { + m.removeAll(); + m.add(new JMenuItem("Fixed :)")); + }); + mbar.add(b); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + loc = b.getLocationOnScreen(); + dim = b.getSize(); + m.doClick(); + }); + robot.waitForIdle(); + robot.delay(500); + SwingUtilities.invokeAndWait(() -> { + old_popupBounds = m.getPopupMenu().getBounds(); + }); + robot.mouseMove(loc.x + dim.width / 2, loc.y + dim.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(500); + SwingUtilities.invokeAndWait(() -> { + m.doClick(); + }); + robot.waitForIdle(); + robot.delay(500); + SwingUtilities.invokeAndWait(() -> { + new_popupBounds = m.getPopupMenu().getBounds(); + }); + if (new_popupBounds.getWidth() >= old_popupBounds.getWidth()) { + System.out.println("before cut popup Bounds " + old_popupBounds); + System.out.println("after cut popupBounds " + new_popupBounds); + throw new RuntimeException("JMenu popup width is wrong"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + +} diff --git a/test/jdk/javax/swing/JMenuItem/bug4402082.java b/test/jdk/javax/swing/JMenuItem/bug4402082.java new file mode 100644 index 00000000000..546a2d3218b --- /dev/null +++ b/test/jdk/javax/swing/JMenuItem/bug4402082.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4402082 + * @requires (os.family == "windows") + * @summary Tests that JMenuItem accelerator is rendered correctly. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4402082 + */ + +import java.awt.Container; +import java.awt.GridLayout; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; +import javax.swing.UIManager; + +public class bug4402082 { + + private static final String INSTRUCTIONS = """ + You see three menu items, each having different look-and-feels. + Each menu item should display accelerator "F1" on its right side. + The accelerator should be fully visible. If it is partially + offscreen, or not visible at all, test fails."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4402082 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4402082::createTestUI) + .build() + .awaitAndCheck(); + } + + static JMenuItem getMenuItem(String lnf) { + try { + UIManager.setLookAndFeel(lnf); + } catch (Exception exc) { + System.err.println("Could not load LookAndFeel: " + lnf); + } + JMenuItem mi = new JMenuItem("Bad Item"); + mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0)); + return mi; + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4402082"); + Container pane = frame.getContentPane(); + pane.setLayout(new GridLayout(3,1)); + pane.add(getMenuItem("javax.swing.plaf.metal.MetalLookAndFeel")); + pane.add(getMenuItem("com.sun.java.swing.plaf.motif.MotifLookAndFeel")); + pane.add(getMenuItem("com.sun.java.swing.plaf.windows.WindowsLookAndFeel")); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JMenuItem/bug4729669.java b/test/jdk/javax/swing/JMenuItem/bug4729669.java deleted file mode 100644 index 815558fc8fd..00000000000 --- a/test/jdk/javax/swing/JMenuItem/bug4729669.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact 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 4729669 - * @summary 1.4 REGRESSION: Text edge of different types of JMenuItems are not aligned - * @library /java/awt/regtesthelpers - * @build PassFailJFrame - * @run main/manual bug4729669 - */ - -import java.awt.Color; -import java.awt.ComponentOrientation; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; - -import javax.swing.AbstractAction; -import javax.swing.Icon; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.KeyStroke; - -import java.util.List; - -public class bug4729669 { - - private static final String INSTRUCTIONS = """ - Two windows should appear: Left-to-right and Right-to-left. - Check that text on all the menu items of all menus - is properly vertically aligned."""; - - public static void main(String[] args) throws Exception { - PassFailJFrame.builder() - .title("bug4729669 Instructions") - .instructions(INSTRUCTIONS) - .columns(35) - .testUI(bug4729669::createTestUI) - .position(PassFailJFrame.Position.TOP_LEFT_CORNER) - .logArea() - .build() - .awaitAndCheck(); - } - - private static List createTestUI() { - JFrame f1 = MenuItemTest.doMenuItemTest(true); - f1.setLocation(300, 300); - JFrame f2 = MenuItemTest.doMenuItemTest(false); - f2.setLocation(500, 300); - return List.of(f1, f2); - } -} - -class MenuItemTest { - public static JFrame doMenuItemTest(boolean isLeft) { - JMenu menu = new JMenu("View"); - menu.setMnemonic('V'); - - menu.add(new JMenuItem("Refresh")); - menu.add(new JMenuItem("Customize...")); - menu.add(new JCheckBoxMenuItem("Show Toolbar")); - menu.addSeparator(); - menu.add(new JRadioButtonMenuItem("List")); - menu.add(new JRadioButtonMenuItem("Icons")); - JRadioButtonMenuItem rm2 = new JRadioButtonMenuItem("And icon."); - rm2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, - KeyEvent.SHIFT_MASK)); - menu.add(rm2); - JRadioButtonMenuItem mi3 = new JRadioButtonMenuItem("Radio w/icon"); - - Icon myIcon = new Icon() { // 10 pixel red - public void paintIcon(Component c, Graphics g, int x, int y) { - Color color = g.getColor(); - g.setColor(Color.RED); - g.fillRect(x, y, 10, 10); - g.setColor(color); - } - - public int getIconWidth() { - return 10; - } - - public int getIconHeight() { - return 10; - } - }; - - Icon myIcon2 = new Icon() { // 15 pixel green - public void paintIcon(Component c, Graphics g, int x, int y) { - Color color = g.getColor(); - g.setColor(Color.GREEN); - g.fillRect(x, y, 15, 10); - g.setColor(color); - } - - public int getIconWidth() { - return 15; - } - - public int getIconHeight() { - return 10; - } - }; - - rm2.setIcon(myIcon2); - - mi3.setIcon(myIcon); - menu.add(mi3); - menu.add(new JMenuItem(myIcon2)); - - final JMenu menu2 = new JMenu("No nothing"); - menu2.add("One").addActionListener(new AbstractAction() { - public void actionPerformed(ActionEvent e) { - PassFailJFrame.log("menu.width = " + menu2.getPopupMenu().getWidth()); - } - }); - menu2.add("Two").addActionListener(new AbstractAction() { - public void actionPerformed(ActionEvent e) { - PassFailJFrame.log("menu.width = " + menu2.getPopupMenu().getWidth()); - } - }); - menu2.add("Threeee").addActionListener(new AbstractAction() { - public void actionPerformed(ActionEvent e) { - PassFailJFrame.log("menu.width = " + menu2.getPopupMenu().getWidth()); - } - }); - - JMenuItem mi4 = new JMenuItem("Item with icon"); - mi4.setIcon(myIcon); - menu.addSeparator(); - menu.add(mi4); - String title = "Menu Item Test " + (isLeft ? "(Left-to-right)" : "(Right-to-left)"); - JFrame frame = new JFrame(title); - - JMenuBar menuBar = new JMenuBar(); - menuBar.add(menu); - menuBar.add(menu2); - - JMenu someIcons = new JMenu("Some icons"); - JMenuItem imi1 = new JMenuItem("Icon!"); - imi1.setIcon(myIcon); - someIcons.add(imi1); - JMenuItem imi2 = new JMenuItem("Wide icon!"); - imi2.setIcon(myIcon2); - someIcons.add(imi2); - someIcons.add(new JCheckBoxMenuItem("CheckBox")); - someIcons.add(new JRadioButtonMenuItem("RadioButton")); - menuBar.add(someIcons); - frame.setJMenuBar(menuBar); - ComponentOrientation co = (isLeft ? - ComponentOrientation.LEFT_TO_RIGHT : - ComponentOrientation.RIGHT_TO_LEFT); - frame.applyComponentOrientation(co); - frame.setSize(300, 300); - int frameX = isLeft ? 0 : 600; - frame.setLocation(frameX, 20); - return frame; - } - -} diff --git a/test/jdk/javax/swing/JOptionPane/bug4194862.java b/test/jdk/javax/swing/JOptionPane/bug4194862.java new file mode 100644 index 00000000000..2a2822ebf1d --- /dev/null +++ b/test/jdk/javax/swing/JOptionPane/bug4194862.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4194862 + * @summary Tests that internal frame-based dialogs are centered relative + to their parents + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4194862 + */ + +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JOptionPane; + +public class bug4194862 { + private static final String INSTRUCTIONS = """ + In the internal frame titled "Main", + click the "Show JOptionPane Dialog" button. + A dialog will appear. It should be centered with + respect to the JInternalFrame - "Main". + + If the above is true then click on JOptionPane's "YES" button + to PASS else click JOptionPane's "NO" button to FAIL the test. + """; + + public static void main(String[] args) throws Exception{ + PassFailJFrame.builder() + .title("Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4194862::createAndShowUI) + .screenCapture() + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4194862 - JInternalFrame JOptionPane"); + JDesktopPane desktop = new JDesktopPane(); + frame.add(desktop); + JInternalFrame jInternalFrame = new JInternalFrame("Main", true); + desktop.add(jInternalFrame); + jInternalFrame.setBounds(5, 30, 390, 240); + jInternalFrame.setVisible(true); + + JButton b = new JButton("Show JOptionPane Dialog"); + b.addActionListener(e -> { + int retVal = JOptionPane.showInternalConfirmDialog( + jInternalFrame, "Am I centered?", + "bug4194862 JOptionPane", JOptionPane.YES_NO_OPTION); + switch (retVal) { + case JOptionPane.YES_OPTION -> PassFailJFrame.forcePass(); + case JOptionPane.NO_OPTION -> + PassFailJFrame.forceFail("JOptionPane isn't centered" + + " within JInternalFrame \"Main\""); + } + }); + jInternalFrame.add(b); + + for (int i = 0; i < 4; i++) { + JInternalFrame f = new JInternalFrame("JIF: "+ i); + f.setBounds(i * 50, i * 33, 120, 120); + f.setVisible(true); + desktop.add(f); + } + frame.setSize(450, 400); + return frame; + } +} diff --git a/test/jdk/javax/swing/JPasswordField/PasswordFieldInputMapWordTest.java b/test/jdk/javax/swing/JPasswordField/PasswordFieldInputMapWordTest.java new file mode 100644 index 00000000000..c49e9f7083c --- /dev/null +++ b/test/jdk/javax/swing/JPasswordField/PasswordFieldInputMapWordTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key headful + * @bug 8358813 + * @summary Password fields' InputMap should not include any word-related action. + * + * @run main PasswordFieldInputMapWordTest + */ + +import java.util.Collection; +import java.util.Set; + +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JPasswordField; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.text.DefaultEditorKit; + +public class PasswordFieldInputMapWordTest { + public static void main(String[] args) throws Exception { + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + System.out.println("Testing LAF: " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> { + if (setLookAndFeel(laf)) { + runTest(); + } + }); + } + } + + private static boolean setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + return true; + } catch (UnsupportedLookAndFeelException e) { + System.err.println("Skipping unsupported look and feel:"); + e.printStackTrace(); + return false; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + static int[] inputMapConditions = new int[] { + JComponent.WHEN_IN_FOCUSED_WINDOW, + JComponent.WHEN_FOCUSED, + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT + }; + + /** + * These are all the actions with "word" in their field name. + */ + static Collection wordActions = Set.of( + DefaultEditorKit.deleteNextWordAction, + DefaultEditorKit.deletePrevWordAction, + DefaultEditorKit.beginWordAction, + DefaultEditorKit.endWordAction, + DefaultEditorKit.selectionBeginWordAction, + DefaultEditorKit.selectionEndWordAction, + DefaultEditorKit.previousWordAction, + DefaultEditorKit.nextWordAction, + DefaultEditorKit.selectionPreviousWordAction, + DefaultEditorKit.selectionNextWordAction + ); + + private static void runTest() { + JPasswordField field = new JPasswordField(); + + boolean testPassed = true; + for (int condition : inputMapConditions) { + InputMap inputMap = field.getInputMap(condition); + if (inputMap.allKeys() == null) { + continue; + } + for (KeyStroke keyStroke : inputMap.allKeys()) { + Object actionBinding = inputMap.get(keyStroke); + if (wordActions.contains(actionBinding)) { + if (testPassed) { + System.err.println("The following inputs/actions should not be available in a JPasswordField:"); + } + System.err.println(inputMap.get(keyStroke) + " (try typing " + keyStroke + ")"); + testPassed = false; + } + } + } + + if (!testPassed) { + throw new RuntimeException("One or more input/action binding was observed for a JPasswordField."); + } + } +} diff --git a/test/jdk/javax/swing/JPasswordField/bug4382819.java b/test/jdk/javax/swing/JPasswordField/bug4382819.java new file mode 100644 index 00000000000..3a8799a2d52 --- /dev/null +++ b/test/jdk/javax/swing/JPasswordField/bug4382819.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.FlowLayout; +import java.awt.event.ItemListener; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JPasswordField; + +/* + * @test + * @bug 4382819 + * @summary Tests the correctness of color used for the disabled passwordField. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4382819 + */ + +public class bug4382819 { + static JCheckBox enabledCheckBox; + static JPasswordField passwordField; + + private static final String INSTRUCTIONS = """ + Clear the "enabled" checkbox. + If the JPasswordField's foreground color changes to + light gray press Pass. If it stays black press Fail. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4382819::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame mainFrame = new JFrame("bug4382819"); + enabledCheckBox = new javax.swing.JCheckBox(); + enabledCheckBox.setSelected(true); + enabledCheckBox.setText("enabled"); + enabledCheckBox.setActionCommand("enabled"); + mainFrame.add(enabledCheckBox); + + passwordField = new javax.swing.JPasswordField(); + passwordField.setText("blahblahblah"); + mainFrame.add(passwordField); + SymItem lSymItem = new SymItem(); + enabledCheckBox.addItemListener(lSymItem); + + mainFrame.setSize(300, 100); + mainFrame.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + return mainFrame; + } + + static class SymItem implements ItemListener { + public void itemStateChanged(java.awt.event.ItemEvent event) { + Object object = event.getSource(); + if (object == enabledCheckBox) { + passwordField.setEnabled(enabledCheckBox.isSelected()); + } + } + } +} + diff --git a/test/jdk/javax/swing/JPopupMenu/bug4119993.java b/test/jdk/javax/swing/JPopupMenu/bug4119993.java new file mode 100644 index 00000000000..1fe72ea29d6 --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4119993.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4119993 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Check that mouse button 3 is reserved for popup invocation not selection. + * @run main/manual bug4119993 + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.border.BevelBorder; + +/* + * This is a sort of negative test. Mouse Button 3 is not supposed to cause selections. + * If it did, then it would not be useable to invoke popup menus. + * So this popup menu test .. does not popup menus. + */ + +public class bug4119993 { + + static final String INSTRUCTIONS = """ + + The test window contains a text area, a table, and a list. +

+ For each component, try to select text/cells/rows/items as appropriate + using the RIGHT mouse button (Mouse Button 3). +

+ If the selection changes, then press FAIL. +

+ If the selection does not change, press PASS + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4119993::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("bug4119993"); + JPanel p = new JPanel(); + p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); + frame.add(p); + + String text = "This is some text that you should try to select using the right mouse button"; + JTextArea area = new JTextArea(text, 5, 40); + JScrollPane scrollpane0 = new JScrollPane(area); + scrollpane0.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane0.setPreferredSize(new Dimension(430, 200)); + p.add(scrollpane0); + + String[][] data = new String[5][5]; + String[] cols = new String[5]; + for (int r = 0; r < 5; r ++) { + cols[r] = "col " + r; + for (int c = 0; c < 5; c ++) { + data[r][c] = "(" + r + "," + c + ")"; + } + } + + JTable tableView = new JTable(data, cols); + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + p.add(scrollpane); + + String[] s = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; + JList listView = new JList(s); + JScrollPane scrollpane2 = new JScrollPane(listView); + scrollpane2.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane2.setPreferredSize(new Dimension(430, 200)); + p.add(scrollpane2); + + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4187004.java b/test/jdk/javax/swing/JPopupMenu/bug4187004.java new file mode 100644 index 00000000000..40a6633c130 --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4187004.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4187004 + @summary test that title/label is show on menu for Motif L&F + @key headful +*/ + +import java.awt.Dimension; +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4187004 { + + static volatile JPopupMenu m; + static volatile Dimension d1, d2; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(bug4187004::createUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + d1 = m.getSize(); + SwingUtilities.invokeAndWait(bug4187004::hideMenu); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(bug4187004::updateUI); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(bug4187004::showMenu); + robot.waitForIdle(); + robot.delay(1000); + d2 = m.getSize(); + } finally { + SwingUtilities.invokeAndWait(bug4187004::hideMenu); + } + System.out.println(d1); + System.out.println(d2); + if (d1.width <= d2.width) { + throw new RuntimeException("Menu not updated"); + } + } + + static void createUI() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + m = new JPopupMenu("One really long menu title"); + m.add("Item 1"); + m.add("Item 2"); + m.add("Item 3"); + m.add("Item 4"); + m.pack(); + m.setVisible(true); + } + + static void hideMenu() { + m.setVisible(false); + } + + static void showMenu() { + m.setVisible(true); + } + + static void updateUI() { + m.setLabel("short"); + m.pack(); + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4188832.java b/test/jdk/javax/swing/JPopupMenu/bug4188832.java new file mode 100644 index 00000000000..9c958ebc1ef --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4188832.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 that medium weight submenus are not hidden by a heavyweight canvas. + * @bug 4188832 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4188832 + */ + +import java.awt.Color; +import java.awt.Panel; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +public class bug4188832 { + + static final String INSTRUCTIONS = """ + Select the File menu, then select the "Save As..." submenu. + If you can see the submenu items displayed, press PASS, else press FAIL + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4188832::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + // for Medium Weight menus + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + JFrame frame = new JFrame("bug4188832"); + + // Create the menus + JMenuBar menuBar = new JMenuBar(); + JMenu fileMenu = new JMenu("File"); + menuBar.add(fileMenu); + fileMenu.add(new JMenuItem("New")); + fileMenu.add(new JMenuItem("Open")); + fileMenu.add(new JMenuItem("Save")); + JMenu sm = new JMenu("Save As..."); + // these guys don't show up + sm.add(new JMenuItem("This")); + sm.add(new JMenuItem("That")); + fileMenu.add(sm); + fileMenu.add(new JMenuItem("Exit")); + frame.setJMenuBar(menuBar); + + Panel field = new Panel(); // a heavyweight container + field.setBackground(Color.blue); + frame.add(field); + frame.setSize(400, 400); + return frame; + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4212464.java b/test/jdk/javax/swing/JPopupMenu/bug4212464.java new file mode 100644 index 00000000000..c1c434f6b16 --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4212464.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4212464 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Verify popup menu borders are drawn correctly when switching L&Fs + * @run main/manual bug4212464 + */ + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4212464 extends JFrame implements ActionListener { + + static String strMotif = "Motif"; + static String motifClassName = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + + static String strMetal = "Metal"; + static String metalClassName = "javax.swing.plaf.metal.MetalLookAndFeel"; + + static bug4212464 frame; + static JPopupMenu popup; + + static final String INSTRUCTIONS = """ + This test is to see whether popup menu borders behave properly when switching + back and forth between Motif and Metal L&F. The initial L&F is Metal. + + Pressing the mouse button on the label in the center of the test window brings + up a popup menu. + + In order to test, use the labeled buttons to switch the look and feel. + Clicking a button will cause the menu to be hidden. This is OK. Just click the label again. + Switch back and forth and verify that the popup menu border changes consistently + and there is a title for the menu when using Motif L&F (Metal won't have a title). + + Make sure you switch back and forth several times. + If the change is consistent, press PASS otherwise press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4212464::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + try { + UIManager.setLookAndFeel(metalClassName); // initialize to Metal. + } catch (Exception e) { + throw new RuntimeException(e); + } + frame = new bug4212464("bug4212464"); + popup = new JPopupMenu("Test"); + popup.add("Item 1"); + popup.add("Item 2"); + popup.add("Item 3"); + popup.add("Item 4"); + + JPanel p = new JPanel(); + p.setLayout(new FlowLayout()); + JButton motif = (JButton)p.add(new JButton(strMotif)); + JButton metal = (JButton)p.add(new JButton(strMetal)); + motif.setActionCommand(motifClassName); + metal.setActionCommand(metalClassName); + motif.addActionListener(frame); + metal.addActionListener(frame); + frame.add(BorderLayout.NORTH, p); + + JLabel l = new JLabel("Click any mouse button on this big label"); + l.setFont(new Font(Font.DIALOG, Font.PLAIN, 20)); + l.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + popup.show(e.getComponent(), e.getX(), e.getY()); + } + }); + frame.add(BorderLayout.CENTER, l); + frame.setSize(500, 400); + return frame; + } + + public bug4212464(String title) { + super(title); + } + + public void actionPerformed(ActionEvent e) { + String str = e.getActionCommand(); + if (str.equals(metalClassName) || str.equals(motifClassName)) { + changeLNF(str); + } else { + System.out.println("ActionEvent: " + str); + } + } + + public void changeLNF(String str) { + System.out.println("Changing LNF to " + str); + try { + UIManager.setLookAndFeel(str); + SwingUtilities.updateComponentTreeUI(frame); + SwingUtilities.updateComponentTreeUI(popup); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4234793.java b/test/jdk/javax/swing/JPopupMenu/bug4234793.java new file mode 100644 index 00000000000..9ad91e5165f --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4234793.java @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4234793 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary PopupMenuListener popupMenuCanceled is never called + * @run main/manual bug4234793 + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.KeyStroke; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +/** + * For all 3 components (JPopupMenu, JComboBox, JPopup) when the popup is visible, + * the popupMenuCanceled should be invoked in these two circumstances: + * + * 1. The ESCAPE key is pressed while the popup is open. + * + * 2. The mouse is clicked on another component. + * + */ + +public class bug4234793 extends JFrame implements PopupMenuListener { + + static final String INSTRUCTIONS = """ + The test window will contain several kinds of menus. + + * A menu bar with two menus labeled "1 - First Menu" and "2 - Second Menu" + * A drop down combo box - ie a button which pops up a menu when clicked + * Clicking any where on the background of the window will display a popup menu + + That is 4 menus in total. + + For each case, verify that the menu can be cancelled (hidden) in two ways + 1) Click to display the menu, then to hide it, press the ESCAPE key. + 2) Click to display the menu, then to hide it, LEFT click on the window background. + Note : the popup menu must be displayed using RIGHT click, the others use LEFT click. + + Notice each time you perform a hide/cancel action an appropriate message should + appear in the log area + If this is true for all 8 combinations of menus + hide actions the test PASSES + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4234793::createUI) + .logArea() + .build() + .awaitAndCheck(); + } + + private static String[] numData = { + "One", "Two", "Three", "Four", "Five", "Six", "Seven" + }; + + private static String[] dayData = { + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + }; + + private static char[] mnDayData = { + 'M', 'T', 'W', 'R', 'F', 'S', 'U' + }; + + bug4234793(String title) { + super(title); + } + + static volatile JPopupMenu popupMenu; + static volatile bug4234793 frame; + + static JFrame createUI() { + frame = new bug4234793("bug4234793"); + frame.setJMenuBar(createMenuBar()); + JPanel panel = createContentPane(); + frame.add(panel); + + // CTRL-down will show the popup. + panel.getInputMap().put(KeyStroke.getKeyStroke( + KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP"); + panel.getActionMap().put("OPEN_POPUP", new PopupHandler()); + panel.addMouseListener(new PopupListener(popupMenu)); + panel.setPreferredSize(new Dimension(400, 300)); + frame.setSize(400, 300); + return frame; + } + + static class PopupListener extends MouseAdapter { + private JPopupMenu popup; + + public PopupListener(JPopupMenu popup) { + this.popup = popup; + } + + public void mousePressed(MouseEvent e) { + maybeShowPopup(e); + } + + public void mouseReleased(MouseEvent e) { + maybeShowPopup(e); + } + + public void mouseClicked(MouseEvent ex) { + } + + private void maybeShowPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(e.getComponent(), e.getX(), e.getY()); + } + } + } + + static class PopupHandler extends AbstractAction { + public void actionPerformed(ActionEvent e) { + if (!popupMenu.isVisible()) + popupMenu.show((Component)e.getSource(), 40, 40); + } + } + + static JPanel createContentPane() { + popupMenu = new JPopupMenu(); + JMenuItem item; + for (int i = 0; i < dayData.length; i++) { + item = popupMenu.add(new JMenuItem(dayData[i], mnDayData[i])); + } + popupMenu.addPopupMenuListener(frame); + + JComboBox combo = new JComboBox(numData); + combo.addPopupMenuListener(frame); + JPanel comboPanel = new JPanel(); + comboPanel.add(combo); + + JPanel panel = new JPanel(new BorderLayout()); + + panel.add(new JLabel("Right click on the panel to show the PopupMenu"), BorderLayout.NORTH); + panel.add(comboPanel, BorderLayout.CENTER); + + return panel; + } + + static JMenuBar createMenuBar() { + JMenuBar menubar = new JMenuBar(); + JMenuItem menuitem; + + JMenu menu = new JMenu("1 - First Menu"); + menu.setMnemonic('1'); + menu.getPopupMenu().addPopupMenuListener(frame); + + menubar.add(menu); + for (int i = 0; i < 10; i ++) { + menuitem = new JMenuItem("1 JMenuItem" + i); + menuitem.setMnemonic('0' + i); + menu.add(menuitem); + } + + // second menu + menu = new JMenu("2 - Second Menu"); + menu.getPopupMenu().addPopupMenuListener(frame); + menu.setMnemonic('2'); + + menubar.add(menu); + for (int i = 0; i < 5; i++) { + menuitem = new JMenuItem("2 JMenuItem" + i); + menuitem.setMnemonic('0' + i); + menu.add(menuitem); + } + + JMenu submenu = new JMenu("Sub Menu"); + submenu.setMnemonic('S'); + submenu.getPopupMenu().addPopupMenuListener(frame); + for (int i = 0; i < 5; i++) { + menuitem = new JMenuItem("S JMenuItem" + i); + menuitem.setMnemonic('0' + i); + submenu.add(menuitem); + } + menu.add(new JSeparator()); + menu.add(submenu); + + return menubar; + } + + // PopupMenuListener methods. + + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("popupmenu visible: " + source.getClass().getName()); + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("popupMenuWillBecomeInvisible: " + source.getClass().getName()); + } + + public void popupMenuCanceled(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("POPUPMENU CANCELED: " + source.getClass().getName()); + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4530303.java b/test/jdk/javax/swing/JPopupMenu/bug4530303.java new file mode 100644 index 00000000000..c99dacc7cff --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4530303.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4530303 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Tests JPopupMenu.pack() + * @run main/manual bug4530303 + */ + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +public class bug4530303 { + + static final String INSTRUCTIONS = """ + The test window has a menu bar. + Open the menu "Menu" and place the mouse pointer over the first menu item, "Point here". + The second menu item, "Ghost", should be replaced with another item, "Fixed!". + If the item just disappears and no new item appears in the empty space, the test FAILS. + """; + + static volatile JMenu menu; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4530303::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("bug4530303"); + menu = new JMenu("Menu"); + JMenuItem item = new JMenuItem("Point here"); + item.addMouseListener(new MenuBuilder()); + menu.add(item); + menu.add(new JMenuItem("Ghost")); + + JMenuBar mbar = new JMenuBar(); + mbar.add(menu); + frame.setJMenuBar(mbar); + frame.setSize(300, 300); + return frame; + } + + static class MenuBuilder extends MouseAdapter { + public void mouseEntered(MouseEvent ev) { + menu.remove(1); + menu.add(new JMenuItem("Fixed!")); + + JPopupMenu pm = menu.getPopupMenu(); + pm.pack(); + pm.paintImmediately(pm.getBounds()); + } + } +} diff --git a/test/jdk/javax/swing/JProgressBar/RightLeftOrientation.java b/test/jdk/javax/swing/JProgressBar/RightLeftOrientation.java new file mode 100644 index 00000000000..5cc183b1e8e --- /dev/null +++ b/test/jdk/javax/swing/JProgressBar/RightLeftOrientation.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4230355 + * @summary + * This test checks if progress bars lay out correctly when their + * ComponentOrientation property is set to RIGHT_TO_LEFT. This test is + * manual. The tester is asked to compare left-to-right and + * right-to-left progress bars and judge whether they are mirror images + * of each other. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RightLeftOrientation + */ + +import java.awt.ComponentOrientation; +import java.awt.Container; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.LookAndFeel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.UIManager; + +public class RightLeftOrientation { + + static final String INSTRUCTIONS = """ + This test checks progress bars for correct Right-To-Left Component Orientation. + The progress bars in the left column should fill up from the left while the bars in + the right column should fill up from the right. + If this is so, the test PASSES, otherwise it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Progress Bar Orientation Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(RightLeftOrientation::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Progress Bar Orientation Test"); + Container contentPane = frame.getContentPane(); + contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS)); + contentPane.add(createBarSet(ComponentOrientation.LEFT_TO_RIGHT)); + contentPane.add(createBarSet(ComponentOrientation.RIGHT_TO_LEFT)); + frame.pack(); + return frame; + } + + static JPanel createBarSet(ComponentOrientation o) { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + JLabel header; + if (o.isLeftToRight()) + header = new JLabel("Left To Right"); + else + header = new JLabel("Right To Left"); + panel.add(header); + + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels(); + for (int i = 0; i < lafs.length; i++) { + if (i > 0) + panel.add(Box.createVerticalStrut(10)); + panel.add(createProgressBars(lafs[i].getName(), + lafs[i].getClassName(), o)); + } + + return panel; + } + + static JPanel createProgressBars(String name, String plaf, + ComponentOrientation o) { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + JLabel label = new JLabel(name); + panel.add(label); + try { + LookAndFeel save = UIManager.getLookAndFeel(); + UIManager.setLookAndFeel(plaf); + + panel.add(createProgressBar(true, 0, o)); + panel.add(Box.createVerticalStrut(5)); + + panel.add(createProgressBar(true, 5, o)); + panel.add(Box.createVerticalStrut(5)); + + panel.add(createProgressBar(true, 10, o)); + panel.add(Box.createVerticalStrut(5)); + + panel.add(createProgressBar(true, 20, o)); + panel.add(Box.createVerticalStrut(5)); + + UIManager.put("ProgressBar.cellSpacing", Integer.valueOf(2)); + UIManager.put("ProgressBar.cellLength", Integer.valueOf(7)); + + panel.add(createProgressBar(false, 5, o)); + panel.add(Box.createVerticalStrut(5)); + + panel.add(createProgressBar(false, 20, o)); + + UIManager.setLookAndFeel(save); + } catch (Exception e) { + System.err.println(e); + } + return panel; + } + + static JProgressBar createProgressBar(boolean paintStr, int value, + ComponentOrientation o) { + JProgressBar p = new JProgressBar(JProgressBar.HORIZONTAL, 0, 20); + p.setStringPainted(paintStr); + p.setValue(value); + p.setComponentOrientation(o); + return p; + } + +} diff --git a/test/jdk/javax/swing/JProgressBar/bug4230391.java b/test/jdk/javax/swing/JProgressBar/bug4230391.java new file mode 100644 index 00000000000..473862d83a3 --- /dev/null +++ b/test/jdk/javax/swing/JProgressBar/bug4230391.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4230391 + * @summary Tests that JProgressBar draws correctly when Insets are not zero + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4230391 +*/ + +import java.awt.ComponentOrientation; +import java.awt.Container; +import java.awt.Insets; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.LookAndFeel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.UIManager; + +public class bug4230391 { + + static final String INSTRUCTIONS = """ + Tests that progress bars honor insets in different L&Fs. + Different L&Fs render the progress bar differently, and may or may + not have a different colored background around the progress bar, + and may or may not draw a border around the bar+background. + The progress bars should be of equal width and the progress + rendering line/bar should not extend past/overlap any border. + If it is as described, the test PASSES. + """; + + static class InsetProgressBar extends JProgressBar { + private Insets insets = new Insets(12, 12, 12, 12); + + public InsetProgressBar(boolean horiz, int low, int hi) { + super((horiz)?JProgressBar.HORIZONTAL:JProgressBar.VERTICAL, low, hi); + } + + public Insets getInsets() { + return insets; + } + } + + static JPanel createBarSet() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createEmptyBorder(20,20,20,20)); + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels(); + for (int i = 0; i < lafs.length; i++) { + if (i > 0) { + panel.add(Box.createVerticalStrut(10)); + } + panel.add(createProgressBars(lafs[i].getName(), lafs[i].getClassName())); + } + return panel; + } + + static JPanel createProgressBars(String name, String plaf) { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); + try { + LookAndFeel save = UIManager.getLookAndFeel(); + UIManager.setLookAndFeel(plaf); + + ComponentOrientation ltr = ComponentOrientation.LEFT_TO_RIGHT; + + Box b = Box.createVerticalBox(); + panel.add(b); + panel.add(Box.createHorizontalStrut(5)); + panel.add(createProgressBar(false, true, ltr)); + UIManager.setLookAndFeel(save); + } catch (Exception e) { + System.err.println(e); + } + return panel; + } + + static JProgressBar createProgressBar(boolean solid, boolean horiz, + ComponentOrientation o) { + if (solid) { + UIManager.put("ProgressBar.cellSpacing", Integer.valueOf(0)); + UIManager.put("ProgressBar.cellLength", Integer.valueOf(1)); + } else { + UIManager.put("ProgressBar.cellSpacing", Integer.valueOf(2)); + UIManager.put("ProgressBar.cellLength", Integer.valueOf(7)); + } + + JProgressBar p = new InsetProgressBar(horiz, 0, 20); + p.setStringPainted(solid); + p.setValue(20); + p.setComponentOrientation(o); + + return p; + } + + static JFrame createUI() { + JFrame frame = new JFrame("Progress Bar Insets Test"); + Container contentPane = frame.getContentPane(); + contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS)); + contentPane.add(createBarSet()); + frame.setSize(400, 300); + return frame; + } + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Progress Bar Insets Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4230391::createUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JProgressBar/bug4393042.java b/test/jdk/javax/swing/JProgressBar/bug4393042.java new file mode 100644 index 00000000000..f17d70a1309 --- /dev/null +++ b/test/jdk/javax/swing/JProgressBar/bug4393042.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4393042 + * @summary JProgressBar should update painting when maximum value is very large + * @key headful + */ + +import java.awt.Graphics; +import javax.swing.JFrame; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4393042 extends JProgressBar { + + static final int MAXIMUM = Integer.MAX_VALUE - 100; + static volatile int value = 0; + static volatile bug4393042 progressBar; + static JFrame frame; + static volatile int paintCount = 0; + + public void paintComponent(Graphics g) { + super.paintComponent(g); + System.out.println("paint count=" + (++paintCount)); + } + + public bug4393042(int min, int max) { + super(min, max); + } + + public static void main(String[] args) throws Exception { + + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + try { + SwingUtilities.invokeAndWait(bug4393042::createUI); + + value = 0; + for (int i = 0; i <= 10; i++) { + Thread.sleep(1000); + SwingUtilities.invokeAndWait(() -> { + progressBar.setValue(value); + }); + value += MAXIMUM / 10; + } + + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + if (paintCount < 10 || paintCount > 100) { + throw new RuntimeException("Unexpected paint count : " + paintCount); + } + } + + static void createUI() { + frame = new JFrame("bug4393042"); + progressBar = new bug4393042(0, MAXIMUM); + progressBar.setStringPainted(true); + progressBar.setValue(0); + frame.add(progressBar); + frame.setSize(400, 200); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JProgressBar/bug5003022.java b/test/jdk/javax/swing/JProgressBar/bug5003022.java new file mode 100644 index 00000000000..57f5fdfc45d --- /dev/null +++ b/test/jdk/javax/swing/JProgressBar/bug5003022.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 5003022 + * @summary Test that setting zero value on JProgressBar works in GTK L&F + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug5003022 +*/ + +import java.awt.FlowLayout; +import javax.swing.JFrame; +import javax.swing.JProgressBar; +import javax.swing.UIManager; + +public class bug5003022 { + + static final String INSTRUCTIONS = """ + There are two progress bars, they should display progress strings. + The first progress bar should display 0% and the bar should show no progress color fill. + The second progress bar should display 30% and the bar should show 30% progress color fill. + If it is as described, the test PASSES, otherwise it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug5003022 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug5003022::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + try { + /* This will only succeed on Linux, but the test is valid for other platforms and L&Fs */ + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch (Exception e) { + e.printStackTrace(); + } + + JFrame frame = new JFrame("bug5003022"); + JProgressBar pb1 = new JProgressBar(); + pb1.setValue(0); + pb1.setStringPainted(true); + + JProgressBar pb2 = new JProgressBar(); + pb2.setValue(30); + pb2.setStringPainted(true); + + frame.setLayout(new FlowLayout()); + frame.add(pb1); + frame.add(pb2); + + frame.setSize(300, 300); + return frame; + } + +} diff --git a/test/jdk/javax/swing/JRadioButton/bug4673850.java b/test/jdk/javax/swing/JRadioButton/bug4673850.java new file mode 100644 index 00000000000..4f9058e978e --- /dev/null +++ b/test/jdk/javax/swing/JRadioButton/bug4673850.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4673850 + * @summary Tests that JRadioButton and JCheckBox checkmarks are painted entirely + * inside circular/rectangle checkboxes for Motif LaF. + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException + * @run main/manual bug4673850 + */ + +import java.awt.FlowLayout; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JRadioButton; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import jtreg.SkippedException; + +public class bug4673850 { + private static final String INSTRUCTIONS = """ + + + + + +

This test is for Motif LaF.

+ +

+ When the test starts, you'll see 2 radio buttons and 2 check boxes + with the checkmarks painted.

+ +

+ Ensure that all the button's checkmarks are painted entirely + within the circular/rectangle checkbox, NOT over them or outside them. +

+ + """; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception e) { + throw new SkippedException("Unsupported LaF", e); + } + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .rows(10) + .columns(45) + .testUI(createAndShowUI()) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4673850"); + frame.setLayout(new FlowLayout()); + + JRadioButton rb = new JRadioButton("RadioButt"); + rb.setSelected(true); + frame.add(rb); + JRadioButton rb2 = new JRadioButton("RadioButt"); + rb2.setHorizontalTextPosition(SwingConstants.LEFT); + rb2.setSelected(true); + frame.add(rb2); + + JCheckBox cb = new JCheckBox("CheckBox"); + cb.setSelected(true); + frame.add(cb); + JCheckBox cb2 = new JCheckBox("CheckBox"); + cb2.setHorizontalTextPosition(SwingConstants.LEFT); + cb2.setSelected(true); + frame.add(cb2); + frame.setSize(200, 150); + return frame; + } +} \ No newline at end of file diff --git a/test/jdk/javax/swing/JRootPane/bug4614623.java b/test/jdk/javax/swing/JRootPane/bug4614623.java new file mode 100644 index 00000000000..9a714d3cdfd --- /dev/null +++ b/test/jdk/javax/swing/JRootPane/bug4614623.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4614623 + * @requires (os.family == "windows") + * @summary Tests that w2k mnemonic underlining works when there's no + focus owner + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4614623 + */ + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.UIManager; + +public class bug4614623 { + private static final String INSTRUCTIONS = """ + This test verifies if the short-cut character + (menu mnemonic) is underlined when the ALT key is held down. + + Check if the following is true. + 1) Press Alt key. The letter 'F' (menu mnemonic) of + the "File" menu should now be underlined. + 2) Release the Alt key, the selection background (light grey) + should appear around the "File" menu. Compare "About" menu + with "File" menu to see the light grey selection background. + + If the above is true, press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(62) + .rows(12) + .testUI(bug4614623::createAndShowUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4614623 - File menu test"); + JMenuBar menuBar = new JMenuBar(); + + JMenu fileMenu = new JMenu("File"); + fileMenu.setMnemonic('F'); + menuBar.add(fileMenu); + + JMenu about = new JMenu("About"); + menuBar.add(about); + menuBar.setSize(300, 100); + + frame.setJMenuBar(menuBar); + menuBar.requestFocus(); + frame.setSize(300, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JSplitPane/bug4820080.java b/test/jdk/javax/swing/JSplitPane/bug4820080.java new file mode 100644 index 00000000000..0702a3a2f59 --- /dev/null +++ b/test/jdk/javax/swing/JSplitPane/bug4820080.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import java.awt.Panel; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JSplitPane; +import javax.swing.UIManager; + +/* + * @test + * @bug 4820080 7175397 + * @summary RFE: Cannot Change the JSplitPane Divider Color while dragging + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4820080 + */ + +public class bug4820080 { + private static final String INSTRUCTIONS = """ + Drag the dividers of the splitpanes (both top and bottom). If the divider + color is green while dragging then test passes, otherwise test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4820080::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4820080"); + UIManager.put("SplitPaneDivider.draggingColor", Color.GREEN); + + Box box = new Box(BoxLayout.Y_AXIS); + frame.add(box); + + JPanel jleft = new JPanel(); + jleft.setBackground(Color.DARK_GRAY); + jleft.setPreferredSize(new Dimension(100, 100)); + JPanel jright = new JPanel(); + jright.setBackground(Color.DARK_GRAY); + jright.setPreferredSize(new Dimension(100, 100)); + + JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jleft, jright); + jsp.setContinuousLayout(false); + box.add(jsp); + + box.add(Box.createVerticalStrut(5)); + box.add(new JSeparator()); + box.add(Box.createVerticalStrut(5)); + + Panel left = new Panel(); + left.setBackground(Color.DARK_GRAY); + left.setPreferredSize(new Dimension(100, 100)); + Panel right = new Panel(); + right.setBackground(Color.DARK_GRAY); + right.setPreferredSize(new Dimension(100, 100)); + + JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right); + sp.setContinuousLayout(false); + box.add(sp); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/4287208/bug4287208.java b/test/jdk/javax/swing/JTabbedPane/4287208/bug4287208.java new file mode 100644 index 00000000000..d7dfe01cff0 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/4287208/bug4287208.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4287208 + * @summary Tests if JTabbedPane's setEnabledAt properly renders bounds of Tabs + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4287208 +*/ + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; + +public class bug4287208 implements ActionListener { + + static final String INSTRUCTIONS = """ + There are two tabs in the test window. Press the "Test" button 5 times. + If this causes tabs to overlap at any time, the test FAILS, otherwise + the test PASSES. + """; + + static boolean state = true; + static JTabbedPane jtp; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4287208 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4287208::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("bug4287208"); + + JButton start = new JButton("Test"); + start.addActionListener(new bug4287208()); + JPanel buttonPanel = new JPanel(); + buttonPanel.add(start); + frame.add(buttonPanel,BorderLayout.SOUTH); + + jtp = new JTabbedPane(); + jtp.addTab("Panel One", new JPanel()); + String s = System.getProperty("test.src",".") + + System.getProperty("file.separator") + "duke.gif"; + ImageIcon ii = new ImageIcon(s); + jtp.addTab("Panel Two", ii, new JPanel()); + + frame.add(jtp, BorderLayout.CENTER); + frame.setSize(500, 300); + return frame; + } + + public void actionPerformed(ActionEvent evt) { + jtp.setEnabledAt(0, state); + jtp.setEnabledAt(1, !state); + state = !state; + } + +} diff --git a/test/jdk/javax/swing/JTabbedPane/4287208/duke.gif b/test/jdk/javax/swing/JTabbedPane/4287208/duke.gif new file mode 100644 index 00000000000..a02a42fd606 Binary files /dev/null and b/test/jdk/javax/swing/JTabbedPane/4287208/duke.gif differ diff --git a/test/jdk/javax/swing/JTabbedPane/bug4273320.java b/test/jdk/javax/swing/JTabbedPane/bug4273320.java new file mode 100644 index 00000000000..d1bcca743b5 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug4273320.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4273320 + * @summary JTabbedPane.setTitleAt() should refresh when using HTML text + * @key headful +*/ + +import java.awt.BorderLayout; +import java.awt.Rectangle; +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.plaf.TabbedPaneUI; + +public class bug4273320 { + + static JFrame frame; + static volatile JTabbedPane tabs; + + static final String PLAIN = "Plain"; + static final String HTML = "A fairly long HTML text label"; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(bug4273320::createUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + TabbedPaneUI ui = tabs.getUI(); + Rectangle origSize = ui.getTabBounds(tabs, 0); + + SwingUtilities.invokeAndWait(() -> { + tabs.setTitleAt(0, HTML); + }); + robot.waitForIdle(); + robot.delay(1000); + + Rectangle newSize = ui.getTabBounds(tabs, 0); + // The tab should be resized larger if the longer HTML text is added + System.out.println("orig = " + origSize.width + " x " + origSize.height); + System.out.println("new = " + newSize.width + " x " + newSize.height); + if (origSize.width >= newSize.width) { + throw new RuntimeException("Tab text is not updated."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static void createUI() { + frame = new JFrame("bug4273320"); + tabs = new JTabbedPane(); + JPanel panel = new JPanel(); + tabs.addTab(PLAIN, panel); + frame.getContentPane().add(tabs, BorderLayout.CENTER); + frame.setSize(500, 300); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/bug4287268.java b/test/jdk/javax/swing/JTabbedPane/bug4287268.java new file mode 100644 index 00000000000..8f7156b93e0 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug4287268.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4287268 + * @summary Tests if setIconAt(index,Icon) does not set Tab's disabled icon + * @key headful +*/ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; + +public class bug4287268 { + + static JFrame frame; + static volatile JTabbedPane jtp; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(bug4287268::createUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + Point point = jtp.getLocationOnScreen(); + int width = jtp.getWidth(); + int height = jtp.getHeight(); + Rectangle r = new Rectangle(point.x, point.y, width, height); + BufferedImage cap = robot.createScreenCapture(r); + + int red = Color.red.getRGB(); + for (int x = 0; x < cap.getWidth(); x++) { + for (int y = 0; y < cap.getHeight(); y++) { + int rgb = cap.getRGB(x, y); + if (rgb == red) { + try { + javax.imageio.ImageIO.write(cap, "png", new java.io.File("cap.png")); + } catch (Exception ee) { + } + throw new RuntimeException("Test failed : found red"); + } + } + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static void createUI() { + frame = new JFrame("bug4287268"); + jtp = new JTabbedPane(); + JPanel panel = new JPanel(); + jtp.add("Panel One", panel); + int size = 64; + BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB); + Graphics g = img.createGraphics(); + g.setColor(Color.red); + g.fillRect(0, 0, size, size); + ImageIcon ii = new ImageIcon(img); + jtp.setIconAt(0, ii); + jtp.setEnabledAt(0, false); + frame.getContentPane().add(jtp, BorderLayout.CENTER); + frame.pack(); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/bug4362226.java b/test/jdk/javax/swing/JTabbedPane/bug4362226.java new file mode 100644 index 00000000000..5339de29119 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug4362226.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4362226 + * @summary JTabbedPane's HTML title should have proper offsets + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4362226 +*/ + +import java.awt.BorderLayout; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.UIManager; +import javax.swing.plaf.metal.MetalLookAndFeel; + +public class bug4362226 { + + static final String PLAIN = "Label"; + static final String HTML = "Label"; + + static final String INSTRUCTIONS = """ + The test window contains a JTabbedPane with two tabs. + The titles for both tabs should look similar and drawn with the same fonts. + The text of the tabs should start in a position that is offset from the left + boundary of the tab, so there is clear space between them. + If there is no space, then the test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4362226 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4362226::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + try { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + } catch (Exception e) { + } + JFrame frame = new JFrame("bug4362226"); + JTabbedPane tabs = new JTabbedPane(); + tabs.addTab(PLAIN, new JPanel()); + tabs.addTab(HTML, new JPanel()); + frame.add(tabs, BorderLayout.CENTER); + frame.setSize(500, 300); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/bug4499556.java b/test/jdk/javax/swing/JTabbedPane/bug4499556.java index fe9d7dbbfde..f9150b339e2 100644 --- a/test/jdk/javax/swing/JTabbedPane/bug4499556.java +++ b/test/jdk/javax/swing/JTabbedPane/bug4499556.java @@ -89,9 +89,10 @@ public static void main(String[] args) throws Exception { } static volatile JTabbedPane pane; + static volatile JFrame frame; static JFrame createUI() { - JFrame frame = new JFrame("bug4499556"); + frame = new JFrame("bug4499556"); pane = getTabbedPane(); frame.add(pane); frame.add(getRightPanel(), BorderLayout.EAST); @@ -262,7 +263,7 @@ static boolean setLAF(String laf) { e.printStackTrace(); return false; } - SwingUtilities.updateComponentTreeUI(pane); + SwingUtilities.updateComponentTreeUI(frame); return true; } diff --git a/test/jdk/javax/swing/JTabbedPane/bug4613811.java b/test/jdk/javax/swing/JTabbedPane/bug4613811.java new file mode 100644 index 00000000000..ecad64e95f8 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug4613811.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4613811 + * @summary Scrollable Buttons of JTabbedPane don't + * get enabled or disabled on selecting tab + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4613811 + */ + +import java.awt.BorderLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTabbedPane; + +public class bug4613811 { + private static final String INSTRUCTIONS = """ + Select different tabs and check that the scrollable + buttons are correctly enabled and disabled. + + When the very first tab (Tab 1) is fully visible + On macOS: + the left arrow button should NOT be visible. + + On other platforms: + the left arrow button should be disabled. + + If the last tab (Tab 5) is fully visible + On macOS: + the right arrow button should NOT be visible. + + On other platforms: + the right arrow button should be disabled. + + If the above is true press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(30) + .testUI(bug4613811::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4613811 - JTabbedPane Test"); + final JTabbedPane tabPane = new JTabbedPane(JTabbedPane.TOP, + JTabbedPane.SCROLL_TAB_LAYOUT); + for (int i = 1; i <= 5; i++) { + tabPane.addTab("TabbedPane: Tab " + i, null, new JLabel("Tab " + i)); + } + frame.add(tabPane, BorderLayout.CENTER); + frame.setResizable(false); + frame.setSize(400, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/bug4668865.java b/test/jdk/javax/swing/JTabbedPane/bug4668865.java new file mode 100644 index 00000000000..711ef12f682 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug4668865.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4668865 + * @summary Tests if JTabbedPane's setEnabledAt properly renders bounds of Tabs + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4668865 +*/ + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; + +public class bug4668865 { + + static final String INSTRUCTIONS = """ + This tests that tooltips are shown for all tabs in all orientations, + when it is necessary to scroll to see all the tabs. + Use the buttons to select each orientation (top/bottom/left/right) in turn. + Scroll through the 8 tabs - using the navigation arrows as needed. + Move the mouse over each tab in turn and verify that the matching tooltip is shown + after sufficient hover time. + The test PASSES if the tooltips are shown for all cases, and FAILS otherwise. + """; + + static JTabbedPane tabPane; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4668865 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4668865::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("bug4668865"); + + tabPane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT); + for(int i = 1; i < 9; i++) { + tabPane.addTab("Tab" + i, null, new JTextField("Tab" + i), "Tab" + i); + } + frame.add(tabPane, BorderLayout.CENTER); + + JButton top = new JButton(new AbstractAction() { + public void actionPerformed(ActionEvent e) { + tabPane.setTabPlacement(JTabbedPane.TOP); + } + }); + top.setText("Top"); + frame.add(top, BorderLayout.NORTH); + + JButton bottom = new JButton(new AbstractAction() { + public void actionPerformed(ActionEvent e) { + tabPane.setTabPlacement(JTabbedPane.BOTTOM); + } + }); + bottom.setText("Bottom"); + frame.add(bottom, BorderLayout.SOUTH); + + JButton left = new JButton(new AbstractAction() { + public void actionPerformed(ActionEvent e) { + tabPane.setTabPlacement(JTabbedPane.LEFT); + } + }); + + left.setText("Left"); + frame.add(left, BorderLayout.WEST); + + JButton right = new JButton(new AbstractAction() { + public void actionPerformed(ActionEvent e) { + tabPane.setTabPlacement(JTabbedPane.RIGHT); + } + }); + + right.setText("Right"); + frame.add(right, BorderLayout.EAST); + + frame.setSize(400, 400); + return frame; + } + +} diff --git a/test/jdk/javax/swing/JTable/CheckBoxFirstClick.java b/test/jdk/javax/swing/JTable/CheckBoxFirstClick.java new file mode 100644 index 00000000000..91f8930103e --- /dev/null +++ b/test/jdk/javax/swing/JTable/CheckBoxFirstClick.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4115930 + * @summary Verify checkboxes in the table respond to first click. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual CheckBoxFirstClick + */ + +public class CheckBoxFirstClick { + private static final String INSTRUCTIONS = """ + Click over the checkbox in the table. It should change state + on the first click. If not - press 'fail'. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(CheckBoxFirstClick::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("ListSizeBug"); + + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { + return names.length; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) { + return names[column]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + public boolean isCellEditable(int row, int col) { + return true; + } + + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer) headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number) value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.add(scrollpane); + frame.setSize(500, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/IllegalStateException.java b/test/jdk/javax/swing/JTable/IllegalStateException.java new file mode 100644 index 00000000000..427b81ab2d9 --- /dev/null +++ b/test/jdk/javax/swing/JTable/IllegalStateException.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4133143 + * @summary Illegal State exception in ComboBox editor in table + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual IllegalStateException + */ + +public class IllegalStateException { + private static final String INSTRUCTIONS = """ + Click on a cell in the first column, delete the contents but leave the editor with focus. + Click on the third column popping up a combo box. + Verify that the text editor loses focus. + If it does, press "pass", otherwise press "fail". + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(IllegalStateException::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("IllegalStateException"); + + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { + return names.length; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) { + return names[column]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + public boolean isCellEditable(int row, int col) { + return true; + } + + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer) headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number) value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.add(scrollpane); + frame.setSize(500, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/InternationalCharacters.java b/test/jdk/javax/swing/JTable/InternationalCharacters.java new file mode 100644 index 00000000000..1d8fc2c4576 --- /dev/null +++ b/test/jdk/javax/swing/JTable/InternationalCharacters.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4179066 + * @summary Tests that JTable prints AltGr characters (~\@|{}[]²µ³) + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual InternationalCharacters + */ + +public class InternationalCharacters { + private static final String INSTRUCTIONS = """ + Double-click an entry in the JTable. + Press Alt-Gr or Option with any key to type an international character. + Verify that the international character appears in the table. + If it does, press "pass", otherwise press "fail". + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(InternationalCharacters::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("InternationalCharacters test"); + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { return names.length; } + public int getRowCount() { return data.length;} + public Object getValueAt(int row, int col) {return data[row][col];} + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) {return names[column];} + public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} + public boolean isCellEditable(int row, int col) {return true;} + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer)headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number)value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.add(scrollpane); + frame.setSize(500, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/JTableScrollPrintTest.java b/test/jdk/javax/swing/JTable/JTableScrollPrintTest.java new file mode 100644 index 00000000000..a2bd03081a9 --- /dev/null +++ b/test/jdk/javax/swing/JTable/JTableScrollPrintTest.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Graphics; +import java.awt.Graphics2D; +import java.awt.print.PageFormat; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; + +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JViewport; +import javax.swing.table.DefaultTableModel; + +/* + * @test + * @key headful + * @bug 8210807 8322140 8322135 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Test to check if JTable can be printed when JScrollPane added to it. + * @run main/manual JTableScrollPrintTest + */ + +public class JTableScrollPrintTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + Instructions to Test: + 1. Print table onto Paper/PDF, using the Print Dialog. + 2. If entire table is printed, then the Test is PASS. + 3. If table is partially printed without table cells, + then the Test is FAIL. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .rows(6) + .columns(35) + .testUI(JTableScrollPrintTest::initialize) + .build() + .awaitAndCheck(); + } + + public static JFrame initialize() { + TestTable testTable = new TestTable(true); + JFrame frame = new JFrame("JTable Print Test"); + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, PassFailJFrame.Position.VERTICAL); + frame.add(testTable); + frame.pack(); + frame.setVisible(true); + PrintUtilities printerJob = new PrintUtilities(testTable); + printerJob.print("Test BackingStore Image Print"); + return frame; + } + + public static class TestTable extends JPanel { + public TestTable(Boolean useScrollPane) { + + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + DefaultTableModel model = new DefaultTableModel(); + model.addColumn("Column 1"); + model.addColumn("Column 2"); + model.addColumn("Column 3"); + model.addColumn("Column 4"); + + for (int row = 1; row <= 5; row++) { + model.addRow(new Object[]{ + "R" + row + " C1", "R" + row + " C2", "R" + row + " C3", "R" + row + " C4"}); + } + + JTable table = new JTable(model); + + if (useScrollPane) { + JScrollPane sp = new JScrollPane(table, + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, + JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + sp.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE); + add(sp); + } else { + add(table.getTableHeader()); + add(table); + } + } + } + + static class PrintUtilities implements Printable { + private final Component componentToBePrinted; + + public void printComponent(Component c, String jobname) { + new PrintUtilities(c).print(jobname); + } + + public PrintUtilities(Component componentToBePrinted) { + this.componentToBePrinted = componentToBePrinted; + } + + public void print(String jobname) { + PrinterJob printJob = PrinterJob.getPrinterJob(); + PageFormat pf = printJob.defaultPage(); + pf.setOrientation(PageFormat.PORTRAIT); + + // set margins to 1/2" + Paper p = new Paper(); + p.setImageableArea(36, 36, p.getWidth() - 72, p.getHeight() - 72); + pf.setPaper(p); + + printJob.setPrintable(this, pf); + printJob.setJobName(jobname); + + if (printJob.printDialog()) { + try { + printJob.print(); + } catch (PrinterException pe) { + System.out.println("Error printing: " + pe); + } + } + } + + public int print(Graphics g, PageFormat pageFormat, int pageIndex) { + if (pageIndex > 0) { + return NO_SUCH_PAGE; + } else { + Graphics2D g2d = (Graphics2D)g; + g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); + Component c = componentToBePrinted; + c.setSize(c.getPreferredSize()); + + double panelX = c.getWidth(); + double panelY = c.getHeight(); + float imageableX = (float) pageFormat.getImageableWidth() - 1; + float imageableY = (float) pageFormat.getImageableHeight() - 1; + + double xscale = imageableX/panelX; + double yscale = imageableY/panelY; + double optimalScale; + if (xscale < yscale) { + optimalScale = xscale; + } else { + optimalScale = yscale; + } + + if (optimalScale > 1) { + optimalScale = 1; + } + + g2d.scale(optimalScale, optimalScale); + c.paint(g2d); + return PAGE_EXISTS; + } + } + } +} diff --git a/test/jdk/javax/swing/JTable/NullTableHeader.java b/test/jdk/javax/swing/JTable/NullTableHeader.java new file mode 100644 index 00000000000..dc62b975d04 --- /dev/null +++ b/test/jdk/javax/swing/JTable/NullTableHeader.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.JTable; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4129409 + * @summary Tests that JTable.setTableHeader(null) doesn't break AutoResize + * @key headful + * @run main NullTableHeader + */ + +public class NullTableHeader { + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + JTable tableView = new JTable(); + tableView.setTableHeader(null); + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + }); + } +} diff --git a/test/jdk/javax/swing/JTable/PrintAllPagesTest.java b/test/jdk/javax/swing/JTable/PrintAllPagesTest.java index 263415f641b..284fbe57097 100644 --- a/test/jdk/javax/swing/JTable/PrintAllPagesTest.java +++ b/test/jdk/javax/swing/JTable/PrintAllPagesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +22,7 @@ */ /* * @test - * @bug 8257810 + * @bug 8257810 8322135 * @library /java/awt/regtesthelpers * @build PassFailJFrame * @summary Verifies if all pages are printed if scrollRectToVisible is set. diff --git a/test/jdk/javax/swing/JTable/ShiftClick.java b/test/jdk/javax/swing/JTable/ShiftClick.java new file mode 100644 index 00000000000..4d617b5eeda --- /dev/null +++ b/test/jdk/javax/swing/JTable/ShiftClick.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Dimension; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4201917 + * @summary Shift Click in table before making selection + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ShiftClick + */ + +public class ShiftClick { + private static final String INSTRUCTIONS = """ + Shift click in the table. Check that all cells + from the first through where you clicked are selected. + If the cells are selected, press pass, otherwise fail. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(ShiftClick::createTestUI) + .logArea(6) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("ShiftClick"); + + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { + return names.length; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) { + return names[column]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + public boolean isCellEditable(int row, int col) { + return true; + } + + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer) headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number) value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.add(scrollpane); + frame.setSize(500, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4118307.java b/test/jdk/javax/swing/JTable/bug4118307.java new file mode 100644 index 00000000000..537e92176ef --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4118307.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.BorderLayout; +import java.awt.Component; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4118307 + * @summary Tests that JTable's cell editor for Number and Date work correctly + * @key headful + * @run main bug4118307 + */ + +public class bug4118307 { + static JFrame frame; + static MyTable tbl; + static Point tableLoc; + static Point p; + private static volatile boolean flag; + static final String[] columnNames = {"Integer", "Double"}; + static final Object[][] data = { + {5, 3.14}, + {10, 2.71}, + {70, 3.14}, + {200, 2.71}, + }; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(250); + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + tableLoc = tbl.getLocationOnScreen(); + p = tbl.getCellRect(0, 0, true).getLocation(); + }); + robot.waitForIdle(); + + robot.mouseMove(tableLoc.x + p.x + 10, tableLoc.y + p.y + 10); + robot.waitForIdle(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> + p = tbl.getCellRect(1, 1, true).getLocation()); + robot.waitForIdle(); + + robot.mouseMove(tableLoc.x + p.x + 10, tableLoc.y + p.y + 10); + robot.waitForIdle(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> + p = tbl.getCellRect(1, 0, true).getLocation()); + robot.waitForIdle(); + + robot.mouseMove(tableLoc.x + p.x + 10, tableLoc.y + p.y + 10); + robot.waitForIdle(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(5000); + + if (!flag) { + throw new RuntimeException("Test Failed."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4118307"); + MyTableModel myModel = new MyTableModel(); + tbl = new MyTable(myModel); + JScrollPane sp = new JScrollPane(tbl); + flag = true; + + frame.add(sp, BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + static class MyTable extends JTable { + public MyTable(TableModel tm) { + super(tm); + } + + public Component prepareRenderer(TableCellRenderer rend, int row, int col) { + try { + return super.prepareRenderer(rend, row, col); + } catch (Exception e) { + e.printStackTrace(); + flag = false; + return null; + } + } + } + + static class MyTableModel extends AbstractTableModel { + public int getColumnCount() { + return columnNames.length; + } + + public int getRowCount() { + return data.length; + } + + @Override + public String getColumnName(int col) { + return columnNames[col]; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + @Override + public boolean isCellEditable(int row, int col) { + return true; + } + + @Override + public void setValueAt(Object value, int row, int col) { + data[row][col] = value; + } + } +} diff --git a/test/jdk/javax/swing/JTable/bug4128506.java b/test/jdk/javax/swing/JTable/bug4128506.java new file mode 100644 index 00000000000..21273c6f318 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4128506.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4128506 + * @summary Tests that JTable with AUTO_RESIZE_ALL_COLUMNS correctly compute width of columns + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4128506 + */ + +public class bug4128506 { + private static final String INSTRUCTIONS = """ + If the columns of JTable have the same width the test passes, else test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4128506::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + final Object[][] data = { + {"cell_1_1", "cell_1_2", "cell_1_3"}, + {"cell_2_1", "cell_2_2", "cell_2_3"}, + {"cell_3_1", "cell_3_2", "cell_3_3"}, + {"cell_4_1", "cell_4_2", "cell_4_3"}, + }; + + TableModel dataModel = new AbstractTableModel() { + public int getColumnCount() { + return 3; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + }; + + JFrame frame = new JFrame("bug4128506"); + JTable tableView = new JTable(dataModel); + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + tableView.getColumnModel().getColumn(1).setMinWidth(5); + JScrollPane scrollpane = new JScrollPane(tableView); + frame.add(scrollpane); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4129401.java b/test/jdk/javax/swing/JTable/bug4129401.java new file mode 100644 index 00000000000..37765d34698 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4129401.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.TableColumn; + +/* + * @test + * @bug 4129401 + * @summary Tests that keystroking for combobox cell editor in JTable works + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4129401 + */ + +public class bug4129401 { + private static final String INSTRUCTIONS = """ + 1. Move the mouse cursor to the cell "CELL 2 1", + which contains JComboBox and click left mouse button + to drop down combobox list. + 2. Change selected item in the combobox list + using up and down arrows. + 3. Press Esc. JComboBox drop down list should hide. + If all was successful then test passes, else test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4129401::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + Object data[][] = new Object[4][2]; + JComboBox cb = new JComboBox(); + cb.addItem("Item1"); + cb.addItem("Item2"); + cb.addItem("Item3"); + cb.addItem("Item4"); + data[0][0] = "CELL 0 0"; + data[0][1] = "CELL 0 1"; + data[1][0] = "CELL 1 0"; + data[1][1] = "CELL 1 1"; + data[2][0] = "CELL 2 0"; + data[2][1] = "CELL 2 1"; + data[3][0] = "CELL 3 0"; + data[3][1] = "CELL 3 1"; + String[] str = {"Column 0", "Column 1"}; + JTable tbl = new JTable(data, str); + JScrollPane sp = new JScrollPane(tbl); + + TableColumn col = tbl.getColumn("Column 1"); + col.setCellEditor(new DefaultCellEditor(cb)); + + JFrame f = new JFrame("4129401 test"); + f.getContentPane().add(sp); + f.setBounds(100, 100, 300, 300); + return f; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4138158.java b/test/jdk/javax/swing/JTable/bug4138158.java new file mode 100644 index 00000000000..400b8b1952e --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4138158.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.JScrollPane; +import javax.swing.JTable; + +/* + * @test + * @bug 4138158 + * @summary Tests that setAutoscrolls(false) locks autoscroll + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4138158 + */ + +public class bug4138158 { + private static final String INSTRUCTIONS = """ + Move mouse to beginning of table, press left mouse button and drag mouse down + below the frame. If the table isn't scrolled down then test passes. + If the table is scrolled then test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4138158::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4138158"); + JTable table = new JTable(20, 3); + table.setAutoscrolls(false); + JScrollPane sp = new JScrollPane(table); + frame.add(sp); + frame.setSize(200, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4139910.java b/test/jdk/javax/swing/JTable/bug4139910.java new file mode 100644 index 00000000000..c9d6d62cf0c --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4139910.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; + +/* + * @test + * @bug 4139910 + * @summary Column resize mouse pointer doesn't display in non-resizable JTable. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4139910 + */ + +public class bug4139910 { + private static final String INSTRUCTIONS = """ + Move mouse pointer to the position between "A" and "B" headers. + If mouse pointer does not change its shape then test passes. If + it does then test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4139910::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4139910"); + + String[] colName = {"A", "B"}; + JTable tbl = new JTable(new DefaultTableModel(colName, 6)); + tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + tbl.getTableHeader().setReorderingAllowed(false); + tbl.getTableHeader().setResizingAllowed(false); + JScrollPane sp = new JScrollPane(tbl); + frame.add(sp); + + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4188504.java b/test/jdk/javax/swing/JTable/bug4188504.java new file mode 100644 index 00000000000..b58ee7def03 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4188504.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4188504 + * @summary setResizable for specified column. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4188504 + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; + +public class bug4188504 { + private static final String INSTRUCTIONS = """ + 1. A table is displayed with 3 columns - A, B, C. + + 2. Try to resize second column of table (Move mouse to the position + between "B" and "C" headers, press left mouse button and move to + right/left). + PLEASE NOTE: You may be able to swap the columns but make sure the + width of column B stays the same. + + 3. If the second column does not change its width then press PASS + otherwise press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(createAndShowUI()) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame jFrame = new JFrame("bug4188504"); + JTable tableView = new JTable(4, 3); + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + tableView.getColumnModel().getColumn(1).setResizable(false); + + jFrame.add(new JScrollPane(tableView)); + jFrame.setSize(300, 150); + return jFrame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4190222.java b/test/jdk/javax/swing/JTable/bug4190222.java new file mode 100644 index 00000000000..5d6fcd2b0cc --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4190222.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Dimension; +import java.awt.Robot; +import java.util.Vector; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; + +/* + * @test + * @bug 4190222 + * @summary Setting data vector on the model correctly repaint table + * @key headful + * @run main bug4190222 + */ + +public class bug4190222 { + static JFrame frame; + static DefaultTableModel dtm; + static JTable tbl; + + static Vector data; + static Vector colNames; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(250); + + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + Dimension preResize = tbl.getSize(); + dtm.setDataVector(data, colNames); + + if (!preResize.equals(tbl.getSize())) { + throw new RuntimeException("Size of table changed after resizing."); + } + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4190222"); + + data = new Vector(1, 1); + colNames = new Vector(3); + for (int i = 1; i < 4; i++) { + Vector row = new Vector(1, 1); + row.addElement("Row " + i + ", Col 1"); + row.addElement("Row " + i + ", Col 2"); + row.addElement("Row " + i + ", Col 3"); + data.addElement(row); + } + colNames.addElement("Col 1"); + colNames.addElement("Col 2"); + colNames.addElement("Col 3"); + + dtm = new DefaultTableModel(data, colNames); + tbl = new JTable(dtm); + JScrollPane scrollPane = new JScrollPane(tbl); + frame.add("Center", scrollPane); + JPanel panel = new JPanel(); + frame.add("South", panel); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JTable/bug4193727.java b/test/jdk/javax/swing/JTable/bug4193727.java new file mode 100644 index 00000000000..2ef4159e90c --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4193727.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.BorderLayout; +import java.awt.Component; +import java.awt.FontMetrics; +import java.util.Vector; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; + +/* + * @test + * @bug 4193727 + * @summary Tests that resizing JTable via TableColumn's + * setWidth(int) repaints correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4193727 + */ + +public class bug4193727 { + static EnhancedJTable tblResults; + static JButton bTest = new JButton("Resize"); + + private static final String INSTRUCTIONS = """ + Push button "Resize". + If either of the following happen, test fails: + 1) The size of the columns change + 2) The JTable is not repainted correctly + + Otherwise test passes. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4193727::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4193727"); + Vector v = new Vector(); + Vector data = new Vector(); + Vector cols = new Vector(); + + cols.add("Name"); + cols.add("Address"); + data.add("Steve"); + data.add("100 East Main Street"); + v.add(data); + + data.add("Richard"); + data.add("99 Main Road"); + v.add(data); + + frame.setLayout(new BorderLayout()); + tblResults = new EnhancedJTable(v, cols); + MyTableHeader mth = new MyTableHeader(); + for (int i = 0; i < tblResults.getColumnCount(); i++) + tblResults.getColumnModel().getColumn(i).setHeaderRenderer(mth.getTHR()); + tblResults.setAutoResizeMode(EnhancedJTable.AUTO_RESIZE_OFF); + + JScrollPane pane = new JScrollPane(tblResults); + frame.add(pane, BorderLayout.CENTER); + JPanel panel = new JPanel(); + panel.add(bTest); + frame.add(panel, BorderLayout.EAST); + bTest.addActionListener(e -> tblResults.autoSizeColumns()); + frame.setSize(300, 200); + return frame; + } +} + +class MyTableHeader extends TableColumn { + public TableCellRenderer getTHR() { + return createDefaultHeaderRenderer(); + } +} + +class EnhancedJTable extends JTable { + public EnhancedJTable(Vector data, Vector colNames) { + super(data, colNames); + } + + public synchronized void autoSizeColumns() { + setAutoResizeMode(AUTO_RESIZE_OFF); + int colcnt = getColumnCount(); + int rowcnt = getRowCount(); + + for (int i = 0; i < colcnt; i++) { + // get the max column width needed + Component cell = getColumnModel().getColumn(i).getHeaderRenderer() + .getTableCellRendererComponent(this, null, false, false, -1, i); + FontMetrics fm = cell.getFontMetrics(cell.getFont()); + int max = SwingUtilities.computeStringWidth(fm, getColumnModel().getColumn(i).getHeaderValue() + .toString() + " "); + for (int j = 0; j < rowcnt; j++) { + // add 2 spaces to account for gutter + int width = SwingUtilities.computeStringWidth(fm, getValueAt(j, i).toString() + " "); + if (max < width) max = width; + } + // set the new column width + getColumnModel().getColumn(i).setWidth(max); + } + } +} diff --git a/test/jdk/javax/swing/JTable/bug4224179.java b/test/jdk/javax/swing/JTable/bug4224179.java new file mode 100644 index 00000000000..b223f3f4716 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4224179.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.BorderLayout; +import java.awt.Dimension; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; + +/* + * @test + * @bug 4224179 + * @summary Tests if Table default cell editor doesn't handle % (percent) character correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4224179 + */ + +public class bug4224179 { + private static final String INSTRUCTIONS = """ + 1. Click ONCE on the center cell ("Huml") + 2. Type the following symbols one after another: a%b + + If the center cell doesn't read "Humla%b" the test fails. + + 3. After the above, press the ESCAPE key and note that the cell + reverts back to "Huml" + 4. Do the stuff in part 1 again + 5. Press the ESCAPE key + + If the center cell now reads "Huml" as it initially was, + the test passed and fails otherwise. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4224179::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4224179"); + JTable table = new JTable(3, 3); + table.setValueAt("Huml", 1, 1); + table.setPreferredScrollableViewportSize(new Dimension(500, 70)); + JScrollPane scrollPane = new JScrollPane(table); + frame.add(scrollPane, BorderLayout.CENTER); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4226181.java b/test/jdk/javax/swing/JTable/bug4226181.java new file mode 100644 index 00000000000..70749cf5d55 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4226181.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.BorderLayout; +import java.awt.GridLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +/* + * @test + * @bug 4226181 + * @summary Tests that JTable setModel() correctly re-sizes and counts columns + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4226181 + */ + +public class bug4226181 { + private static final String INSTRUCTIONS = """ + Take a look at the table and remember the number of columns you see. + Now press the "setModel" button. If the number of columns has changed, + then test fails, otherwise it passes. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4226181::createTestUI) + .build() + .awaitAndCheck(); + } + + static class TestModel extends AbstractTableModel { + public int getRowCount() { + return 5; + } + + public int getColumnCount() { + return 7; + } + + public Object getValueAt(int row, int column) { + return row + ":" + column; + } + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4226181"); + TestModel testModel = new TestModel(); + final JTable t = new JTable(testModel); + JButton b = new JButton("setModel"); + b.addActionListener(ae -> t.setModel(new TestModel())); + t.setCellSelectionEnabled(true); + JPanel p1 = new JPanel(new GridLayout(1, 2)); + p1.add(new JLabel("dummy")); + p1.add(t); + frame.add(p1); + frame.add(b, BorderLayout.SOUTH); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4239157.java b/test/jdk/javax/swing/JTable/bug4239157.java new file mode 100644 index 00000000000..025af1615e0 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4239157.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.DefaultCellEditor; +import javax.swing.JFrame; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableColumn; + +/* + * @test + * @bug 4239157 + * @summary Tests that JTable performs cell validation properly + * (i.e. does not accept entries for which stopCellEditing() + * returns false) + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4239157 + */ + +public class bug4239157 { + private static final String INSTRUCTIONS = """ + You see a JTable having one row and two columns. + Click in the very first cell (where "click here" is displayed). + Edit its content (e.g. type some letters) and press right arrow key. + The edited cell should stay active, its content shouldn't change. + The right cell (that with text "inactive forever") shouldn't become active. + The same should be true when you press Tab key. + If it is so, test passes, otherwise it fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4239157::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4239157"); + JTable table = new JTable(new Object[][]{{"click here", + "inactive forever"}}, + new Object[]{"1", "2"}); + frame.add("Center", table); + TableColumn column = table.getColumn("1"); + TableCellEditor editor = new TestEditor(new JTextField()); + column.setCellEditor(editor); + + frame.pack(); + return frame; + } + + static class TestEditor extends DefaultCellEditor { + public TestEditor(JTextField tf) { + super(tf); + } + + public boolean stopCellEditing() { + return false; + } + } +} diff --git a/test/jdk/javax/swing/JTable/bug4242631.java b/test/jdk/javax/swing/JTable/bug4242631.java new file mode 100644 index 00000000000..6e9d1eddc32 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4242631.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.util.ArrayList; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +/* + * @test + * @bug 4242631 + * @summary Tests that JTable repaints itself correctly after a record + * has been removed and added to the table model. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4242631 + */ + +public class bug4242631 { + private static JButton addButton; + private static JButton removeButton; + private static JButton bothButton; + private static SimpleTableModel tableModel; + + private static final String INSTRUCTIONS = """ + Press Add button to add a record to the table. The record added should + have number 0. Then press Remove/Add button some times. The record number + should increase as you press. If it does not, test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4242631::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4242631"); + GridBagLayout grid = new GridBagLayout(); + + frame.setLayout(grid); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(2, 2, 2, 2); + + // Add button. + c.gridx = 0; + c.gridy = 0; + grid.setConstraints(addButton = new JButton("Add"), c); + frame.add(addButton); + + // Edit button. + c.gridx = 1; + c.gridy = 0; + grid.setConstraints(removeButton = new JButton("Remove"), c); + frame.add(removeButton); + + // Remove button. + c.gridx = 2; + c.gridy = 0; + grid.setConstraints(bothButton = new JButton("Remove/Add"), c); + frame.add(bothButton); + + // Table. + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 6; + c.gridheight = 0; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1.0; + c.weighty = 1.0; + JScrollPane scroll = null; + tableModel = new SimpleTableModel(); + grid.setConstraints(scroll = new JScrollPane(new JTable(tableModel)), c); + frame.add(scroll); + + // Create some action listeners. + addButton.addActionListener(event -> tableModel.addRow()); + removeButton.addActionListener(event -> tableModel.removeRow()); + bothButton.addActionListener(event -> tableModel.removeThenAddRow()); + + frame.pack(); + return frame; + } + + static class SimpleTableModel extends AbstractTableModel { + int counter = 0; + ArrayList list = new ArrayList(); + + public SimpleTableModel() {} + public int getColumnCount() { return 1; } + public int getRowCount() { return list.size(); } + + public Object getValueAt(int row, int col) { + String str = (String) list.get(row); + return str;// + "." + col; + } + + public void addRow() { + list.add("" + counter++); + fireTableRowsInserted(list.size() - 1, list.size() - 1); + } + + public void removeRow() { + if (list.size() == 0) return; + list.remove(list.size() - 1); + fireTableRowsDeleted(list.size(), list.size()); + } + + public void removeThenAddRow() { + if (list.size() == 0) return; + removeRow(); + addRow(); + } + } +} diff --git a/test/jdk/javax/swing/JToolTip/TooltipTest.java b/test/jdk/javax/swing/JToolTip/TooltipTest.java new file mode 100644 index 00000000000..c081730a8d7 --- /dev/null +++ b/test/jdk/javax/swing/JToolTip/TooltipTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4207474 4218495 4375928 + * @summary Tests various tooltip issues: HTML tooltips, long tooltip text + * and mnemonic keys displayed in tooltips + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TooltipTest + */ + +import java.awt.FlowLayout; +import java.awt.event.KeyEvent; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.UIManager; + +public class TooltipTest { + private static final String INSTRUCTIONS = """ + 1. Move the mouse over the button labeled "Red tip" and let it stay + still in order to test HTML in JToolTip. If the tooltip has some + text which is red then test passes, otherwise it fails (bug 4207474). + + 2. Move the mouse over the button labeled "Long tip". + If the last letter of the tooltip appears clipped, + then the test fails. If you can see the entire last character, + then the test passes (bug 4218495). + + 3. Verify that "M" is underlined on the button labeled "Mnemonic" + Move the mouse pointer over the button labeled "Mnemonic" and look + at tooltip when it appears. It should read "hint". + If the above is true test passes else test fails (bug 4375928). + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + PassFailJFrame.builder() + .title("TooltipTest Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(TooltipTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + + JButton b = new JButton("Red tip"); + b.setToolTipText("
Here is some " + + "red text.
"); + panel.add(b); + + b = new JButton("Long tip"); + b.setToolTipText("Is the last letter clipped?"); + panel.add(b); + + b = new JButton("Mnemonic"); + b.setMnemonic(KeyEvent.VK_M); + b.setToolTipText("hint"); + panel.add(b); + + return panel; + } +} diff --git a/test/jdk/javax/swing/JToolTip/bug4225314.java b/test/jdk/javax/swing/JToolTip/bug4225314.java new file mode 100644 index 00000000000..d36bd461272 --- /dev/null +++ b/test/jdk/javax/swing/JToolTip/bug4225314.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4225314 + * @summary Tests that tooltip is painted properly when it has thick border + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4225314 + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JToolTip; +import javax.swing.border.LineBorder; + +public class bug4225314 { + private static final String INSTRUCTIONS = """ + The word "Tooltip" in both tooltips should not be clipped by the + black border and be fully visible for this test to pass. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4225314 Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4225314::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + JToolTip tt1 = new JToolTip(); + tt1.setTipText("Tooltip"); + tt1.setBorder(new LineBorder(Color.BLACK, 10)); + + JToolTip tt2 = new JToolTip(); + tt2.setTipText("Tooltip"); + tt2.setBorder(new LineBorder(Color.BLACK, 10)); + + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + panel.add(tt1); + panel.add(tt2); + + return panel; + } +} diff --git a/test/jdk/javax/swing/JToolTip/bug4255441.java b/test/jdk/javax/swing/JToolTip/bug4255441.java new file mode 100644 index 00000000000..4a90c975502 --- /dev/null +++ b/test/jdk/javax/swing/JToolTip/bug4255441.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4255441 + * @summary Tests that tooltip appears inside AWT Frame + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4255441 + */ + +import java.awt.FlowLayout; +import java.awt.Frame; +import javax.swing.JButton; + +public class bug4255441 { + private static final String INSTRUCTIONS = """ + Move mouse pointer inside the button. + If a tooltip with "Tooltip text" appears, the test passes. + """; + + private static Frame createTestUI() { + Frame fr = new Frame("bug4255441"); + fr.setLayout(new FlowLayout()); + + JButton bt = new JButton("Button"); + bt.setToolTipText("Tooltip text"); + fr.add(bt); + + fr.setSize(200, 200); + return fr; + } + + public static void main(String[] argv) throws Exception { + PassFailJFrame.builder() + .title("bug4255441 Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4255441::createTestUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JViewport/ScrollRectToVisibleTest3.java b/test/jdk/javax/swing/JViewport/ScrollRectToVisibleTest3.java new file mode 100644 index 00000000000..bf96ab2fc46 --- /dev/null +++ b/test/jdk/javax/swing/JViewport/ScrollRectToVisibleTest3.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key headful + * @bug 4217252 + * @summary Verify that scrolling beyond the visible region and scrolling + * a component smaller than the viewport is not allowed. + * @library /javax/swing/regtesthelpers + * @build Util + * @run main/othervm -Dsun.java2d.uiScale=1 ScrollRectToVisibleTest3 + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; + +public class ScrollRectToVisibleTest3 { + private static JFrame frame; + private static JTable table; + private static JButton scrollButton; + private static volatile int clickCount = 0; + private static final String[] EXPECTED_TEXT = {"99 x 0", "98 x 0", + "97 x 0", "96 x 0"}; + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + + SwingUtilities.invokeAndWait(ScrollRectToVisibleTest3::createTestUI); + robot.waitForIdle(); + robot.delay(1000); + + Rectangle frameBounds = Util.invokeOnEDT(() -> getComponentBounds(frame)); + robot.delay(100); + Point scrollBtnLoc = Util.getCenterPoint(scrollButton); + + robot.mouseMove(scrollBtnLoc.x, scrollBtnLoc.y); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(50); + + int rowHeight = Util.invokeOnEDT(() -> table.getRowHeight()); + for (int i = 1; i <= 4; i++) { + robot.mouseMove(frameBounds.x + 50, + frameBounds.y + frameBounds.height - (rowHeight * i + 2)); + robot.delay(300); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + // 500 ms delay added so that current mouseClicked event + // is processed successfully before proceeding to the next + robot.delay(500); + } + if (clickCount != 4) { + throw new RuntimeException("Test Failed! Expected 4 mouse clicks" + + " but got " + clickCount); + } + } + + private static void createTestUI() { + frame = new JFrame("ScrollRectToVisibleTest3"); + table = new JTable(new TestModel()); + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + JTable testTable = (JTable) e.getComponent(); + int row = testTable.getSelectedRow(); + int column = testTable.getSelectedColumn(); + String cellContent = testTable.getValueAt(row, column).toString(); + if (!EXPECTED_TEXT[clickCount].equals(cellContent)) { + throw new RuntimeException(("Test failed! Table Cell Content" + + " at (row %d , col %d)\n Expected: %s vs Actual: %s") + .formatted(row, column, + EXPECTED_TEXT[clickCount], cellContent)); + } + clickCount++; + } + }); + + scrollButton = new JButton("Scroll"); + scrollButton.addActionListener(ae -> { + Rectangle bounds = table.getBounds(); + bounds.y = bounds.height + table.getRowHeight(); + bounds.height = table.getRowHeight(); + System.out.println("scrolling: " + bounds); + table.scrollRectToVisible(bounds); + System.out.println("bounds: " + table.getVisibleRect()); + }); + + frame.add(scrollButton, BorderLayout.NORTH); + frame.add(new JScrollPane(table), BorderLayout.CENTER); + frame.setSize(400, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + + private static class TestModel extends AbstractTableModel { + @Override + public String getColumnName(int column) { + return Integer.toString(column); + } + + @Override + public int getRowCount() { + return 100; + } + + @Override + public int getColumnCount() { + return 5; + } + + @Override + public Object getValueAt(int row, int col) { + return row + " x " + col; + } + + @Override + public boolean isCellEditable(int row, int column) { return false; } + + @Override + public void setValueAt(Object value, int row, int col) { + } + } + + private static Rectangle getComponentBounds(Component c) { + Point locationOnScreen = c.getLocationOnScreen(); + Dimension size = c.getSize(); + return new Rectangle(locationOnScreen, size); + } +} diff --git a/test/jdk/javax/swing/JViewport/SetViewRepaint.java b/test/jdk/javax/swing/JViewport/SetViewRepaint.java new file mode 100644 index 00000000000..379a3e4e33b --- /dev/null +++ b/test/jdk/javax/swing/JViewport/SetViewRepaint.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4128110 + * @summary Verify that JViewport.setViewportView() and JScrollPane.setViewport() + * force a re-layout and a repaint. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SetViewRepaint + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridLayout; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JViewport; + +public class SetViewRepaint { + private static final String INSTRUCTIONS = """ + Verify the following two cases: + + 1) Press "JViewport.setViewportView()" button and verify that + the blue label is replaced by a scrolling list. + + 2) Press "JScrollPane.setViewport()" button and verify that + the red label is replaced by a scrolling list as well. + + In either case the display should update automatically after + pressing the button. + + If the above is true, press PASS else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(30) + .testUI(SetViewRepaint::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("SetViewRepaint"); + JPanel p1 = new JPanel(new BorderLayout()); + JPanel p2 = new JPanel(new BorderLayout()); + + JLabel label1 = new ColorLabel(Color.BLUE, "Blue Label"); + final JList list1 = new JList(new String[]{"one", "two", "three", "four"}); + final JScrollPane sp1 = new JScrollPane(label1); + ActionListener doSetViewportView = e -> sp1.setViewportView(list1); + JButton b1 = new JButton("JViewport.setViewportView()"); + b1.addActionListener(doSetViewportView); + p1.add(sp1, BorderLayout.CENTER); + p1.add(b1, BorderLayout.SOUTH); + + JLabel label2 = new ColorLabel(Color.RED, "Red Label"); + final JList list2 = new JList(new String[]{"five", "six", "seven", "eight"}); + final JScrollPane sp2 = new JScrollPane(label2); + ActionListener doSetViewport = e -> { + JViewport vp = new JViewport(); + vp.setView(list2); + sp2.setViewport(vp); + }; + JButton b2 = new JButton("JScrollPane.setViewport()"); + b2.addActionListener(doSetViewport); + p2.add(sp2, BorderLayout.CENTER); + p2.add(b2, BorderLayout.SOUTH); + frame.setLayout(new GridLayout(1, 2)); + frame.add(p1); + frame.add(p2); + frame.setResizable(false); + frame.setSize(500, 120); + return frame; + } + + private static class ColorLabel extends JLabel { + ColorLabel(Color color, String text) { + super(text); + setForeground(Color.WHITE); + setBackground(color); + setOpaque(true); + setHorizontalAlignment(CENTER); + } + } +} diff --git a/test/jdk/javax/swing/JWindow/bug4251781.java b/test/jdk/javax/swing/JWindow/bug4251781.java new file mode 100644 index 00000000000..0152db71f24 --- /dev/null +++ b/test/jdk/javax/swing/JWindow/bug4251781.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4251781 + * @summary Tests that JWindow repaint is optimized (background is not + cleared). + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4251781 + */ + +import java.awt.Color; +import java.awt.Container; +import javax.swing.JButton; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JWindow; + +public class bug4251781 { + private static final String INSTRUCTIONS = """ + Press the button at the bottom-right corner of the gray + window with the mouse. + If the window DOES NOT flicker when you press and/or release + the mouse button press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4251781::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JWindow createAndShowUI() { + JWindow w = new JWindow(); + final Container pane = w.getContentPane(); + pane.setLayout(null); + pane.setBackground(Color.GRAY.darker()); + + final JPopupMenu popup = new JPopupMenu(); + popup.add(new JMenuItem("item 1")); + popup.add(new JMenuItem("exit")); + + JButton b = new JButton("menu"); + b.setBounds(350, 250, 50, 50); + b.addActionListener(ev -> popup.show(pane, 0, 0)); + pane.add(b); + + w.setSize(400, 300); + return w; + } +} diff --git a/test/jdk/javax/swing/SwingUtilities/bug4967768.java b/test/jdk/javax/swing/SwingUtilities/bug4967768.java index 43f9f7cabfb..6ce1f5c787b 100644 --- a/test/jdk/javax/swing/SwingUtilities/bug4967768.java +++ b/test/jdk/javax/swing/SwingUtilities/bug4967768.java @@ -37,13 +37,19 @@ public class bug4967768 { private static final String INSTRUCTIONS = """ - When the test starts you'll see a button "Oops" - with the "p" letter underlined at the bottom - of the instruction frame. + When the test starts you'll see a button "Oops". + + For Windows and GTK Look and Feel, you will need to + press the ALT key to make the mnemonic visible. + Once the ALT key is pressed, the letter "p" will be + underlined at the bottom of the instruction frame. Ensure the underline cuts through the descender of letter "p", i.e. the underline is painted not below the letter but below the baseline. + + Press Pass if you see the expected behaviour else + press Fail. """; public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/swing/ToolTipManager/bug4250178.java b/test/jdk/javax/swing/ToolTipManager/bug4250178.java new file mode 100644 index 00000000000..18a9c4d93e2 --- /dev/null +++ b/test/jdk/javax/swing/ToolTipManager/bug4250178.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4250178 + * @summary Tooltip in incorrect location on ToolBar + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4250178 + */ + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.ToolTipManager; + +public class bug4250178 { + private static final String INSTRUCTIONS = """ + Click somewhere in the test UI frame to make it focused. + Move mouse to the bottom right corner of the button in this frame + and wait until tooltip appears. + + If the tooltip fits into the frame OR partially covered by the mouse + cursor then test fails. Otherwise test passes. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4250178::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame fr = new JFrame("bug4250178"); + JButton button = new JButton("Button"); + button.setToolTipText("ToolTip"); + ToolTipManager.sharedInstance().setLightWeightPopupEnabled(true); + fr.add(button); + fr.setSize(250, 100); + return fr; + } +} diff --git a/test/jdk/javax/swing/ToolTipManager/bug4294808.java b/test/jdk/javax/swing/ToolTipManager/bug4294808.java new file mode 100644 index 00000000000..d4ec109020a --- /dev/null +++ b/test/jdk/javax/swing/ToolTipManager/bug4294808.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4294808 + * @summary Tooltip blinking. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4294808 + */ + +import java.awt.Dimension; +import javax.swing.JButton; +import javax.swing.JComponent; + +public class bug4294808 { + private static final String INSTRUCTIONS = """ + Move mouse cursor to the button named "Tooltip Button" + at the bottom of the instruction window and wait until + tooltip has appeared. + + If tooltip appears and eventually disappears without + rapid blinking then press PASS else FAIL. + """; + + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4294808 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .splitUIBottom(bug4294808::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createAndShowUI() { + JButton bt = new JButton("Tooltip Button"); + bt.setToolTipText("Long tooltip text here"); + bt.setPreferredSize(new Dimension(200, 60)); + return bt; + } +} diff --git a/test/jdk/javax/swing/ToolTipManager/bug6178004.java b/test/jdk/javax/swing/ToolTipManager/bug6178004.java new file mode 100644 index 00000000000..e33a6391e89 --- /dev/null +++ b/test/jdk/javax/swing/ToolTipManager/bug6178004.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4148057 6178004 + * @summary REGRESSION: setToolTipText does not work if the + * component is not focused + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6178004 + */ + +import java.awt.Point; +import java.awt.Window; +import java.awt.event.MouseEvent; +import java.util.List; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; +import javax.swing.ToolTipManager; +import javax.swing.UIManager; + +public class bug6178004 { + private static JFrame frame1; + private static JFrame frame2; + private static final int SIZE = 300; + + private static final String INSTRUCTIONS = """ + You can change Look And Feel using the menu "Change LaF". + + Make sure that Frame2 or instruction window is active. + Move mouse over the button inside "Frame 1". + If tooltip is NOT shown or Frame 1 jumped on top of + the Frame2, press FAIL. + + For Metal/Windows LaF: + Tooltips are shown only if one of the frames (or the instruction + window) is active. To test it click on any other application to + make frames and instruction window inactive and then verify that + tooltips are not shown any more. + + For Motif/GTK/Nimbus/Aqua LaF: + Tooltips should be shown for all frames irrespective of whether + the application is active or inactive. + + Note: Tooltip for Frame1 is always shown at the top-left corner. + Tooltips could be shown partly covered by another frame. + + If above is true press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug6178004 Test Instructions") + .instructions(INSTRUCTIONS) + .testTimeOut(10) + .columns(40) + .testUI(createAndShowUI()) + .positionTestUI(bug6178004::positionTestWindows) + .build() + .awaitAndCheck(); + } + + private static List createAndShowUI() { + ToolTipManager.sharedInstance().setInitialDelay(0); + + frame1 = new JFrame("bug6178004 Frame1"); + frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JButton button = new JButton("Test") { + public Point getToolTipLocation(MouseEvent event) { + return new Point(10, 10); + } + }; + button.setToolTipText("Tooltip-1"); + frame1.add(button); + frame1.setSize(SIZE, SIZE); + + frame2 = new JFrame("bug6178004 Frame2"); + frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JButton button2 = new JButton("Click me") ; + button2.setToolTipText("Tooltip-2"); + frame2.add(button2); + frame2.setSize(SIZE, SIZE); + + JMenuBar bar = new JMenuBar(); + JMenu lafMenu = new JMenu("Change LaF"); + ButtonGroup lafGroup = new ButtonGroup(); + + LookAndFeel currentLaf = UIManager.getLookAndFeel(); + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels(); + for (final UIManager.LookAndFeelInfo lafInfo : lafs) { + JCheckBoxMenuItem lafItem = new JCheckBoxMenuItem(lafInfo.getName()); + lafItem.addActionListener(e -> setLaF(lafInfo.getClassName())); + if (lafInfo.getClassName().equals(currentLaf.getClass().getName())) { + lafItem.setSelected(true); + } + + lafGroup.add(lafItem); + lafMenu.add(lafItem); + } + + bar.add(lafMenu); + frame2.setJMenuBar(bar); + return List.of(frame1, frame2); + } + + private static void setLaF(String laf) { + try { + UIManager.setLookAndFeel(laf); + SwingUtilities.updateComponentTreeUI(frame1); + SwingUtilities.updateComponentTreeUI(frame2); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // custom window layout required for this test + private static void positionTestWindows(List testWindows, + PassFailJFrame.InstructionUI instructionUI) { + int gap = 5; + int x = instructionUI.getLocation().x + instructionUI.getSize().width + gap; + // the two test frames need to overlap for this test + testWindows.get(0).setLocation(x, instructionUI.getLocation().y); + testWindows.get(1).setLocation((x + SIZE / 2), instructionUI.getLocation().y); + } +} diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java index fc83b49597d..80faeed460e 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 +42,18 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; +import static sun.java2d.pipe.Region.clipRound; + /* * @test - * @bug 8282958 + * @bug 8282958 8349188 * @summary Verify LineBorder edges have the same width * @requires (os.family == "windows") + * @modules java.desktop/sun.java2d.pipe * @run main ScaledLineBorderTest */ public class ScaledLineBorderTest { - private static final Dimension SIZE = new Dimension(120, 25); + private static final Dimension SIZE = new Dimension(250, 50); private static final Color OUTER_COLOR = Color.BLACK; private static final Color BORDER_COLOR = Color.RED; @@ -59,12 +62,19 @@ public class ScaledLineBorderTest { private static final double[] scales = {1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00}; + private static final int[] thickness = {1, 4, 10, 15}; + + private record TestImage(BufferedImage image, + List panelLocations, + double scale, + int thickness) { + } - private static final List images = - new ArrayList<>(scales.length); + private record TestUI(JComponent content, + List panelLocations, + int thickness) { + } - private static final List panelLocations = - new ArrayList<>(4); public static void main(String[] args) throws Exception { Collection params = Arrays.asList(args); @@ -74,29 +84,38 @@ public static void main(String[] args) throws Exception { } private static void testScaling(boolean showFrame, boolean saveImages) { - JComponent content = createUI(); - if (showFrame) { - showFrame(content); + for (int thickness : thickness) { + TestUI testUI = createUI(thickness); + if (showFrame) { + showFrame(testUI.content); + } + + List images = paintToImages(testUI, saveImages); + verifyBorderRendering(images, saveImages); + } + + if (errorCount > 0) { + throw new Error("Test failed: " + + errorCount + " error(s) detected - " + + errorMessage); } - paintToImages(content, saveImages); - verifyBorderRendering(saveImages); } - private static void verifyBorderRendering(final boolean saveImages) { - String errorMessage = null; - int errorCount = 0; - for (int i = 0; i < images.size(); i++) { - BufferedImage img = images.get(i); - double scaling = scales[i]; - try { - int thickness = (int) Math.floor(scaling); + private static String errorMessage = null; + private static int errorCount = 0; - checkVerticalBorders(SIZE.width / 2, thickness, img); + private static void verifyBorderRendering(final List images, + final boolean saveImages) { + for (TestImage test : images) { + final BufferedImage img = test.image; + final int effectiveThickness = clipRound(test.thickness * test.scale); + try { + checkVerticalBorders((int) (SIZE.width * test.scale / 2), effectiveThickness, img); - for (Point p : panelLocations) { - int y = (int) (p.y * scaling) + SIZE.height / 2; - checkHorizontalBorder(y, thickness, img); + for (Point p : test.panelLocations) { + int y = (int) ((p.y + (SIZE.height / 2)) * test.scale); + checkHorizontalBorder(y, effectiveThickness, img); } } catch (Error e) { if (errorMessage == null) { @@ -104,21 +123,13 @@ private static void verifyBorderRendering(final boolean saveImages) { } errorCount++; - System.err.printf("Scaling: %.2f\n", scaling); + System.err.printf("Scale: %.2f; thickness: %d, effective: %d\n", + test.scale, test.thickness, effectiveThickness); e.printStackTrace(); - // Save the image if it wasn't already saved - if (!saveImages) { - saveImage(img, getImageFileName(scaling)); - } + saveImage(img, getImageFileName(test.scale, test.thickness)); } } - - if (errorCount > 0) { - throw new Error("Test failed: " - + errorCount + " error(s) detected - " - + errorMessage); - } } private static void checkVerticalBorders(final int x, @@ -220,17 +231,19 @@ private static void throwUnexpectedColor(int x, int y, int color) { x, y, color)); } - private static JComponent createUI() { + private static TestUI createUI(int thickness) { Box contentPanel = Box.createVerticalBox(); contentPanel.setBackground(OUTER_COLOR); + List panelLocations = new ArrayList<>(4); + Dimension childSize = null; for (int i = 0; i < 4; i++) { JComponent filler = new JPanel(null); filler.setBackground(INSIDE_COLOR); filler.setPreferredSize(SIZE); filler.setBounds(i, 0, SIZE.width, SIZE.height); - filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); + filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, thickness)); JPanel childPanel = new JPanel(new BorderLayout()); childPanel.setBorder(BorderFactory.createEmptyBorder(0, i, 4, 4)); @@ -248,7 +261,7 @@ private static JComponent createUI() { contentPanel.setSize(childSize.width, childSize.height * 4); - return contentPanel; + return new TestUI(contentPanel, panelLocations, thickness); } private static void showFrame(JComponent content) { @@ -260,28 +273,33 @@ private static void showFrame(JComponent content) { frame.setVisible(true); } - private static void paintToImages(final JComponent content, - final boolean saveImages) { - for (double scaling : scales) { + private static List paintToImages(final TestUI testUI, + final boolean saveImages) { + final List images = new ArrayList<>(scales.length); + final JComponent content = testUI.content; + for (double scale : scales) { BufferedImage image = - new BufferedImage((int) Math.ceil(content.getWidth() * scaling), - (int) Math.ceil(content.getHeight() * scaling), + new BufferedImage((int) Math.ceil(content.getWidth() * scale), + (int) Math.ceil(content.getHeight() * scale), BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = image.createGraphics(); - g2d.scale(scaling, scaling); + g2d.scale(scale, scale); content.paint(g2d); g2d.dispose(); if (saveImages) { - saveImage(image, getImageFileName(scaling)); + saveImage(image, getImageFileName(scale, testUI.thickness)); } - images.add(image); + images.add(new TestImage(image, testUI.panelLocations, + scale, testUI.thickness)); } + return images; } - private static String getImageFileName(final double scaling) { - return String.format("test%.2f.png", scaling); + private static String getImageFileName(final double scaling, + final int thickness) { + return String.format("test%02d@%.2f.png", thickness, scaling); } private static void saveImage(BufferedImage image, String filename) { diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java index 4b076977313..2a732812e38 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * 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,12 +44,15 @@ import javax.swing.SwingUtilities; import javax.swing.border.LineBorder; +import static sun.java2d.pipe.Region.clipRound; + /* * @test - * @bug 8282958 + * @bug 8282958 8349188 * @summary Verify all the borders are rendered consistently for a JTextField * in Windows LaF which uses LineBorder * @requires (os.family == "windows") + * @modules java.desktop/sun.java2d.pipe * @run main ScaledTextFieldBorderTest */ public class ScaledTextFieldBorderTest { @@ -92,7 +95,7 @@ private static void verifyBorderRendering(final boolean saveImages) { BufferedImage img = images.get(i); double scaling = scales[i]; try { - int thickness = (int) Math.floor(scaling); + int thickness = clipRound(scaling); checkVerticalBorders(textFieldSize.width / 2, thickness, img); diff --git a/test/jdk/javax/swing/border/TransparentTitleTest.java b/test/jdk/javax/swing/border/TransparentTitleTest.java new file mode 100644 index 00000000000..49a32a5890c --- /dev/null +++ b/test/jdk/javax/swing/border/TransparentTitleTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4154572 + * @summary Tests that the area behind a TitledBorder's title string is transparent, + * allowing the component's background to show through + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TransparentTitleTest + */ + +import java.awt.GridLayout; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Color; +import java.awt.image.BufferedImage; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.border.TitledBorder; +import javax.swing.border.LineBorder; + +public class TransparentTitleTest { + private static final String INSTRUCTIONS = """ + If all panels are correctly painted such that the title of the + border allows the underlying panel image (green rectangle) + to show through the background of the text, + then this test passes; else it fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("TransparentTitleTest Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(TransparentTitleTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("TransparentTitleTest"); + + frame.setLayout(new GridLayout(3, 6, 5, 5)); + + frame.add(new ImagePanel(TitledBorder.TOP, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.TOP, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.TOP, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.ABOVE_TOP, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.ABOVE_TOP, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.ABOVE_TOP, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.BELOW_TOP, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.BELOW_TOP, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.BELOW_TOP, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.BOTTOM, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.BOTTOM, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.BOTTOM, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.ABOVE_BOTTOM, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.ABOVE_BOTTOM, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.ABOVE_BOTTOM, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.BELOW_BOTTOM, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.BELOW_BOTTOM, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.BELOW_BOTTOM, TitledBorder.RIGHT)); + + frame.pack(); + return frame; + } +} + +class ImagePanel extends JPanel { + + private final ImageIcon imageIcon; + + private static final BufferedImage bufferedImage = + new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB); + + static { + Graphics g = bufferedImage.getGraphics(); + g.setColor(Color.GREEN); + g.fillRect(0, 0, 128, 128); + } + + public ImagePanel(int titlePos, int titleJust) { + imageIcon = new ImageIcon(bufferedImage); + + TitledBorder b = new TitledBorder(new LineBorder(Color.black,3), "title text"); + b.setTitlePosition(titlePos); + b.setTitleJustification(titleJust); + b.setTitleColor(Color.black); + setBorder(b); + } + + public Dimension getPreferredSize() { + return new Dimension(imageIcon.getIconWidth(), imageIcon.getIconHeight()); + } + + public void paintComponent(Graphics g) { + imageIcon.paintIcon(this, g, 0, 0); + } +} diff --git a/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java b/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java new file mode 100644 index 00000000000..695d8a83c70 --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @key headful + * @bug 4231444 8354646 + * @summary Password fields' ActionMap needs to replace + * DefaultEditorKit.selectWordAction with + * DefaultEditorKit.selectLineAction. + * + * @run main PasswordSelectionWordTest + */ + +import javax.swing.Action; +import javax.swing.JPasswordField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.basic.BasicTextUI; +import javax.swing.text.DefaultEditorKit; +import java.awt.event.ActionEvent; + +public class PasswordSelectionWordTest { + public static void main(String[] args) throws Exception { + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + System.out.println("Testing LAF: " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> { + if (setLookAndFeel(laf)) { + runTest(); + } + }); + } + } + + private static boolean setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + return true; + } catch (UnsupportedLookAndFeelException e) { + System.err.println("Skipping unsupported look and feel:"); + e.printStackTrace(); + return false; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void runTest() { + String str = "one two three"; + JPasswordField field = new JPasswordField(str); + if (!(field.getUI() instanceof BasicTextUI)) { + throw new RuntimeException("Unexpected condition: JPasswordField UI was " + field.getUI()); + } + System.out.println("Testing " + field.getUI()); + + // do something (anything) to initialize the Views: + field.setSize(100, 100); + field.addNotify(); + + Action action = field.getActionMap().get( + DefaultEditorKit.selectWordAction); + action.actionPerformed(new ActionEvent(field, 0, "")); + int selectionStart = field.getSelectionStart(); + int selectionEnd = field.getSelectionEnd(); + System.out.println("selectionStart = " + selectionStart); + System.out.println("selectionEnd = " + selectionEnd); + if (selectionStart != 0 || selectionEnd != str.length()) { + throw new RuntimeException("selectionStart = " + selectionStart + + " and selectionEnd = " + selectionEnd); + } + } +} diff --git a/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java b/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java index f3562108314..65c5c510fc3 100644 --- a/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java +++ b/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java @@ -29,7 +29,7 @@ * @modules java.desktop/sun.awt * @library /test/lib * @key headful - * @run main bug4952462 + * @run main/othervm -Dsun.java2d.uiScale=1 bug4952462 */ import java.awt.Color; @@ -41,10 +41,8 @@ import javax.swing.JRadioButton; import javax.swing.SwingUtilities; import javax.swing.UIManager; -import javax.swing.plaf.metal.MetalTheme; - -import jtreg.SkippedException; -import sun.awt.AppContext; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.OceanTheme; public class bug4952462 { private static JFrame frame; @@ -52,41 +50,35 @@ public class bug4952462 { public static void main(String[] args) throws Exception { try { + MetalLookAndFeel.setCurrentTheme(new OceanTheme()); UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + Robot r = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("Metal JRadioButton Foreground Color Test"); + frame.getContentPane().setLayout(new FlowLayout()); + rb = new JRadioButton("RadioButton", true); + rb.setEnabled(false); + rb.setForeground(Color.RED); + frame.getContentPane().add(rb); + frame.setSize(250, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); - MetalTheme theme = (MetalTheme) AppContext.getAppContext().get("currentMetalTheme"); - if (theme == null || !"Ocean".equals(theme.getName())) { - throw new SkippedException("Current theme is not Ocean. Test is " + - "only for Metal's Ocean theme. Skipping test."); - } else { - Robot r = new Robot(); - SwingUtilities.invokeAndWait(() -> { - frame = new JFrame("Metal JRadioButton Foreground Color Test"); - frame.getContentPane().setLayout(new FlowLayout()); - rb = new JRadioButton("RadioButton", true); - rb.setEnabled(false); - rb.setForeground(Color.RED); - frame.getContentPane().add(rb); - frame.setSize(250, 100); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - }); - - r.waitForIdle(); - r.delay(500); + r.waitForIdle(); + r.delay(500); - SwingUtilities.invokeAndWait(() -> { - Point p = rb.getLocationOnScreen(); - for (int i = 0; i < 50; i++) { - Color c = r.getPixelColor(p.x + 10 + i, p.y + (rb.getHeight() / 2)); - System.out.println(c); - if (c.getRed() > 200 && c.getBlue() < 200 && c.getGreen() < 200) { - throw new RuntimeException("Test failed. Radiobutton is red " + - "and not grey."); - } + SwingUtilities.invokeAndWait(() -> { + Point p = rb.getLocationOnScreen(); + for (int i = 0; i < 50; i++) { + Color c = r.getPixelColor(p.x + 10 + i, p.y + (rb.getHeight() / 2)); + System.out.println(c); + if (c.getRed() > 200 && c.getBlue() < 80 && c.getGreen() < 80) { + throw new RuntimeException("Test failed. Radiobutton is red " + + "and not grey."); } - }); - } + } + }); } finally { SwingUtilities.invokeAndWait(() -> { if (frame != null) { diff --git a/test/jdk/javax/swing/text/BoxView/BaselineTest.java b/test/jdk/javax/swing/text/BoxView/BaselineTest.java new file mode 100644 index 00000000000..1af8d6cb286 --- /dev/null +++ b/test/jdk/javax/swing/text/BoxView/BaselineTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4519537 4522866 + * @summary Tests that text and components in paragraph views line up at their baselines. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual BaselineTest + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.GridLayout; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; + +import javax.swing.text.ComponentView; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; + +public class BaselineTest { + + static final String INSTRUCTIONS = """ + Test that components displayed in a JTextPane properly respect their vertical alignment. + There are two text panes, stacked vertically with similar content except the bottom components are taller. + The content consists of a leading and trailing text string, with pink coloured components between. + The text string content means the strings 'Default Size Text' and 'Large Size Text'. + Text content baseline is at the bottom of CAPITAL letters in the text. + Each pink component has a string displaying its alignment setting in the range 0.0 to 1.0 + NB: The position of the strings "align = 0.0" etc is not important, it is the component position that matters. + 0.0 means it should be aligned with its top at the text content baseline, + 1.0 means it should be aligned with its bottom at the text content baseline. + A value in between will be a proportional alignment, eg 0.5 is centered on the text content baseline + If the content displays as described, the test PASSES. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("BaselineTest Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .rows(12) + .testUI(BaselineTest::createUI) + .positionTestUIBottomRowCentered() + .build() + .awaitAndCheck(); + } + + public static JFrame createUI() { + JFrame frame = new JFrame("BaselineTest"); + frame.setLayout(new GridLayout(2, 1)); + + JTextPane prefPane = new JTextPane(); + initJTextPane(prefPane); + frame.add(new JScrollPane(prefPane)); + + JTextPane variablePane = new JTextPane(); + variablePane.setEditorKit(new CustomEditorKit()); + initJTextPane(variablePane); + frame.add(new JScrollPane(variablePane)); + frame.setSize(800, 400); + return frame; + } + + static void initJTextPane(JTextPane tp) { + + try { + Document doc = tp.getDocument(); + + doc.insertString(0, " Default Size Text ", null); + tp.setCaretPosition(doc.getLength()); + tp.insertComponent(new PaintLabel(0.0f)); + tp.insertComponent(new PaintLabel(0.2f)); + tp.insertComponent(new PaintLabel(0.5f)); + tp.insertComponent(new PaintLabel(0.7f)); + tp.insertComponent(new PaintLabel(1.0f)); + SimpleAttributeSet set = new SimpleAttributeSet(); + StyleConstants.setFontSize(set, 20); + tp.setCaretPosition(doc.getLength()); + doc.insertString(doc.getLength(), " Large Size Text ", set); + } catch (BadLocationException ble) { + throw new RuntimeException(ble); + } + } + + static class PaintLabel extends JLabel { + + private int pref = 40; + private int min = pref - 30; + private int max = pref + 30; + + public PaintLabel(float align) { + + setAlignmentY(align); + String alignStr = String.valueOf(align); + + setText("align = " + alignStr); + setOpaque(true); + setBackground(Color.PINK); + } + + public Dimension getMinimumSize() { + return new Dimension(super.getMinimumSize().width, min); + } + + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, pref); + } + + public Dimension getMaximumSize() { + return new Dimension(super.getMaximumSize().width, max); + } + + public void paintComponent(Graphics g) { + g.setColor(Color.PINK); + g.fillRect(0, 0, getWidth(), getHeight()); + int y = (int)(getAlignmentY() * getHeight()); + g.setColor(Color.BLACK); + g.drawLine(0, y, getWidth(), y); + g.drawString(getText(), 0, 10); + } + } + + static class CustomComponentView extends ComponentView { + + public CustomComponentView(Element elem) { + super(elem); + } + + public int getResizeWeight(int axis) { + return 1; + } +} + + static class CustomEditorKit extends StyledEditorKit implements ViewFactory { + + public View create(Element elem) { + if (StyleConstants.ComponentElementName.equals(elem.getName())) { + return new CustomComponentView(elem); + } else { + return super.getViewFactory().create(elem); + } + } + + public ViewFactory getViewFactory() { + return this; + } +} + +} diff --git a/test/jdk/javax/swing/text/DefaultEditorKit/4278839/bug4278839.java b/test/jdk/javax/swing/text/DefaultEditorKit/4278839/bug4278839.java index 980a9c9f528..819ba52d270 100644 --- a/test/jdk/javax/swing/text/DefaultEditorKit/4278839/bug4278839.java +++ b/test/jdk/javax/swing/text/DefaultEditorKit/4278839/bug4278839.java @@ -49,6 +49,7 @@ public class bug4278839 { private static JFrame frame; public static void main(String[] args) throws Exception { + int caret; try { robo = new Robot(); @@ -61,24 +62,67 @@ public static void main(String[] args) throws Exception { clickMouse(); robo.waitForIdle(); + robo.delay(250); area.setCaretPosition(0); robo.waitForIdle(); + robo.delay(250); - passed &= moveCaret(true) == 1; - passed &= moveCaret(true) == 5; - passed &= moveCaret(true) == 8; - passed &= moveCaret(true) == 9; - passed &= moveCaret(true) == 13; - passed &= moveCaret(true) == 16; - passed &= moveCaret(true) == 17; - passed &= moveCaret(false) == 16; - passed &= moveCaret(false) == 13; - passed &= moveCaret(false) == 9; - passed &= moveCaret(false) == 8; - passed &= moveCaret(false) == 5; - passed &= moveCaret(false) == 1; - passed &= moveCaret(false) == 0; + passed &= (caret = moveCaret(true)) == 1; + System.out.println(" passed " + passed + + " Expected position 1 actual position " + caret); + + passed &= (caret = moveCaret(true)) == 5; + System.out.println(" passed " + passed + + " Expected position 5 actual position " + caret); + + passed &= (caret = moveCaret(true)) == 8; + System.out.println(" passed " + passed + + " Expected position 8 actual position " + caret); + + passed &= (caret = moveCaret(true)) == 9; + System.out.println(" passed " + passed + + " Expected position 9 actual position " + caret); + + passed &= (caret = moveCaret(true)) == 13; + System.out.println(" passed " + passed + + " Expected position 13 actual position " + caret); + + passed &= (caret = moveCaret(true)) == 16; + System.out.println(" passed " + passed + + " Expected position 16 actual position " + caret); + + passed &= (caret = moveCaret(true)) == 17; + System.out.println(" passed " + passed + + " Expected position 17 actual position " + caret); + + passed &= (caret = moveCaret(false)) == 16; + System.out.println(" passed " + passed + + " Expected position 16 actual position " + caret); + + passed &= (caret = moveCaret(false)) == 13; + System.out.println(" passed " + passed + + " Expected position 13 actual position " + caret); + + passed &= (caret = moveCaret(false)) == 9; + System.out.println(" passed " + passed + + " Expected position 9 actual position " + caret); + + passed &= (caret = moveCaret(false)) == 8; + System.out.println(" passed " + passed + + " Expected position 8 actual position " + caret); + + passed &= (caret = moveCaret(false)) == 5; + System.out.println(" passed " + passed + + " Expected position 5 actual position " + caret); + + passed &= (caret = moveCaret(false)) == 1; + System.out.println(" passed " + passed + + " Expected position 1 actual position " + caret); + + passed &= (caret = moveCaret(false)) == 0; + System.out.println(" passed " + passed + + " Expected position 0 actual position " + caret); } catch (Exception e) { throw new RuntimeException("Test failed because of an exception:", @@ -98,6 +142,7 @@ private static int moveCaret(boolean right) throws Exception { Util.hitKeys(robo, getCtrlKey(), right ? KeyEvent.VK_RIGHT : KeyEvent.VK_LEFT); robo.waitForIdle(); + robo.delay(250); final int[] result = new int[1]; diff --git a/test/jdk/javax/swing/text/GlyphView/bug4188841.java b/test/jdk/javax/swing/text/GlyphView/bug4188841.java new file mode 100644 index 00000000000..9935712bd49 --- /dev/null +++ b/test/jdk/javax/swing/text/GlyphView/bug4188841.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4188841 + * @summary Tests a JTextPane wrapping issue + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4188841 +*/ + +import java.awt.Dimension; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; + +public class bug4188841 { + + static final String INSTRUCTIONS = """ + The text pane contains the phrase "the quick brown fox jumps over the lazy dog", + all the words are separated by tabs. When the test starts, the whole phrase should + appear on one line. If it is wrapped along two or more lines, the test FAILS. + + Otherwise, place the text caret in the very end of the line (e.g. by clicking + in the line and hitting End). Press Enter twice. The text should appear as one + line at all times. If the text wraps when you press Enter, the test FAILS. + """; + + static class NoWrapTextPane extends JTextPane { + + public boolean getScrollableTracksViewportWidth() { + //should not allow text to be wrapped + return false; + } + + public void setSize(Dimension d) { + // don't let the Textpane get sized smaller than its parent + if (d.width < getParent().getSize().width) { + super.setSize(getParent().getSize()); + } + else { + super.setSize(d); + } + } + } + + static JFrame createUI() { + + JFrame frame = new JFrame("bug4188841"); + + NoWrapTextPane nwp = new NoWrapTextPane(); + nwp.setText("the\tquick\tbrown\tfox\tjumps\tover\tthe\tlazy\tdog!"); + nwp.setCaretPosition(nwp.getText().length()); + + JScrollPane scrollPane = new JScrollPane(nwp, + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + + frame.add(scrollPane); + frame.setSize(400, 300); + return frame; + } + + public static void main(String args[]) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4188841::createUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/text/html/FormView/4473401/bug4473401.java b/test/jdk/javax/swing/text/html/FormView/4473401/bug4473401.java new file mode 100644 index 00000000000..29dbba7ca04 --- /dev/null +++ b/test/jdk/javax/swing/text/html/FormView/4473401/bug4473401.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4473401 + * @summary Tests if FormSubmitEvent is submitted correctly. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4473401 +*/ + +import java.io.File; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.text.html.FormSubmitEvent; +import javax.swing.text.html.HTMLEditorKit; + +public class bug4473401 implements HyperlinkListener { + + static final String INSTRUCTIONS = """ + The test window displays an HTML frameset with a frame + on the left and another to the right. + Push the 'Submit Query' button in the left frame to perform testing. + The window should be updated to have only one frame with the + message 'If you see this page the test PASSED'. + If it appears, PASS the test, otherwise FAIL the test. + """; + + static JEditorPane jep; + static JFrame createUI() { + + JFrame frame = new JFrame("bug4473401"); + jep = new JEditorPane(); + jep.addHyperlinkListener(new bug4473401()); + HTMLEditorKit kit = new HTMLEditorKit(); + kit.setAutoFormSubmission(false); + jep.setEditorKit(kit); + jep.setEditable(false); + + try { + File file = new File(System.getProperty("test.src", "."), "frameset.html"); + System.out.println(file.toURI().toURL()); + jep.setPage(file.toURL()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + frame.add(jep); + frame.setSize(500, 500); + return frame; + } + + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e instanceof FormSubmitEvent) { + jep.setText("If you see this page the test PASSED"); + } + } + + public static void main(String args[]) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4473401::createUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/text/html/FormView/4473401/frame1.html b/test/jdk/javax/swing/text/html/FormView/4473401/frame1.html new file mode 100644 index 00000000000..833bc1f6352 --- /dev/null +++ b/test/jdk/javax/swing/text/html/FormView/4473401/frame1.html @@ -0,0 +1,9 @@ + + +Push the Submit query button +
+
+ +
+ + diff --git a/test/jdk/javax/swing/text/html/FormView/4473401/frame2.html b/test/jdk/javax/swing/text/html/FormView/4473401/frame2.html new file mode 100644 index 00000000000..5bc6dba57fc --- /dev/null +++ b/test/jdk/javax/swing/text/html/FormView/4473401/frame2.html @@ -0,0 +1,4 @@ + + + + diff --git a/test/jdk/javax/swing/text/html/FormView/4473401/frameresult.html b/test/jdk/javax/swing/text/html/FormView/4473401/frameresult.html new file mode 100644 index 00000000000..6ef5c8198cc --- /dev/null +++ b/test/jdk/javax/swing/text/html/FormView/4473401/frameresult.html @@ -0,0 +1,5 @@ + + +If you see this page the test FAILED. + + diff --git a/test/jdk/javax/swing/text/html/FormView/4473401/frameset.html b/test/jdk/javax/swing/text/html/FormView/4473401/frameset.html new file mode 100644 index 00000000000..1e7f8298d62 --- /dev/null +++ b/test/jdk/javax/swing/text/html/FormView/4473401/frameset.html @@ -0,0 +1,11 @@ + + + + Manual test for bug 4463014 + + + + + + + \ No newline at end of file diff --git a/test/jdk/javax/swing/text/html/FormView/bug4529702.java b/test/jdk/javax/swing/text/html/FormView/bug4529702.java new file mode 100644 index 00000000000..4962a0a6663 --- /dev/null +++ b/test/jdk/javax/swing/text/html/FormView/bug4529702.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4529702 + * @summary Test that radio buttons with different names should be selectable at the same time + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4529702 +*/ + +import javax.swing.JFrame; +import javax.swing.JTextPane; + +public class bug4529702 { + + static final String INSTRUCTIONS = """ + There are two rows of radio buttons, each row having two buttons. + If you can select radio buttons from the first and the second rows + at the same time the test PASSES otherwise the test FAILS. + """; + + static JFrame createUI() { + JFrame frame = new JFrame("bug4529702"); + JTextPane jtp = new JTextPane(); + jtp.setContentType("text/html"); + jtp.setText("

" + + "
"); + frame.add(jtp); + frame.setSize(200, 200); + return frame; + } + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4529702::createUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/text/html/FrameSetView/4890934/bug4890934.java b/test/jdk/javax/swing/text/html/FrameSetView/4890934/bug4890934.java new file mode 100644 index 00000000000..988db296f7b --- /dev/null +++ b/test/jdk/javax/swing/text/html/FrameSetView/4890934/bug4890934.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 4890934 + * @summary Tests if JEditor Pane updates the correct frame when using + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4890934 +*/ + +import java.io.File; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.HTMLFrameHyperlinkEvent; + +public class bug4890934 implements HyperlinkListener { + + static final String INSTRUCTIONS = """ + The test window displays an HTML frameset with a frame + on the left and another to the right. + Click the link in the left frame which should change the view. + The resulting page will tell you if the test PASSED or FAILED. + """; + + static JFrame createUI() { + + JFrame frame = new JFrame("bug4890934"); + JEditorPane jep = new JEditorPane(); + jep.setEditorKit(new HTMLEditorKit()); + jep.setEditable(false); + jep.addHyperlinkListener(new bug4890934()); + + try { + File file = new File(System.getProperty("test.src", "."), "frameset.html"); + System.out.println(file.toURI().toURL()); + jep.setPage(file.toURL()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + frame.add(jep); + frame.setSize(600, 300); + return frame; + } + + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + JEditorPane pane = (JEditorPane) e.getSource(); + if (e instanceof HTMLFrameHyperlinkEvent) { + HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent)e; + HTMLDocument doc = (HTMLDocument)pane.getDocument(); + doc.processHTMLFrameHyperlinkEvent(evt); + } + } + } + + public static void main(String args[]) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4890934::createUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/text/html/FrameSetView/4890934/frame1.html b/test/jdk/javax/swing/text/html/FrameSetView/4890934/frame1.html new file mode 100644 index 00000000000..31f95568aae --- /dev/null +++ b/test/jdk/javax/swing/text/html/FrameSetView/4890934/frame1.html @@ -0,0 +1,8 @@ + + + + + + a link + + diff --git a/test/jdk/javax/swing/text/html/FrameSetView/4890934/frame2.html b/test/jdk/javax/swing/text/html/FrameSetView/4890934/frame2.html new file mode 100644 index 00000000000..5bc6dba57fc --- /dev/null +++ b/test/jdk/javax/swing/text/html/FrameSetView/4890934/frame2.html @@ -0,0 +1,4 @@ + + + + diff --git a/test/jdk/javax/swing/text/html/FrameSetView/4890934/frameresult.html b/test/jdk/javax/swing/text/html/FrameSetView/4890934/frameresult.html new file mode 100644 index 00000000000..a31045833b5 --- /dev/null +++ b/test/jdk/javax/swing/text/html/FrameSetView/4890934/frameresult.html @@ -0,0 +1,7 @@ + + +If you see this text in the RIGHT frame the test PASSED. +

If you see this text in the LEFT frame the test FAILED. + + + diff --git a/test/jdk/javax/swing/text/html/FrameSetView/4890934/frameset.html b/test/jdk/javax/swing/text/html/FrameSetView/4890934/frameset.html new file mode 100644 index 00000000000..9462e1894a5 --- /dev/null +++ b/test/jdk/javax/swing/text/html/FrameSetView/4890934/frameset.html @@ -0,0 +1,11 @@ + + + + Manual test for bug 4463014 + + + + + + + diff --git a/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java b/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java index a97edd581fe..3ab8b35ae0a 100644 --- a/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java +++ b/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Red Hat, Inc. + * Copyright (c) 2022, 2025, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,9 @@ public void testCgPathNonEmptyRoot() { assertEquals(expectedPath, ctrl.path()); } + /* + * Less common cases: Containers + */ @Test public void testCgPathSubstring() { String root = "/foo/bar/baz"; @@ -71,8 +74,18 @@ public void testCgPathSubstring() { CgroupV1SubsystemController ctrl = new CgroupV1SubsystemController(root, mountPoint); String cgroupPath = "/foo/bar/baz/some"; ctrl.setPath(cgroupPath); - String expectedPath = mountPoint + "/some"; + String expectedPath = mountPoint; assertEquals(expectedPath, ctrl.path()); } + @Test + public void testCgPathToMovedPath() { + String root = "/system.slice/garden.service/garden/good/2f57368b-0eda-4e52-64d8-af5c"; + String mountPoint = "/sys/fs/cgroup/cpu,cpuacct"; + CgroupV1SubsystemController ctrl = new CgroupV1SubsystemController(root, mountPoint); + String cgroupPath = "/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c"; + ctrl.setPath(cgroupPath); + String expectedPath = mountPoint; + assertEquals(expectedPath, ctrl.path()); + } } diff --git a/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java b/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java index ede74b5011e..8cf53c66e8a 100644 --- a/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java +++ b/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Red Hat Inc. + * Copyright (c) 2020, 2025, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ import jdk.internal.platform.CgroupSubsystemFactory.CgroupTypeResult; import jdk.internal.platform.CgroupV1MetricsImpl; import jdk.internal.platform.cgroupv1.CgroupV1Subsystem; +import jdk.internal.platform.cgroupv1.CgroupV1SubsystemController; import jdk.internal.platform.Metrics; import jdk.test.lib.Utils; import jdk.test.lib.util.FileUtils; @@ -75,8 +76,10 @@ public class TestCgroupSubsystemFactory { private Path cgroupv1MntInfoDoubleControllers; private Path cgroupv1MntInfoDoubleControllers2; private Path cgroupv1MntInfoColonsHierarchy; + private Path cgroupv1MntInfoNonTrivialRoot; private Path cgroupv1SelfCgroup; private Path cgroupv1SelfColons; + private Path cgroupv1SelfNonTrivialRoot; private Path cgroupv2SelfCgroup; private Path cgroupv1SelfCgroupJoinCtrl; private Path cgroupv1CgroupsOnlyCPUCtrl; @@ -175,6 +178,7 @@ public class TestCgroupSubsystemFactory { "42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup none rw,seclabel,cpuset\n" + "43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup none rw,seclabel,blkio\n" + "44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer\n"; + private String mntInfoNonTrivialRoot = "2207 2196 0:43 /system.slice/garden.service/garden/good/2f57368b-0eda-4e52-64d8-af5c /sys/fs/cgroup/cpu,cpuacct ro,nosuid,nodev,noexec,relatime master:25 - cgroup cgroup rw,cpu,cpuacct\n"; private String cgroupsNonZeroHierarchy = "#subsys_name hierarchy num_cgroups enabled\n" + "cpuset 9 1 1\n" + @@ -230,6 +234,7 @@ public class TestCgroupSubsystemFactory { "2:cpu,cpuacct:/\n" + "1:name=systemd:/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n" + "0::/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n"; + private String cgroupv1SelfNTRoot = "11:cpu,cpuacct:/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c\n"; private String cgroupv2SelfCgroupContent = "0::/user.slice/user-1000.slice/session-2.scope"; // We have a mix of V1 and V2 controllers, but none of the V1 controllers @@ -294,12 +299,18 @@ public void setup() { cgroupv1MntInfoColonsHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_colons"); Files.writeString(cgroupv1MntInfoColonsHierarchy, mntInfoColons); + cgroupv1MntInfoNonTrivialRoot = Paths.get(existingDirectory.toString(), "mountinfo_nt_root"); + Files.writeString(cgroupv1MntInfoNonTrivialRoot, mntInfoNonTrivialRoot); + cgroupv1SelfCgroup = Paths.get(existingDirectory.toString(), "self_cgroup_cgv1"); Files.writeString(cgroupv1SelfCgroup, cgroupv1SelfCgroupContent); cgroupv1SelfColons = Paths.get(existingDirectory.toString(), "self_colons_cgv1"); Files.writeString(cgroupv1SelfColons, cgroupv1SelfColonsContent); + cgroupv1SelfNonTrivialRoot = Paths.get(existingDirectory.toString(), "self_nt_root_cgv1"); + Files.writeString(cgroupv1SelfNonTrivialRoot, cgroupv1SelfNTRoot); + cgroupv2SelfCgroup = Paths.get(existingDirectory.toString(), "self_cgroup_cgv2"); Files.writeString(cgroupv2SelfCgroup, cgroupv2SelfCgroupContent); @@ -449,6 +460,27 @@ public void testColonsCgroupsV1() throws IOException { assertEquals(memoryInfo.getMountRoot(), memoryInfo.getCgroupPath()); } + @Test + public void testMountPrefixCgroupsV1() throws IOException { + String cgroups = cgroupv1CgInfoNonZeroHierarchy.toString(); + String mountInfo = cgroupv1MntInfoNonTrivialRoot.toString(); + String selfCgroup = cgroupv1SelfNonTrivialRoot.toString(); + Optional result = CgroupSubsystemFactory.determineType(mountInfo, cgroups, selfCgroup); + + assertTrue("Expected non-empty cgroup result", result.isPresent()); + CgroupTypeResult res = result.get(); + CgroupInfo cpuInfo = res.getInfos().get("cpu"); + assertEquals(cpuInfo.getCgroupPath(), "/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c"); + String expectedMountPoint = "/sys/fs/cgroup/cpu,cpuacct"; + assertEquals(expectedMountPoint, cpuInfo.getMountPoint()); + CgroupV1SubsystemController cgroupv1MemoryController = new CgroupV1SubsystemController(cpuInfo.getMountRoot(), cpuInfo.getMountPoint()); + cgroupv1MemoryController.setPath(cpuInfo.getCgroupPath()); + String actualPath = cgroupv1MemoryController.path(); + assertNotNull(actualPath); + String expectedPath = expectedMountPoint; + assertEquals("Should be equal to the mount point path", expectedPath, actualPath); + } + @Test public void testZeroHierarchyCgroupsV1() throws IOException { String cgroups = cgroupv1CgInfoZeroHierarchy.toString(); diff --git a/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java index 92b8cf282b7..b7721899ea3 100644 --- a/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020, 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java b/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java index 6307a93fa56..8069965e8d8 100644 --- a/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java +++ b/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ public static void main(String[] args) { case "softlimit": testMemorySoftLimit(args[1]); break; + default: + throw new RuntimeException("unknown args: " + args[0] + " for MetricsMemoryTester"); } } diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java index 72f8a1ceac7..9a531d692ed 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Red Hat, Inc. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * 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 +27,7 @@ * @bug 8293540 * @summary Verify that -XshowSettings:system works * @key cgroups - * @requires docker.support + * @requires container.support * @requires !vm.asan * @library /test/lib * @run main/timeout=360 TestDockerBasic diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java index 952457b8f1f..ff039913b8f 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +34,7 @@ * @test * @key cgroups * @summary Test JDK Metrics class when running inside docker container - * @requires docker.support + * @requires container.support * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java index 4d0ef13da87..7cbab5c3b86 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * 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 @@ * @test * @key cgroups * @summary Test JDK Metrics class when running inside docker container - * @requires docker.support + * @requires container.support * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform @@ -76,7 +76,7 @@ public static void main(String[] args) throws Exception { } testOomKillFlag("100m", true); - testMemoryFailCount("64m"); + testMemoryFailCount("128m"); testMemorySoftLimit("500m","200m"); diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java new file mode 100644 index 00000000000..c6b94370807 --- /dev/null +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2025, BELLSOFT. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.internal.platform.Metrics; +import jdk.test.lib.Container; +import jdk.test.lib.Utils; +import jdk.test.lib.containers.docker.Common; +import jdk.test.lib.containers.docker.DockerfileConfig; +import jdk.test.lib.containers.docker.DockerRunOptions; +import jdk.test.lib.containers.docker.DockerTestUtils; +import jdk.test.lib.containers.docker.ContainerRuntimeVersionTestUtils; + +import java.util.ArrayList; + +import jtreg.SkippedException; + +/* + * @test + * @bug 8343191 + * @key cgroups + * @summary Cgroup v1 subsystem fails to set subsystem path + * @requires container.support + * @library /test/lib + * @modules java.base/jdk.internal.platform + * @build MetricsMemoryTester + * @run main TestDockerMemoryMetricsSubgroup + */ + +public class TestDockerMemoryMetricsSubgroup { + private static final String imageName = + DockerfileConfig.getBaseImageName() + ":" + + DockerfileConfig.getBaseImageVersion(); + + static String getEngineInfo(String format) throws Exception { + return DockerTestUtils.execute(Container.ENGINE_COMMAND, "info", "-f", format) + .getStdout(); + } + + static boolean isRootless() throws Exception { + // Docker and Podman have different INFO structures. + // The node path for Podman is .Host.Security.Rootless, that also holds for + // Podman emulating Docker CLI. The node path for Docker is .SecurityOptions. + return (getEngineInfo("{{.Host.Security.Rootless}}").contains("true") || + getEngineInfo("{{.SecurityOptions}}").contains("name=rootless")); + } + + public static void main(String[] args) throws Exception { + Metrics metrics = Metrics.systemMetrics(); + if (metrics == null) { + System.out.println("Cgroup not configured."); + return; + } + if (!DockerTestUtils.canTestDocker()) { + System.out.println("Unable to run docker tests."); + return; + } + + ContainerRuntimeVersionTestUtils.checkContainerVersionSupported(); + + if (isRootless()) { + throw new SkippedException("Test skipped in rootless mode"); + } + + if ("cgroupv1".equals(metrics.getProvider())) { + testMemoryLimitSubgroupV1("200m", "400m", false); + testMemoryLimitSubgroupV1("500m", "1G", false); + testMemoryLimitSubgroupV1("200m", "400m", true); + testMemoryLimitSubgroupV1("500m", "1G", true); + } else if ("cgroupv2".equals(metrics.getProvider())) { + testMemoryLimitSubgroupV2("200m", "400m", false); + testMemoryLimitSubgroupV2("500m", "1G", false); + testMemoryLimitSubgroupV2("200m", "400m", true); + testMemoryLimitSubgroupV2("500m", "1G", true); + } else { + throw new SkippedException("Metrics are from neither cgroup v1 nor v2, skipped for now."); + } + } + + private static void testMemoryLimitSubgroupV1(String innerSize, String outerGroupMemorySize, boolean privateNamespace) throws Exception { + Common.logNewTestCase("testMemoryLimitSubgroup, innerSize = " + innerSize); + DockerRunOptions opts = + new DockerRunOptions(imageName, "sh", "-c"); + opts.javaOpts = new ArrayList<>(); + opts.appendTestJavaOptions = false; + opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") + .addDockerOpts("--volume", Utils.TEST_JDK + ":/jdk") + .addDockerOpts("--privileged") + .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host")) + .addDockerOpts("--memory", outerGroupMemorySize); + opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " + + "echo " + innerSize + " > /sys/fs/cgroup/memory/test/memory.limit_in_bytes ; " + + "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " + + "/jdk/bin/java -cp /test-classes/ " + + "--add-exports java.base/jdk.internal.platform=ALL-UNNAMED " + + "MetricsMemoryTester memory " + innerSize); + + DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); + } + + private static void testMemoryLimitSubgroupV2(String innerSize, String outerGroupMemorySize, boolean privateNamespace) throws Exception { + Common.logNewTestCase("testMemoryLimitSubgroup, innerSize = " + innerSize); + DockerRunOptions opts = + new DockerRunOptions(imageName, "sh", "-c"); + opts.javaOpts = new ArrayList<>(); + opts.appendTestJavaOptions = false; + opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") + .addDockerOpts("--volume", Utils.TEST_JDK + ":/jdk") + .addDockerOpts("--privileged") + .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host")) + .addDockerOpts("--memory", outerGroupMemorySize); + opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " + + "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " + + "echo '+memory' > /sys/fs/cgroup/cgroup.subtree_control ; " + + "echo '+memory' > /sys/fs/cgroup/memory/cgroup.subtree_control ; " + + "echo " + innerSize + " > /sys/fs/cgroup/memory/test/memory.max ; " + + "/jdk/bin/java -cp /test-classes/ " + + "--add-exports java.base/jdk.internal.platform=ALL-UNNAMED " + + "MetricsMemoryTester memory " + innerSize); + + DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); + } +} diff --git a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java index 5a82a2df4ad..b9d031f0309 100644 --- a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java @@ -1,5 +1,6 @@ /* - * Copyright (C) 2020, 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, 2022, Tencent. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * 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 +26,7 @@ * @test * @key cgroups * @bug 8242480 - * @requires docker.support + * @requires container.support * @requires !vm.asan * @library /test/lib * @build GetFreeSwapSpaceSize diff --git a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java index b78681640a8..31e90e8802a 100644 --- a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java +++ b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Red Hat, Inc. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,7 +29,7 @@ * @bug 8308090 * @key cgroups * @summary Test container limits updating as they get updated at runtime without restart - * @requires docker.support + * @requires container.support * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform diff --git a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java index 99404ab427d..6b19bb475f1 100644 --- a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java +++ b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,7 +27,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside a docker container with limited pids * @bug 8266490 - * @requires docker.support + * @requires container.support * @requires !vm.asan * @library /test/lib * @build TestPidsLimit diff --git a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java index b652a55bc0d..49ec5663478 100644 --- a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * 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 * @key cgroups * @summary Test JDK Metrics class when running inside docker container - * @requires docker.support + * @requires container.support * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform diff --git a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java index c78cf4c779a..d8d300401a0 100644 --- a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java +++ b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, Red Hat, Inc. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * 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 +25,7 @@ /* * @test * @summary UseContainerSupport flag should reflect Metrics being available - * @requires docker.support + * @requires container.support * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform diff --git a/test/jdk/jdk/jfr/api/flightrecorder/TestSettingsControl.java b/test/jdk/jdk/jfr/api/flightrecorder/TestSettingsControl.java index 0b54f218c43..01eb803af80 100644 --- a/test/jdk/jdk/jfr/api/flightrecorder/TestSettingsControl.java +++ b/test/jdk/jdk/jfr/api/flightrecorder/TestSettingsControl.java @@ -28,6 +28,7 @@ import java.util.Set; import jdk.jfr.Event; +import jdk.jfr.Name; import jdk.jfr.Recording; import jdk.jfr.SettingControl; import jdk.jfr.SettingDefinition; @@ -42,7 +43,7 @@ public class TestSettingsControl { static class MySettingsControl extends SettingControl { - public static boolean setWasCalled; + public static boolean myvalueSet; private String value = "default"; @@ -57,7 +58,9 @@ public String combine(Set values) { @Override public void setValue(String value) { - setWasCalled = true; + if ("myvalue".equals(value)) { + myvalueSet = true; + } this.value = value; } @@ -67,9 +70,10 @@ public String getValue() { } } - + @Name("M") static class MyCustomSettingEvent extends Event { @SettingDefinition + @Name("m") boolean mySetting(MySettingsControl msc) { return true; } @@ -77,13 +81,13 @@ boolean mySetting(MySettingsControl msc) { public static void main(String[] args) throws Throwable { Recording r = new Recording(); - r.enable(MyCustomSettingEvent.class).with("mySetting", "myvalue"); + r.enable("M").with("m", "myvalue"); r.start(); MyCustomSettingEvent e = new MyCustomSettingEvent(); e.commit(); r.stop(); r.close(); - assertTrue(MySettingsControl.setWasCalled, "SettingControl.setValue was not called"); + assertTrue(MySettingsControl.myvalueSet, "SettingControl.setValue(\"myvalue\") was not called"); } } diff --git a/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWith32BitOops.java b/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWith32BitOops.java index 0a61a288cc2..9cbc31e55f8 100644 --- a/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWith32BitOops.java +++ b/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWith32BitOops.java @@ -35,6 +35,8 @@ * @requires vm.gc == "Parallel" | vm.gc == null * @requires os.family == "linux" | os.family == "windows" * @requires sun.arch.data.model == "64" + * @comment Asan changes memory layout and we get a different coops mode + * @requires !vm.asan * @library /test/lib /test/jdk * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox diff --git a/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWithZeroBasedOops.java b/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWithZeroBasedOops.java index d63ca856bc3..918f1391b2c 100644 --- a/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWithZeroBasedOops.java +++ b/test/jdk/jdk/jfr/event/gc/configuration/TestGCHeapConfigurationEventWithZeroBasedOops.java @@ -33,6 +33,8 @@ * @requires vm.gc == "Parallel" | vm.gc == null * @requires os.family == "linux" | os.family == "windows" * @requires sun.arch.data.model == "64" + * @comment Asan changes memory layout and we get a different coops mode + * @requires !vm.asan * @library /test/lib /test/jdk * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseParallelGC -XX:+UseCompressedOops -Xmx4g jdk.jfr.event.gc.configuration.TestGCHeapConfigurationEventWithZeroBasedOops */ diff --git a/test/jdk/jdk/jfr/event/os/TestCPULoad.java b/test/jdk/jdk/jfr/event/os/TestCPULoad.java index efc9b39adf5..1edb1639699 100644 --- a/test/jdk/jdk/jfr/event/os/TestCPULoad.java +++ b/test/jdk/jdk/jfr/event/os/TestCPULoad.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * 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,7 +30,6 @@ import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; - /** * @test * @key jfr @@ -41,13 +40,32 @@ public class TestCPULoad { private final static String EVENT_NAME = EventNames.CPULoad; + public static boolean isPrime(int num) { + if (num <= 1) return false; + for (int i = 2; i <= Math.sqrt(num); i++) { + if (num % i == 0) return false; + } + return true; + } + + public static int burnCpuCycles(int limit) { + int primeCount = 0; + for (int i = 2; i < limit; i++) { + if (isPrime(i)) { + primeCount++; + } + } + return primeCount; + } + public static void main(String[] args) throws Throwable { Recording recording = new Recording(); recording.enable(EVENT_NAME); recording.start(); - // Need to sleep so a time delta can be calculated - Thread.sleep(100); + // burn some cycles to check increase of CPU related counters + int pn = burnCpuCycles(2500000); recording.stop(); + System.out.println("Found " + pn + " primes while burning cycles"); List events = Events.fromRecording(recording); if (events.isEmpty()) { diff --git a/test/jdk/sun/awt/font/TestDevTransform.java b/test/jdk/sun/awt/font/TestDevTransform.java index 2783401c0f2..39d4255f154 100644 --- a/test/jdk/sun/awt/font/TestDevTransform.java +++ b/test/jdk/sun/awt/font/TestDevTransform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * 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,9 +22,31 @@ */ /* - * @test + * @test id=dialog_double * @bug 4269775 8341535 * @summary Check that different text rendering APIs agree + * @run main/othervm TestDevTransform DIALOG DOUBLE + */ + +/* + * @test id=dialog_float + * @bug 4269775 8341535 + * @summary Check that different text rendering APIs agree + * @run main/othervm TestDevTransform DIALOG FLOAT + */ + +/* + * @test id=monospaced_double + * @bug 4269775 8341535 + * @summary Check that different text rendering APIs agree + * @run main/othervm TestDevTransform MONOSPACED DOUBLE + */ + +/* + * @test id=monospaced_float + * @bug 4269775 8341535 + * @summary Check that different text rendering APIs agree + * @run main/othervm TestDevTransform MONOSPACED FLOAT */ /** @@ -66,6 +88,8 @@ public class TestDevTransform { static String test = "This is only a test"; static double angle = Math.PI / 6.0; // Rotate 30 degrees static final int W = 400, H = 400; + static boolean useDialog; + static boolean useDouble; static void draw(Graphics2D g2d, TextLayout layout, float x, float y, float scalex) { @@ -101,9 +125,19 @@ static void init(Graphics2D g2d) { g2d.setColor(Color.white); g2d.fillRect(0, 0, W, H); g2d.setColor(Color.black); - g2d.scale(1.481f, 1.481); // Convert to 108 dpi + if (useDouble) { + g2d.scale(1.481, 1.481); // Convert to 108 dpi + } else { + g2d.scale(1.481f, 1.481f); // Convert to 108 dpi + } g2d.addRenderingHints(hints); - Font font = new Font(Font.DIALOG, Font.PLAIN, 12); + String name; + if (useDialog) { + name = Font.DIALOG; + } else { + name = Font.MONOSPACED; + } + Font font = new Font(name, Font.PLAIN, 12); g2d.setFont(font); } @@ -135,6 +169,12 @@ static void compare(BufferedImage bi1, String name1, BufferedImage bi2, String n } public static void main(String args[]) throws Exception { + if (args[0].equals("DIALOG")) { + useDialog = true; + } + if (args[1].equals("DOUBLE")) { + useDouble = true; + } BufferedImage tl_Image = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB); { diff --git a/test/jdk/sun/java2d/cmm/ColorConvertOp/FilterSemiCustomImages.java b/test/jdk/sun/java2d/cmm/ColorConvertOp/FilterSemiCustomImages.java new file mode 100644 index 00000000000..ff3fcde7482 --- /dev/null +++ b/test/jdk/sun/java2d/cmm/ColorConvertOp/FilterSemiCustomImages.java @@ -0,0 +1,162 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.Color; +import java.awt.Point; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; +import java.awt.image.ColorModel; +import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; +import java.io.File; + +import javax.imageio.ImageIO; + +import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR; +import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR; +import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE; +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; +import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE; +import static java.awt.image.BufferedImage.TYPE_INT_BGR; +import static java.awt.image.BufferedImage.TYPE_INT_RGB; +import static java.awt.image.BufferedImage.TYPE_USHORT_GRAY; + +/** + * @test + * @bug 8366208 + * @summary Verifies ColorConvertOp works correctly with BufferedImage and + * semi-custom raster + */ +public final class FilterSemiCustomImages { + + private static final int W = 144; + private static final int H = 123; + + private static final int[] TYPES = { + TYPE_INT_RGB, TYPE_INT_ARGB, TYPE_INT_ARGB_PRE, TYPE_INT_BGR, + TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR, TYPE_4BYTE_ABGR_PRE, + TYPE_USHORT_GRAY + }; + + private static final int[] CSS = { + ColorSpace.CS_CIEXYZ, ColorSpace.CS_GRAY, ColorSpace.CS_LINEAR_RGB, + ColorSpace.CS_PYCC, ColorSpace.CS_sRGB + }; + + private static final class CustomRaster extends WritableRaster { + CustomRaster(SampleModel sampleModel, Point origin) { + super(sampleModel, origin); + } + } + + public static void main(String[] args) throws Exception { + for (int fromIndex : CSS) { + for (int toIndex : CSS) { + if (fromIndex != toIndex) { + for (int type : TYPES) { + test(fromIndex, toIndex, type); + } + } + } + } + } + + private static void test(int fromIndex, int toIndex, int type) + throws Exception + { + ColorSpace fromCS = ColorSpace.getInstance(fromIndex); + ColorSpace toCS = ColorSpace.getInstance(toIndex); + ColorConvertOp op = new ColorConvertOp(fromCS, toCS, null); + + // standard source -> standard dst + BufferedImage srcGold = new BufferedImage(W, H, type); + fill(srcGold); + BufferedImage dstGold = new BufferedImage(W, H, type); + op.filter(srcGold, dstGold); + + // custom source -> standard dst + BufferedImage srcCustom = makeCustomBI(srcGold); + fill(srcCustom); + BufferedImage dst = new BufferedImage(W, H, type); + op.filter(srcCustom, dst); + verify(dstGold, dst); + + // standard source -> custom dst + BufferedImage src = new BufferedImage(W, H, type); + fill(src); + BufferedImage dstCustom = makeCustomBI(dstGold); + op.filter(src, dstCustom); + verify(dstGold, dstCustom); + + // custom source -> custom dst + srcCustom = makeCustomBI(srcGold); + fill(srcCustom); + dstCustom = makeCustomBI(dstGold); + op.filter(srcCustom, dstCustom); + verify(dstGold, dstCustom); + } + + private static BufferedImage makeCustomBI(BufferedImage bi) { + ColorModel cm = bi.getColorModel(); + SampleModel sm = bi.getSampleModel(); + CustomRaster cr = new CustomRaster(sm, new Point()); + return new BufferedImage(cm, cr, bi.isAlphaPremultiplied(), null) { + @Override + public int getType() { + return bi.getType(); + } + }; + } + + private static void fill(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + for (int x = 0; x < width; ++x) { + for (int y = 0; y < height; ++y) { + // alpha channel may be calculated slightly differently on + // different code paths, so only check fully transparent and + // fully opaque pixels + Color c = new Color(y * 255 / (height - 1), + x * 255 / (width - 1), + x % 255, + (x % 2 == 0) ? 0 : 255); + image.setRGB(x, y, c.getRGB()); + } + } + } + + private static void verify(BufferedImage dstGold, BufferedImage dst) + throws Exception + { + for (int x = 0; x < W; ++x) { + for (int y = 0; y < H; ++y) { + if (dst.getRGB(x, y) != dstGold.getRGB(x, y)) { + ImageIO.write(dst, "png", new File("custom.png")); + ImageIO.write(dstGold, "png", new File("gold.png")); + throw new RuntimeException("Test failed."); + } + } + } + } +} diff --git a/test/jdk/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java b/test/jdk/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java index 1a59b0df118..b4291645007 100644 --- a/test/jdk/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java +++ b/test/jdk/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,7 @@ public final class MonitorVmStartTerminate { private static final int PROCESS_COUNT = 10; + private static final int ARGS_ATTEMPTS = 10; public static void main(String... args) throws Exception { @@ -175,8 +176,6 @@ private void releaseTerminated(Integer id) { } } - private static final int ARGS_ATTEMPTS = 3; - private boolean hasMainArgs(Integer id, String args) { VmIdentifier vmid = null; try { @@ -204,7 +203,10 @@ private boolean hasMainArgs(Integer id, String args) { } catch (MonitorException e) { // Process probably not running or not ours, e.g. // sun.jvmstat.monitor.MonitorException: Could not attach to PID - System.out.println("hasMainArgs(" + id + "): " + e); + // Only log if something else, to avoid filling log: + if (!e.getMessage().contains("Could not attach")) { + System.out.println("hasMainArgs(" + id + "): " + e); + } } } return false; @@ -249,23 +251,15 @@ private static void createFile(Path path) throws IOException { } private static void waitForRemoval(Path path) { - String timeoutFactorText = System.getProperty("test.timeout.factor", "1.0"); - double timeoutFactor = Double.parseDouble(timeoutFactorText); - long timeoutNanos = 1000_000_000L*(long)(1000*timeoutFactor); long start = System.nanoTime(); + System.out.println("Waiting for " + path + " to be removed"); while (true) { long now = System.nanoTime(); long waited = now - start; - System.out.println("Waiting for " + path + " to be removed, " + waited + " ns"); if (!Files.exists(path)) { + System.out.println("waitForRemoval: " + path + " has been removed in " + waited + " ns"); return; } - if (waited > timeoutNanos) { - System.out.println("Start: " + start); - System.out.println("Now: " + now); - System.out.println("Process timed out after " + waited + " ns. Abort."); - System.exit(1); - } takeNap(); } } diff --git a/test/jdk/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java b/test/jdk/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java index ddbca2c444d..7d1756be062 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ import java.nio.file.attribute.PosixFilePermission; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -47,7 +46,6 @@ * @author Taras Ledkov */ public abstract class AbstractFilePermissionTest { - private final String TEST_CLASS_PATH = System.getProperty("test.class.path"); protected final String TEST_CLASSES = System.getProperty("test.classes"); protected final FileSystem FS = FileSystems.getDefault(); private int MAX_GET_FREE_PORT_TRIES = 10; @@ -169,11 +167,8 @@ private int doTest() throws Exception { final String pp = "-Dcom.sun.management.jmxremote.port=" + jdk.test.lib.Utils.getFreePort(); List command = new ArrayList<>(); - Collections.addAll(command, jdk.test.lib.Utils.getTestJavaOpts()); command.add(mp); command.add(pp); - command.add("-cp"); - command.add(TEST_CLASSES); command.add(className); ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(command); diff --git a/test/jdk/sun/management/jmxremote/bootstrap/LocalManagementTest.java b/test/jdk/sun/management/jmxremote/bootstrap/LocalManagementTest.java index 0a7c735e2e0..b6e478528d9 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/LocalManagementTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/LocalManagementTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * 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,12 +24,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.Utils; /** * @test @@ -48,7 +46,6 @@ * @run main/othervm/timeout=300 LocalManagementTest */ public class LocalManagementTest { - private static final String TEST_CLASSPATH = System.getProperty("test.class.path"); public static void main(String[] args) throws Exception { int failures = 0; @@ -99,16 +96,13 @@ private static boolean test5() throws Exception { private static boolean doTest(String testId, String arg) throws Exception { List args = new ArrayList<>(); args.add("-XX:+UsePerfData"); - Collections.addAll(args, Utils.getTestJavaOpts()); - args.add("-cp"); - args.add(TEST_CLASSPATH); if (arg != null) { args.add(arg); } args.add("TestApplication"); ProcessBuilder server = ProcessTools.createTestJavaProcessBuilder( - args.toArray(new String[args.size()]) + args.toArray(new String[0]) ); Process serverPrc = null, clientPrc = null; @@ -134,8 +128,6 @@ private static boolean doTest(String testId, String arg) throws Exception { System.out.println(" shutdown port : " + port.get()); ProcessBuilder client = ProcessTools.createTestJavaProcessBuilder( - "-cp", - TEST_CLASSPATH, "--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED", "TestManager", String.valueOf(serverPrc.pid()), diff --git a/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java b/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java index 6cc5708b385..1aa20937962 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; -import java.net.BindException; import java.nio.charset.Charset; import java.nio.file.FileSystem; import java.nio.file.FileSystems; @@ -180,12 +179,9 @@ private int doTest(String... args) throws Exception { initTestEnvironment(); List command = new ArrayList<>(); - Collections.addAll(command, Utils.getTestJavaOpts()); command.add("-Dtest.src=" + TEST_SRC); command.add("-Dtest.rmi.port=" + port); command.addAll(Arrays.asList(args)); - command.add("-cp"); - command.add(TEST_CLASS_PATH); command.add(className); ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(command); diff --git a/test/jdk/sun/net/www/protocol/file/FileURLTest.java b/test/jdk/sun/net/www/protocol/file/FileURLTest.java index 135274a9504..e111a538aca 100644 --- a/test/jdk/sun/net/www/protocol/file/FileURLTest.java +++ b/test/jdk/sun/net/www/protocol/file/FileURLTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4474391 * @summary url: file:///D|/Projects/tmp/test.html: urlConnection.getInputStream() broken. + * @requires os.family == "windows" */ import java.io.*; import java.net.*; @@ -33,10 +34,7 @@ public class FileURLTest { public static void main(String [] args) { - String name = System.getProperty("os.name"); - if (name.startsWith("Windows")) { String urlStr = "file:///C|/nonexisted.txt"; - try { URL url = new URL(urlStr); URLConnection urlConnection = url.openConnection(); @@ -49,6 +47,5 @@ public static void main(String [] args) throw new RuntimeException("Can't handle '|' in place of ':' in file urls"); } } - } } } diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java index 6ea62526566..9ce71064b54 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java @@ -34,379 +34,41 @@ * @author Xuelei Fan */ -import java.net.*; -import java.util.*; -import java.io.*; -import javax.net.ssl.*; -import java.security.Security; + +import java.io.PrintStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.security.KeyPair; +import java.security.KeyPairGenerator; import java.security.KeyStore; -import java.security.KeyFactory; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.X509Certificate; + import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.spec.*; -import java.security.interfaces.*; import java.math.BigInteger; import jdk.test.lib.net.URIBuilder; - -/* - * Certificates and key used in the test. - * - * TLS server certificate: - * server private key: - * -----BEGIN RSA PRIVATE KEY----- - * Proc-Type: 4,ENCRYPTED - * DEK-Info: DES-EDE3-CBC,D9AE407F6D0E389A - * - * WPrA7TFol/cQCcp9oHnXWNpYlvRbbIcQj0m+RKT2Iuzfus+DHt3Zadf8nJpKfX2e - * h2rnhlzCN9M7djRDooZKDOPCsdBn51Au7HlZF3S3Opgo7D8XFM1a8t1Je4ke14oI - * nw6QKYsBblRziPnP2PZ0zvX24nOv7bbY8beynlJHGs00VWSFdoH2DS0aE1p6D+3n - * ptJuJ75dVfZFK4X7162APlNXevX8D6PEQpSiRw1rjjGGcnvQ4HdWk3BxDVDcCNJb - * Y1aGNRxsjTDvPi3R9Qx2M+W03QzEPx4SR3ZHVskeSJHaetM0TM/w/45Paq4GokXP - * ZeTnbEx1xmjkA7h+t4doLL4watx5F6yLsJzu8xB3lt/1EtmkYtLz1t7X4BetPAXz - * zS69X/VwhKfsOI3qXBWuL2oHPyhDmT1gcaUQwEPSV6ogHEEQEDXdiUS8heNK13KF - * TCQYFkETvV2BLxUhV1hypPzRQ6tUpJiAbD5KmoK2lD9slshG2QtvKQq0/bgkDY5J - * LhDHV2dtcZ3kDPkkZXpbcJQvoeH3d09C5sIsuTFo2zgNR6oETHUc5TzP6FY2YYRa - * QcK5HcmtsRRiXFm01ac+aMejJUIujjFt84SiKWT/73vC8AmY4tYcJBLjCg4XIxSH - * fdDFLL1YZENNO5ivlp8mdiHqcawx+36L7DrEZQ8RZt6cqST5t/+XTdM74s6k81GT - * pNsa82P2K2zmIUZ/DL2mKjW1vfRByw1NQFEBkN3vdyZxYfM/JyUzX4hbjXBEkh9Q - * QYrcwLKLjis2QzSvK04B3bvRzRb+4ocWiso8ZPAXAIxZFBWDpTMM2A== - * -----END RSA PRIVATE KEY----- - * - * -----BEGIN RSA PRIVATE KEY----- - * MIICXAIBAAKBgQClrFscN6LdmYktsnm4j9VIpecchBeNaZzGrG358h0fORna03Ie - * buxEzHCk3LoAMPagTz1UemFqzFfQCn+VKBg/mtmU8hvIJIh+/p0PPftXUwizIDPU - * PxdHFNHN6gjYDnVOr77M0uyvqXpJ38LZrLgkQJCmA1Yq0DAFQCxPq9l0iQIDAQAB - * AoGAbqcbg1E1mkR99uOJoNeQYKFOJyGiiXTMnXV1TseC4+PDfQBU7Dax35GcesBi - * CtapIpFKKS5D+ozY6b7ZT8ojxuQ/uHLPAvz0WDR3ds4iRF8tyu71Q1ZHcQsJa17y - * yO7UbkSSKn/Mp9Rb+/dKqftUGNXVFLqgHBOzN2s3We3bbbECQQDYBPKOg3hkaGHo - * OhpHKqtQ6EVkldihG/3i4WejRonelXN+HRh1KrB2HBx0M8D/qAzP1i3rNSlSHer4 - * 59YRTJnHAkEAxFX/sVYSn07BHv9Zhn6XXct/Cj43z/tKNbzlNbcxqQwQerw3IH51 - * 8UH2YOA+GD3lXbKp+MytoFLWv8zg4YT/LwJAfqan75Z1R6lLffRS49bIiq8jwE16 - * rTrUJ+kv8jKxMqc9B3vXkxpsS1M/+4E8bqgAmvpgAb8xcsvHsBd9ErdukQJBAKs2 - * j67W75BrPjBI34pQ1LEfp56IGWXOrq1kF8IbCjxv3+MYRT6Z6UJFkpRymNPNDjsC - * dgUYgITiGJHUGXuw3lMCQHEHqo9ZtXz92yFT+VhsNc29B8m/sqUJdtCcMd/jGpAF - * u6GHufjqIZBpQsk63wbwESAPZZ+kk1O1kS5GIRLX608= - * -----END RSA PRIVATE KEY----- - * - * Private-Key: (1024 bit) - * modulus: - * 00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f: - * d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2: - * 1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc: - * ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a: - * 7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe: - * 9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14: - * d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9: - * 7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0: - * 30:05:40:2c:4f:ab:d9:74:89 - * publicExponent: 65537 (0x10001) - * privateExponent: - * 6e:a7:1b:83:51:35:9a:44:7d:f6:e3:89:a0:d7:90: - * 60:a1:4e:27:21:a2:89:74:cc:9d:75:75:4e:c7:82: - * e3:e3:c3:7d:00:54:ec:36:b1:df:91:9c:7a:c0:62: - * 0a:d6:a9:22:91:4a:29:2e:43:fa:8c:d8:e9:be:d9: - * 4f:ca:23:c6:e4:3f:b8:72:cf:02:fc:f4:58:34:77: - * 76:ce:22:44:5f:2d:ca:ee:f5:43:56:47:71:0b:09: - * 6b:5e:f2:c8:ee:d4:6e:44:92:2a:7f:cc:a7:d4:5b: - * fb:f7:4a:a9:fb:54:18:d5:d5:14:ba:a0:1c:13:b3: - * 37:6b:37:59:ed:db:6d:b1 - * prime1: - * 00:d8:04:f2:8e:83:78:64:68:61:e8:3a:1a:47:2a: - * ab:50:e8:45:64:95:d8:a1:1b:fd:e2:e1:67:a3:46: - * 89:de:95:73:7e:1d:18:75:2a:b0:76:1c:1c:74:33: - * c0:ff:a8:0c:cf:d6:2d:eb:35:29:52:1d:ea:f8:e7: - * d6:11:4c:99:c7 - * prime2: - * 00:c4:55:ff:b1:56:12:9f:4e:c1:1e:ff:59:86:7e: - * 97:5d:cb:7f:0a:3e:37:cf:fb:4a:35:bc:e5:35:b7: - * 31:a9:0c:10:7a:bc:37:20:7e:75:f1:41:f6:60:e0: - * 3e:18:3d:e5:5d:b2:a9:f8:cc:ad:a0:52:d6:bf:cc: - * e0:e1:84:ff:2f - * exponent1: - * 7e:a6:a7:ef:96:75:47:a9:4b:7d:f4:52:e3:d6:c8: - * 8a:af:23:c0:4d:7a:ad:3a:d4:27:e9:2f:f2:32:b1: - * 32:a7:3d:07:7b:d7:93:1a:6c:4b:53:3f:fb:81:3c: - * 6e:a8:00:9a:fa:60:01:bf:31:72:cb:c7:b0:17:7d: - * 12:b7:6e:91 - * exponent2: - * 00:ab:36:8f:ae:d6:ef:90:6b:3e:30:48:df:8a:50: - * d4:b1:1f:a7:9e:88:19:65:ce:ae:ad:64:17:c2:1b: - * 0a:3c:6f:df:e3:18:45:3e:99:e9:42:45:92:94:72: - * 98:d3:cd:0e:3b:02:76:05:18:80:84:e2:18:91:d4: - * 19:7b:b0:de:53 - * coefficient: - * 71:07:aa:8f:59:b5:7c:fd:db:21:53:f9:58:6c:35: - * cd:bd:07:c9:bf:b2:a5:09:76:d0:9c:31:df:e3:1a: - * 90:05:bb:a1:87:b9:f8:ea:21:90:69:42:c9:3a:df: - * 06:f0:11:20:0f:65:9f:a4:93:53:b5:91:2e:46:21: - * 12:d7:eb:4f - * - * - * server certificate: - * Data: - * Version: 3 (0x2) - * Serial Number: 7 (0x7) - * Signature Algorithm: md5WithRSAEncryption - * Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org - * Validity - * Not Before: Dec 8 03:27:57 2008 GMT - * Not After : Aug 25 03:27:57 2028 GMT - * Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Server, CN=localhost - * Subject Public Key Info: - * Public Key Algorithm: rsaEncryption - * RSA Public Key: (1024 bit) - * Modulus (1024 bit): - * 00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f: - * d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2: - * 1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc: - * ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a: - * 7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe: - * 9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14: - * d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9: - * 7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0: - * 30:05:40:2c:4f:ab:d9:74:89 - * Exponent: 65537 (0x10001) - * X509v3 extensions: - * X509v3 Basic Constraints: - * CA:FALSE - * X509v3 Key Usage: - * Digital Signature, Non Repudiation, Key Encipherment - * X509v3 Subject Key Identifier: - * ED:6E:DB:F4:B5:56:C8:FB:1A:06:61:3F:0F:08:BB:A6:04:D8:16:54 - * X509v3 Authority Key Identifier: - * keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14 - * - * X509v3 Subject Alternative Name: critical - * IP Address:127.0.0.1 - * Signature Algorithm: md5WithRSAEncryption - * - * -----BEGIN CERTIFICATE----- - * MIICnzCCAgigAwIBAgIBBzANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET - * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK - * EwhTb21lLU9yZzAeFw0wODEyMDgwMzI3NTdaFw0yODA4MjUwMzI3NTdaMHIxCzAJ - * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp - * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD - * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3 - * ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6 - * YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS - * 7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjbjBsMAkGA1UdEwQCMAAw - * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV - * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDASBgNVHREBAf8ECDAGhwR/AAAB - * MA0GCSqGSIb3DQEBBAUAA4GBAFJjItCtCBZcjD69wdqfIbKmRFa6eJAjR6LcoDva - * cKC/sDOLelpspiZ66Zb0Xdv5qQ7QrfOXt3K8QqJKRMdZLF9WfUfy0gJDM32ub91h - * pu+TmcGPs+6RdrAQcuvU1ZDV9X8SMj7BtKaim4d5sqFw1npncKiA5xFn8vOYwdun - * nZif - * -----END CERTIFICATE----- - * - * - * TLS client certificate: - * client private key: - * ----BEGIN RSA PRIVATE KEY----- - * Proc-Type: 4,ENCRYPTED - * DEK-Info: DES-EDE3-CBC,FA2A435CD35A9390 - * - * Z+Y2uaETbsUWIyJUyVu1UV2G4rgFYJyACZT6Tp1KjRtxflSh2kXkJ9MpuXMXA0V4 - * Yy3fDzPqCL9NJmQAYRlAx/W/+j4F5EyMWDIx8fUxzONRZyoiwF7jLm+KscAfv6Pf - * q7ItWOdj3z7IYrwlB8YIGd3F2cDKT3S+lYRk7rKb/qT7itbuHnY4Ardh3yl+MZak - * jBp+ELUlRsUqSr1V0LoM+0rCCykarpyfhpxEcqsrl0v9Cyi5uhU50/oKv5zql3SH - * l2ImgDjp3batAs8+Bd4NF2aqi0a7Hy44JUHxRm4caZryU/i/D9N1MbuM6882HLat - * 5N0G+NaIUfywa8mjwq2D5aiit18HqKA6XeRRYeJ5Dvu9DCO4GeFSwcUFIBMI0L46 - * 7s114+oDodg57pMgITi+04vmUxvqlN9aiyd7f5Fgd7PeHGeOdbMz1NaJLJaPI9++ - * NakK8eK9iwT/Gdq0Uap5/CHW7vCT5PO+h3HY0STH0lWStXhdWnFO04zTdywsbSp+ - * DLpHeFT66shfeUlxR0PsCbG9vPRt/QmGLeYQZITppWo/ylSq4j+pRIuXvuWHdBRN - * rTZ8QF4Y7AxQUXVz1j1++s6ZMHTzaK2i9HrhmDs1MbJl+QwWre3Xpv3LvTVz3k5U - * wX8kuY1m3STt71QCaRWENq5sRaMImLxZbxc/ivFl9RAzUqo4NCxLod/QgA4iLqtO - * ztnlpzwlC/F8HbQ1oqYWwnZAPhzU/cULtstl+Yrws2c2atO323LbPXZqbASySgig - * sNpFXQMObdfP6LN23bY+1SvtK7V4NUTNhpdIc6INQAQ= - * -----END RSA PRIVATE KEY----- - * - * -----BEGIN RSA PRIVATE KEY----- - * MIICWwIBAAKBgQC78EA2rCZUTvSjWgAvaSFvuXo6k+yi9uGOx2PYLxIwmS6w8o/4 - * Jy0keCiE9wG/jUR53TvSVfPOPLJbIX3v/TNKsaP/xsibuQ98QTWX+ds6BWAFFa9Z - * F5KjEK0WHOQHU6+odqJWKpLT+SjgeM9eH0irXBnd4WdDunWN9YKsQ5JEGwIDAQAB - * AoGAEbdqNj0wN85hnWyEi/ObJU8UyKTdL9eaF72QGfcF/fLSxfd3vurihIeXOkGW - * tpn4lIxYcVGM9CognhqgJpl11jFTQzn1KqZ+NEJRKkCHA4hDabKJbSC9fXHvRwrf - * BsFpZqgiNxp3HseUTiwnaUVeyPgMt/jAj5nB5Sib+UyUxrECQQDnNQBiF2aifEg6 - * zbJOOC7he5CHAdkFxSxWVFVHL6EfXfqdLVkUohMbgZv+XxyIeU2biOExSg49Kds3 - * FOKgTau1AkEA0Bd1haj6QuCo8I0AXm2WO+MMTZMTvtHD/bGjKNM+fT4I8rKYnQRX - * 1acHdqS9Xx2rNJqZgkMmpESIdPR2fc4yjwJALFeM6EMmqvj8/VIf5UJ/Mz14fXwM - * PEARfckUxd9LnnFutCBTWlKvKXJVEZb6KO5ixPaegc57Jp3Vbh3yTN44lQJADD/1 - * SSMDaIB1MYP7a5Oj7m6VQNPRq8AJe5vDcRnOae0G9dKRrVyeFxO4GsHj6/+BHp2j - * P8nYMn9eURQ7DXjf/QJAAQzMlWnKGSO8pyTDtnQx3hRMoUkOEhmNq4bQhLkYqtnY - * FcqpUQ2qMjW+NiNWk5HnTrMS3L9EdJobMUzaNZLy4w== - * -----END RSA PRIVATE KEY----- - * - * Private-Key: (1024 bit) - * modulus: - * 00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69: - * 21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f: - * 12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7: - * 01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21: - * 7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41: - * 35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10: - * ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9: - * 28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba: - * 75:8d:f5:82:ac:43:92:44:1b - * publicExponent: 65537 (0x10001) - * privateExponent: - * 11:b7:6a:36:3d:30:37:ce:61:9d:6c:84:8b:f3:9b: - * 25:4f:14:c8:a4:dd:2f:d7:9a:17:bd:90:19:f7:05: - * fd:f2:d2:c5:f7:77:be:ea:e2:84:87:97:3a:41:96: - * b6:99:f8:94:8c:58:71:51:8c:f4:2a:20:9e:1a:a0: - * 26:99:75:d6:31:53:43:39:f5:2a:a6:7e:34:42:51: - * 2a:40:87:03:88:43:69:b2:89:6d:20:bd:7d:71:ef: - * 47:0a:df:06:c1:69:66:a8:22:37:1a:77:1e:c7:94: - * 4e:2c:27:69:45:5e:c8:f8:0c:b7:f8:c0:8f:99:c1: - * e5:28:9b:f9:4c:94:c6:b1 - * prime1: - * 00:e7:35:00:62:17:66:a2:7c:48:3a:cd:b2:4e:38: - * 2e:e1:7b:90:87:01:d9:05:c5:2c:56:54:55:47:2f: - * a1:1f:5d:fa:9d:2d:59:14:a2:13:1b:81:9b:fe:5f: - * 1c:88:79:4d:9b:88:e1:31:4a:0e:3d:29:db:37:14: - * e2:a0:4d:ab:b5 - * prime2: - * 00:d0:17:75:85:a8:fa:42:e0:a8:f0:8d:00:5e:6d: - * 96:3b:e3:0c:4d:93:13:be:d1:c3:fd:b1:a3:28:d3: - * 3e:7d:3e:08:f2:b2:98:9d:04:57:d5:a7:07:76:a4: - * bd:5f:1d:ab:34:9a:99:82:43:26:a4:44:88:74:f4: - * 76:7d:ce:32:8f - * exponent1: - * 2c:57:8c:e8:43:26:aa:f8:fc:fd:52:1f:e5:42:7f: - * 33:3d:78:7d:7c:0c:3c:40:11:7d:c9:14:c5:df:4b: - * 9e:71:6e:b4:20:53:5a:52:af:29:72:55:11:96:fa: - * 28:ee:62:c4:f6:9e:81:ce:7b:26:9d:d5:6e:1d:f2: - * 4c:de:38:95 - * exponent2: - * 0c:3f:f5:49:23:03:68:80:75:31:83:fb:6b:93:a3: - * ee:6e:95:40:d3:d1:ab:c0:09:7b:9b:c3:71:19:ce: - * 69:ed:06:f5:d2:91:ad:5c:9e:17:13:b8:1a:c1:e3: - * eb:ff:81:1e:9d:a3:3f:c9:d8:32:7f:5e:51:14:3b: - * 0d:78:df:fd - * coefficient: - * 01:0c:cc:95:69:ca:19:23:bc:a7:24:c3:b6:74:31: - * de:14:4c:a1:49:0e:12:19:8d:ab:86:d0:84:b9:18: - * aa:d9:d8:15:ca:a9:51:0d:aa:32:35:be:36:23:56: - * 93:91:e7:4e:b3:12:dc:bf:44:74:9a:1b:31:4c:da: - * 35:92:f2:e3 - * - * client certificate: - * Data: - * Version: 3 (0x2) - * Serial Number: 6 (0x6) - * Signature Algorithm: md5WithRSAEncryption - * Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org - * Validity - * Not Before: Dec 8 03:27:34 2008 GMT - * Not After : Aug 25 03:27:34 2028 GMT - * Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Client, CN=localhost - * Subject Public Key Info: - * Public Key Algorithm: rsaEncryption - * RSA Public Key: (1024 bit) - * Modulus (1024 bit): - * 00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69: - * 21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f: - * 12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7: - * 01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21: - * 7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41: - * 35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10: - * ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9: - * 28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba: - * 75:8d:f5:82:ac:43:92:44:1b - * Exponent: 65537 (0x10001) - * X509v3 extensions: - * X509v3 Basic Constraints: - * CA:FALSE - * X509v3 Key Usage: - * Digital Signature, Non Repudiation, Key Encipherment - * X509v3 Subject Key Identifier: - * CD:BB:C8:85:AA:91:BD:FD:1D:BE:CD:67:7C:FF:B3:E9:4C:A8:22:E6 - * X509v3 Authority Key Identifier: - * keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14 - * - * X509v3 Subject Alternative Name: critical - * IP Address:127.0.0.1 - * Signature Algorithm: md5WithRSAEncryption - * - * -----BEGIN CERTIFICATE----- - * MIICnzCCAgigAwIBAgIBBjANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET - * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK - * EwhTb21lLU9yZzAeFw0wODEyMDgwMzI3MzRaFw0yODA4MjUwMzI3MzRaMHIxCzAJ - * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp - * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD - * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas - * JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV - * 8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq - * ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjbjBsMAkGA1UdEwQCMAAw - * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV - * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDASBgNVHREBAf8ECDAGhwR/AAAB - * MA0GCSqGSIb3DQEBBAUAA4GBACjj9PS+W6XOF7toFMwMOv/AemZeBOpcEF1Ei1Hx - * HjvB6EOHkMY8tFm5OPzkiWiK3+s3awpSW0jWdzMYwrQJ3/klMsPDpI7PEuirqwHP - * i5Wyl/vk7jmfWVcBO9MVhPUo4BYl4vS9aj6JA5QbkbkB95LOgT/BowY0WmHeVsXC - * I9aw - * -----END CERTIFICATE----- - * - * - * - * Trusted CA certificate: - * Certificate: - * Data: - * Version: 3 (0x2) - * Serial Number: 0 (0x0) - * Signature Algorithm: md5WithRSAEncryption - * Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org - * Validity - * Not Before: Dec 8 02:43:36 2008 GMT - * Not After : Aug 25 02:43:36 2028 GMT - * Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org - * Subject Public Key Info: - * Public Key Algorithm: rsaEncryption - * RSA Public Key: (1024 bit) - * Modulus (1024 bit): - * 00:cb:c4:38:20:07:be:88:a7:93:b0:a1:43:51:2d: - * d7:8e:85:af:54:dd:ad:a2:7b:23:5b:cf:99:13:53: - * 99:45:7d:ee:6d:ba:2d:bf:e3:ad:6e:3d:9f:1a:f9: - * 03:97:e0:17:55:ae:11:26:57:de:01:29:8e:05:3f: - * 21:f7:e7:36:e8:2e:37:d7:48:ac:53:d6:60:0e:c7: - * 50:6d:f6:c5:85:f7:8b:a6:c5:91:35:72:3c:94:ee: - * f1:17:f0:71:e3:ec:1b:ce:ca:4e:40:42:b0:6d:ee: - * 6a:0e:d6:e5:ad:3c:0f:c9:ba:82:4f:78:f8:89:97: - * 89:2a:95:12:4c:d8:09:2a:e9 - * Exponent: 65537 (0x10001) - * X509v3 extensions: - * X509v3 Subject Key Identifier: - * FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14 - * X509v3 Authority Key Identifier: - * keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14 - * DirName:/C=US/ST=Some-State/L=Some-City/O=Some-Org - * serial:00 - * - * X509v3 Basic Constraints: - * CA:TRUE - * Signature Algorithm: md5WithRSAEncryption - * - * -----BEGIN CERTIFICATE----- - * MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET - * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK - * EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ - * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp - * dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB - * gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX - * 4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj - * 7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G - * A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ - * hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt - * U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw - * DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA - * ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ - * LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P - * 6Mvf0r1PNTY2hwTJLJmKtg== - * -----END CERTIFICATE--- - */ +import jdk.test.lib.security.CertificateBuilder; +import jdk.test.lib.security.CertificateBuilder.KeyUsage; +import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNames; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.SerialNumber; +import sun.security.x509.X500Name; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManagerFactory; public class IPIdentities { - static Map cookies; - ServerSocket ss; /* * ============================================================= @@ -421,208 +83,14 @@ public class IPIdentities { */ static boolean separateServerThread = true; - /* - * Where do we find the keystores? - */ - static String trusedCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" + - "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" + - "EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ\n" + - "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" + - "dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" + - "gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX\n" + - "4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj\n" + - "7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G\n" + - "A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ\n" + - "hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt\n" + - "U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw\n" + - "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA\n" + - "ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ\n" + - "LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P\n" + - "6Mvf0r1PNTY2hwTJLJmKtg==\n" + - "-----END CERTIFICATE-----"; - - static String serverCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICnzCCAgigAwIBAgIBBzANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" + - "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" + - "EwhTb21lLU9yZzAeFw0wODEyMDgwMzI3NTdaFw0yODA4MjUwMzI3NTdaMHIxCzAJ\n" + - "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" + - "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD\n" + - "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3\n" + - "ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6\n" + - "YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS\n" + - "7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjbjBsMAkGA1UdEwQCMAAw\n" + - "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV\n" + - "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDASBgNVHREBAf8ECDAGhwR/AAAB\n" + - "MA0GCSqGSIb3DQEBBAUAA4GBAFJjItCtCBZcjD69wdqfIbKmRFa6eJAjR6LcoDva\n" + - "cKC/sDOLelpspiZ66Zb0Xdv5qQ7QrfOXt3K8QqJKRMdZLF9WfUfy0gJDM32ub91h\n" + - "pu+TmcGPs+6RdrAQcuvU1ZDV9X8SMj7BtKaim4d5sqFw1npncKiA5xFn8vOYwdun\n" + - "nZif\n" + - "-----END CERTIFICATE-----"; - - static String clientCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICnzCCAgigAwIBAgIBBjANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" + - "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" + - "EwhTb21lLU9yZzAeFw0wODEyMDgwMzI3MzRaFw0yODA4MjUwMzI3MzRaMHIxCzAJ\n" + - "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" + - "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD\n" + - "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas\n" + - "JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV\n" + - "8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq\n" + - "ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjbjBsMAkGA1UdEwQCMAAw\n" + - "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV\n" + - "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDASBgNVHREBAf8ECDAGhwR/AAAB\n" + - "MA0GCSqGSIb3DQEBBAUAA4GBACjj9PS+W6XOF7toFMwMOv/AemZeBOpcEF1Ei1Hx\n" + - "HjvB6EOHkMY8tFm5OPzkiWiK3+s3awpSW0jWdzMYwrQJ3/klMsPDpI7PEuirqwHP\n" + - "i5Wyl/vk7jmfWVcBO9MVhPUo4BYl4vS9aj6JA5QbkbkB95LOgT/BowY0WmHeVsXC\n" + - "I9aw\n" + - "-----END CERTIFICATE-----"; - - - static byte serverPrivateExponent[] = { - (byte)0x6e, (byte)0xa7, (byte)0x1b, (byte)0x83, - (byte)0x51, (byte)0x35, (byte)0x9a, (byte)0x44, - (byte)0x7d, (byte)0xf6, (byte)0xe3, (byte)0x89, - (byte)0xa0, (byte)0xd7, (byte)0x90, (byte)0x60, - (byte)0xa1, (byte)0x4e, (byte)0x27, (byte)0x21, - (byte)0xa2, (byte)0x89, (byte)0x74, (byte)0xcc, - (byte)0x9d, (byte)0x75, (byte)0x75, (byte)0x4e, - (byte)0xc7, (byte)0x82, (byte)0xe3, (byte)0xe3, - (byte)0xc3, (byte)0x7d, (byte)0x00, (byte)0x54, - (byte)0xec, (byte)0x36, (byte)0xb1, (byte)0xdf, - (byte)0x91, (byte)0x9c, (byte)0x7a, (byte)0xc0, - (byte)0x62, (byte)0x0a, (byte)0xd6, (byte)0xa9, - (byte)0x22, (byte)0x91, (byte)0x4a, (byte)0x29, - (byte)0x2e, (byte)0x43, (byte)0xfa, (byte)0x8c, - (byte)0xd8, (byte)0xe9, (byte)0xbe, (byte)0xd9, - (byte)0x4f, (byte)0xca, (byte)0x23, (byte)0xc6, - (byte)0xe4, (byte)0x3f, (byte)0xb8, (byte)0x72, - (byte)0xcf, (byte)0x02, (byte)0xfc, (byte)0xf4, - (byte)0x58, (byte)0x34, (byte)0x77, (byte)0x76, - (byte)0xce, (byte)0x22, (byte)0x44, (byte)0x5f, - (byte)0x2d, (byte)0xca, (byte)0xee, (byte)0xf5, - (byte)0x43, (byte)0x56, (byte)0x47, (byte)0x71, - (byte)0x0b, (byte)0x09, (byte)0x6b, (byte)0x5e, - (byte)0xf2, (byte)0xc8, (byte)0xee, (byte)0xd4, - (byte)0x6e, (byte)0x44, (byte)0x92, (byte)0x2a, - (byte)0x7f, (byte)0xcc, (byte)0xa7, (byte)0xd4, - (byte)0x5b, (byte)0xfb, (byte)0xf7, (byte)0x4a, - (byte)0xa9, (byte)0xfb, (byte)0x54, (byte)0x18, - (byte)0xd5, (byte)0xd5, (byte)0x14, (byte)0xba, - (byte)0xa0, (byte)0x1c, (byte)0x13, (byte)0xb3, - (byte)0x37, (byte)0x6b, (byte)0x37, (byte)0x59, - (byte)0xed, (byte)0xdb, (byte)0x6d, (byte)0xb1 - }; - - static byte serverModulus[] = { - (byte)0x00, - (byte)0xa5, (byte)0xac, (byte)0x5b, (byte)0x1c, - (byte)0x37, (byte)0xa2, (byte)0xdd, (byte)0x99, - (byte)0x89, (byte)0x2d, (byte)0xb2, (byte)0x79, - (byte)0xb8, (byte)0x8f, (byte)0xd5, (byte)0x48, - (byte)0xa5, (byte)0xe7, (byte)0x1c, (byte)0x84, - (byte)0x17, (byte)0x8d, (byte)0x69, (byte)0x9c, - (byte)0xc6, (byte)0xac, (byte)0x6d, (byte)0xf9, - (byte)0xf2, (byte)0x1d, (byte)0x1f, (byte)0x39, - (byte)0x19, (byte)0xda, (byte)0xd3, (byte)0x72, - (byte)0x1e, (byte)0x6e, (byte)0xec, (byte)0x44, - (byte)0xcc, (byte)0x70, (byte)0xa4, (byte)0xdc, - (byte)0xba, (byte)0x00, (byte)0x30, (byte)0xf6, - (byte)0xa0, (byte)0x4f, (byte)0x3d, (byte)0x54, - (byte)0x7a, (byte)0x61, (byte)0x6a, (byte)0xcc, - (byte)0x57, (byte)0xd0, (byte)0x0a, (byte)0x7f, - (byte)0x95, (byte)0x28, (byte)0x18, (byte)0x3f, - (byte)0x9a, (byte)0xd9, (byte)0x94, (byte)0xf2, - (byte)0x1b, (byte)0xc8, (byte)0x24, (byte)0x88, - (byte)0x7e, (byte)0xfe, (byte)0x9d, (byte)0x0f, - (byte)0x3d, (byte)0xfb, (byte)0x57, (byte)0x53, - (byte)0x08, (byte)0xb3, (byte)0x20, (byte)0x33, - (byte)0xd4, (byte)0x3f, (byte)0x17, (byte)0x47, - (byte)0x14, (byte)0xd1, (byte)0xcd, (byte)0xea, - (byte)0x08, (byte)0xd8, (byte)0x0e, (byte)0x75, - (byte)0x4e, (byte)0xaf, (byte)0xbe, (byte)0xcc, - (byte)0xd2, (byte)0xec, (byte)0xaf, (byte)0xa9, - (byte)0x7a, (byte)0x49, (byte)0xdf, (byte)0xc2, - (byte)0xd9, (byte)0xac, (byte)0xb8, (byte)0x24, - (byte)0x40, (byte)0x90, (byte)0xa6, (byte)0x03, - (byte)0x56, (byte)0x2a, (byte)0xd0, (byte)0x30, - (byte)0x05, (byte)0x40, (byte)0x2c, (byte)0x4f, - (byte)0xab, (byte)0xd9, (byte)0x74, (byte)0x89 - }; - - static byte clientPrivateExponent[] = { - (byte)0x11, (byte)0xb7, (byte)0x6a, (byte)0x36, - (byte)0x3d, (byte)0x30, (byte)0x37, (byte)0xce, - (byte)0x61, (byte)0x9d, (byte)0x6c, (byte)0x84, - (byte)0x8b, (byte)0xf3, (byte)0x9b, (byte)0x25, - (byte)0x4f, (byte)0x14, (byte)0xc8, (byte)0xa4, - (byte)0xdd, (byte)0x2f, (byte)0xd7, (byte)0x9a, - (byte)0x17, (byte)0xbd, (byte)0x90, (byte)0x19, - (byte)0xf7, (byte)0x05, (byte)0xfd, (byte)0xf2, - (byte)0xd2, (byte)0xc5, (byte)0xf7, (byte)0x77, - (byte)0xbe, (byte)0xea, (byte)0xe2, (byte)0x84, - (byte)0x87, (byte)0x97, (byte)0x3a, (byte)0x41, - (byte)0x96, (byte)0xb6, (byte)0x99, (byte)0xf8, - (byte)0x94, (byte)0x8c, (byte)0x58, (byte)0x71, - (byte)0x51, (byte)0x8c, (byte)0xf4, (byte)0x2a, - (byte)0x20, (byte)0x9e, (byte)0x1a, (byte)0xa0, - (byte)0x26, (byte)0x99, (byte)0x75, (byte)0xd6, - (byte)0x31, (byte)0x53, (byte)0x43, (byte)0x39, - (byte)0xf5, (byte)0x2a, (byte)0xa6, (byte)0x7e, - (byte)0x34, (byte)0x42, (byte)0x51, (byte)0x2a, - (byte)0x40, (byte)0x87, (byte)0x03, (byte)0x88, - (byte)0x43, (byte)0x69, (byte)0xb2, (byte)0x89, - (byte)0x6d, (byte)0x20, (byte)0xbd, (byte)0x7d, - (byte)0x71, (byte)0xef, (byte)0x47, (byte)0x0a, - (byte)0xdf, (byte)0x06, (byte)0xc1, (byte)0x69, - (byte)0x66, (byte)0xa8, (byte)0x22, (byte)0x37, - (byte)0x1a, (byte)0x77, (byte)0x1e, (byte)0xc7, - (byte)0x94, (byte)0x4e, (byte)0x2c, (byte)0x27, - (byte)0x69, (byte)0x45, (byte)0x5e, (byte)0xc8, - (byte)0xf8, (byte)0x0c, (byte)0xb7, (byte)0xf8, - (byte)0xc0, (byte)0x8f, (byte)0x99, (byte)0xc1, - (byte)0xe5, (byte)0x28, (byte)0x9b, (byte)0xf9, - (byte)0x4c, (byte)0x94, (byte)0xc6, (byte)0xb1 - }; - - static byte clientModulus[] = { - (byte)0x00, - (byte)0xbb, (byte)0xf0, (byte)0x40, (byte)0x36, - (byte)0xac, (byte)0x26, (byte)0x54, (byte)0x4e, - (byte)0xf4, (byte)0xa3, (byte)0x5a, (byte)0x00, - (byte)0x2f, (byte)0x69, (byte)0x21, (byte)0x6f, - (byte)0xb9, (byte)0x7a, (byte)0x3a, (byte)0x93, - (byte)0xec, (byte)0xa2, (byte)0xf6, (byte)0xe1, - (byte)0x8e, (byte)0xc7, (byte)0x63, (byte)0xd8, - (byte)0x2f, (byte)0x12, (byte)0x30, (byte)0x99, - (byte)0x2e, (byte)0xb0, (byte)0xf2, (byte)0x8f, - (byte)0xf8, (byte)0x27, (byte)0x2d, (byte)0x24, - (byte)0x78, (byte)0x28, (byte)0x84, (byte)0xf7, - (byte)0x01, (byte)0xbf, (byte)0x8d, (byte)0x44, - (byte)0x79, (byte)0xdd, (byte)0x3b, (byte)0xd2, - (byte)0x55, (byte)0xf3, (byte)0xce, (byte)0x3c, - (byte)0xb2, (byte)0x5b, (byte)0x21, (byte)0x7d, - (byte)0xef, (byte)0xfd, (byte)0x33, (byte)0x4a, - (byte)0xb1, (byte)0xa3, (byte)0xff, (byte)0xc6, - (byte)0xc8, (byte)0x9b, (byte)0xb9, (byte)0x0f, - (byte)0x7c, (byte)0x41, (byte)0x35, (byte)0x97, - (byte)0xf9, (byte)0xdb, (byte)0x3a, (byte)0x05, - (byte)0x60, (byte)0x05, (byte)0x15, (byte)0xaf, - (byte)0x59, (byte)0x17, (byte)0x92, (byte)0xa3, - (byte)0x10, (byte)0xad, (byte)0x16, (byte)0x1c, - (byte)0xe4, (byte)0x07, (byte)0x53, (byte)0xaf, - (byte)0xa8, (byte)0x76, (byte)0xa2, (byte)0x56, - (byte)0x2a, (byte)0x92, (byte)0xd3, (byte)0xf9, - (byte)0x28, (byte)0xe0, (byte)0x78, (byte)0xcf, - (byte)0x5e, (byte)0x1f, (byte)0x48, (byte)0xab, - (byte)0x5c, (byte)0x19, (byte)0xdd, (byte)0xe1, - (byte)0x67, (byte)0x43, (byte)0xba, (byte)0x75, - (byte)0x8d, (byte)0xf5, (byte)0x82, (byte)0xac, - (byte)0x43, (byte)0x92, (byte)0x44, (byte)0x1b - }; + static X509Certificate trustedCert; + + static X509Certificate serverCert; + + static X509Certificate clientCert; + + static KeyPair serverKeys; + static KeyPair clientKeys; static char passphrase[] = "passphrase".toCharArray(); @@ -639,7 +107,7 @@ public class IPIdentities { /* * Turn on SSL debugging? */ - static boolean debug = false; + static boolean debug = Boolean.getBoolean("test.debug"); private SSLServerSocket sslServerSocket = null; @@ -650,8 +118,8 @@ public class IPIdentities { * to avoid infinite hangs. */ void doServerSide() throws Exception { - SSLContext context = getSSLContext(trusedCertStr, serverCertStr, - serverModulus, serverPrivateExponent, passphrase); + SSLContext context = getSSLContext(trustedCert, serverCert, + serverKeys, passphrase); SSLServerSocketFactory sslssf = context.getServerSocketFactory(); // doClientSide() connects to the loopback address @@ -706,8 +174,8 @@ void doServerSide() throws Exception { void doClientSide() throws Exception { SSLContext reservedSSLContext = SSLContext.getDefault(); try { - SSLContext context = getSSLContext(trusedCertStr, clientCertStr, - clientModulus, clientPrivateExponent, passphrase); + SSLContext context = getSSLContext(trustedCert, clientCert, + clientKeys, passphrase); SSLContext.setDefault(context); /* @@ -755,6 +223,65 @@ void doClientSide() throws Exception { volatile Exception serverException = null; volatile Exception clientException = null; + private static X509Certificate createTrustedCert(KeyPair caKeys) throws Exception { + SecureRandom random = new SecureRandom(); + + KeyIdentifier kid = new KeyIdentifier(caKeys.getPublic()); + GeneralNames gns = new GeneralNames(); + GeneralName name = new GeneralName(new X500Name( + "O=Some-Org, L=Some-City, ST=Some-State, C=US")); + gns.add(name); + BigInteger serialNumber = BigInteger.valueOf(random.nextLong(1000000)+1); + return CertificateBuilder.newCertificateBuilder( + "O=Some-Org, L=Some-City, ST=Some-State, C=US", + caKeys.getPublic(), caKeys.getPublic()) + .setSerialNumber(serialNumber) + .addExtension(new AuthorityKeyIdentifierExtension(kid, gns, + new SerialNumber(serialNumber))) + .addBasicConstraintsExt(true, true, -1) + .setOneHourValidity() + .build(null, caKeys.getPrivate(), "MD5WithRSA"); + } + + private static void setupCertificates() throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + KeyPair caKeys = kpg.generateKeyPair(); + serverKeys = kpg.generateKeyPair(); + clientKeys = kpg.generateKeyPair(); + + trustedCert = createTrustedCert(caKeys); + if (debug) { + System.out.println("----------- Trusted Cert -----------"); + CertificateBuilder.printCertificate(trustedCert, System.out); + } + + serverCert = CertificateBuilder.newCertificateBuilder( + "O=Some-Org, L=Some-City, ST=Some-State, C=US", + serverKeys.getPublic(), caKeys.getPublic(), + KeyUsage.DIGITAL_SIGNATURE, KeyUsage.NONREPUDIATION, KeyUsage.KEY_ENCIPHERMENT) + .addBasicConstraintsExt(false, false, -1) + .addExtension(CertificateBuilder.createIPSubjectAltNameExt(true, "127.0.0.1")) + .setOneHourValidity() + .build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); + if (debug) { + System.out.println("----------- Server Cert -----------"); + CertificateBuilder.printCertificate(serverCert, System.out); + } + + clientCert = CertificateBuilder.newCertificateBuilder( + "CN=localhost, OU=SSL-Client, O=Some-Org, L=Some-City, ST=Some-State, C=US", + clientKeys.getPublic(), caKeys.getPublic(), + KeyUsage.DIGITAL_SIGNATURE, KeyUsage.NONREPUDIATION, KeyUsage.KEY_ENCIPHERMENT) + .addExtension(CertificateBuilder.createIPSubjectAltNameExt(true, "127.0.0.1")) + .addBasicConstraintsExt(false, false, -1) + .setOneHourValidity() + .build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); + if (debug) { + System.out.println("----------- Client Cert -----------"); + CertificateBuilder.printCertificate(clientCert, System.out); + } + } + public static void main(String args[]) throws Exception { // MD5 is used in this test case, don't disable MD5 algorithm. Security.setProperty("jdk.certpath.disabledAlgorithms", @@ -762,8 +289,11 @@ public static void main(String args[]) throws Exception { Security.setProperty("jdk.tls.disabledAlgorithms", "SSLv3, RC4, DH keySize < 768"); - if (debug) + if (debug) { System.setProperty("javax.net.debug", "all"); + } + + setupCertificates(); /* * Start the tests. @@ -855,45 +385,23 @@ public void run() { } // get the ssl context - private static SSLContext getSSLContext(String trusedCertStr, - String keyCertStr, byte[] modulus, - byte[] privateExponent, char[] passphrase) throws Exception { - - // generate certificate from cert string - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - - ByteArrayInputStream is = - new ByteArrayInputStream(trusedCertStr.getBytes()); - Certificate trusedCert = cf.generateCertificate(is); - is.close(); + private static SSLContext getSSLContext(X509Certificate trustedCert, + X509Certificate keyCert, KeyPair key, char[] passphrase) throws Exception { // create a key store - KeyStore ks = KeyStore.getInstance("JKS"); + KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(null, null); // import the trused cert - ks.setCertificateEntry("RSA Export Signer", trusedCert); - - if (keyCertStr != null) { - // generate the private key. - RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec( - new BigInteger(modulus), - new BigInteger(privateExponent)); - KeyFactory kf = KeyFactory.getInstance("RSA"); - RSAPrivateKey priKey = - (RSAPrivateKey)kf.generatePrivate(priKeySpec); - - // generate certificate chain - is = new ByteArrayInputStream(keyCertStr.getBytes()); - Certificate keyCert = cf.generateCertificate(is); - is.close(); + ks.setCertificateEntry("RSA Export Signer", trustedCert); + if (keyCert != null) { Certificate[] chain = new Certificate[2]; chain[0] = keyCert; - chain[1] = trusedCert; + chain[1] = trustedCert; // import the key entry. - ks.setKeyEntry("Whatever", priKey, passphrase, chain); + ks.setKeyEntry("Whatever", key.getPrivate(), passphrase, chain); } // create SSL context @@ -902,7 +410,7 @@ private static SSLContext getSSLContext(String trusedCertStr, SSLContext ctx = SSLContext.getInstance("TLSv1.2"); - if (keyCertStr != null) { + if (keyCert != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TEST.properties b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TEST.properties new file mode 100644 index 00000000000..e1ed216f21d --- /dev/null +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TEST.properties @@ -0,0 +1,3 @@ +modules = \ + java.base/sun.security.util \ + java.base/sun.security.x509 diff --git a/test/jdk/sun/security/jgss/GssContextCleanup.java b/test/jdk/sun/security/jgss/GssContextCleanup.java index 00d84e8a70e..1e992df97d5 100644 --- a/test/jdk/sun/security/jgss/GssContextCleanup.java +++ b/test/jdk/sun/security/jgss/GssContextCleanup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,4 +59,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/sun/security/jgss/GssNameCleanup.java b/test/jdk/sun/security/jgss/GssNameCleanup.java index be68c46087d..ef19479b6a0 100644 --- a/test/jdk/sun/security/jgss/GssNameCleanup.java +++ b/test/jdk/sun/security/jgss/GssNameCleanup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,4 +66,3 @@ public static void main(String[] args) throws Exception { } } } - diff --git a/test/jdk/sun/security/krb5/Krb5NameEquals.java b/test/jdk/sun/security/krb5/Krb5NameEquals.java index 0851423a7fd..421c290453c 100644 --- a/test/jdk/sun/security/krb5/Krb5NameEquals.java +++ b/test/jdk/sun/security/krb5/Krb5NameEquals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * 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,57 +22,65 @@ */ /* + * @test * @bug 4634392 - * @summary JDK code doesn't respect contract for equals and hashCode + * @summary Ensure the GSSName has the correct impl which respects + * the contract for equals and hashCode across different configurations. + * @library /test/lib * @author Andrew Fan + * + * @run main/othervm -Djava.security.krb5.realm=R -Djava.security.krb5.kdc=127.0.0.1 Krb5NameEquals + * @run main/othervm -Dsun.security.jgss.native=true Krb5NameEquals */ -import org.ietf.jgss.*; +import jtreg.SkippedException; +import org.ietf.jgss.GSSManager; +import org.ietf.jgss.GSSName; +import org.ietf.jgss.Oid; public class Krb5NameEquals { - private static String NAME_STR1 = "service@localhost"; - private static String NAME_STR2 = "service2@localhost"; + private static final String NAME_STR1 = "service@localhost"; + private static final String NAME_STR2 = "service2@localhost"; private static final Oid MECH; static { - Oid temp = null; try { - temp = new Oid("1.2.840.113554.1.2.2"); // KRB5 + MECH = new Oid("1.2.840.113554.1.2.2"); // KRB5 } catch (Exception e) { // should never happen + throw new RuntimeException("Exception initialising Oid", e); } - MECH = temp; } public static void main(String[] argv) throws Exception { - GSSManager mgr = GSSManager.getInstance(); + final GSSManager mgr = GSSManager.getInstance(); + + // Checking if native GSS is installed, throwing skip exception if it's not. + if (Boolean.getBoolean("sun.security.jgss.native")) { + final var mechs = mgr.getMechs(); + if (mechs == null || mechs.length == 0) { + throw new SkippedException("NativeGSS not supported"); + } + } - boolean result = true; // Create GSSName and check their equals(), hashCode() impl - GSSName name1 = mgr.createName(NAME_STR1, - GSSName.NT_HOSTBASED_SERVICE, MECH); - GSSName name2 = mgr.createName(NAME_STR2, - GSSName.NT_HOSTBASED_SERVICE, MECH); - GSSName name3 = mgr.createName(NAME_STR1, - GSSName.NT_HOSTBASED_SERVICE, MECH); + final GSSName name1 = mgr.createName(NAME_STR1, + GSSName.NT_HOSTBASED_SERVICE, MECH); + final GSSName name2 = mgr.createName(NAME_STR2, + GSSName.NT_HOSTBASED_SERVICE, MECH); + final GSSName name3 = mgr.createName(NAME_STR1, + GSSName.NT_HOSTBASED_SERVICE, MECH); - if (!name1.equals(name1) || !name1.equals(name3) || - !name1.equals((Object) name1) || - !name1.equals((Object) name3)) { - System.out.println("Error: should be the same name"); - result = false; + if (!name1.equals(name3) || !name1.equals((Object) name3)) { + throw new RuntimeException("Error: should be the same name"); } else if (name1.hashCode() != name3.hashCode()) { - System.out.println("Error: should have same hash"); - result = false; + throw new RuntimeException("Error: should have same hash"); } if (name1.equals(name2) || name1.equals((Object) name2)) { - System.out.println("Error: should be different names"); - result = false; + throw new RuntimeException("Error: should be different names"); } - if (result) { - System.out.println("Done"); - } else System.exit(1); + System.out.println("Done"); } } diff --git a/test/jdk/sun/security/krb5/MicroTime.java b/test/jdk/sun/security/krb5/MicroTime.java index 8b6b9232415..84a88cedf83 100644 --- a/test/jdk/sun/security/krb5/MicroTime.java +++ b/test/jdk/sun/security/krb5/MicroTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * 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,9 +44,10 @@ public static void main(String[] args) throws Exception { count++; } } - // We believe a nice KerberosTime can at least tell the - // difference of 100 musec. - if (count < 10000) { + // Before JDK-6882687, KerberosTime was measured in milliseconds. + // Now it's in microseconds. We should be able to record more than + // 1000 distinct KerberosTime values within one second. + if (count < 1001) { throw new Exception("What? only " + (1000000/count) + " musec precision?"); } diff --git a/test/jdk/sun/security/krb5/auto/SaslBasic.java b/test/jdk/sun/security/krb5/auto/SaslBasic.java index 0aebdefbe04..89eb22383f2 100644 --- a/test/jdk/sun/security/krb5/auto/SaslBasic.java +++ b/test/jdk/sun/security/krb5/auto/SaslBasic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * 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 @@ * @run main/othervm -Djdk.net.hosts.file=TestHosts SaslBasic unbound auth-conf * @run main/othervm -Djdk.net.hosts.file=TestHosts SaslBasic bound auth */ -import java.io.IOException; +import static jdk.test.lib.Asserts.assertEquals; + import java.util.Arrays; import java.util.HashMap; import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.sasl.*; // The basic krb5 test skeleton you can copy from @@ -61,15 +60,12 @@ public static void main(String[] args) throws Exception { srvprops.put(Sasl.QOP, "auth,auth-int,auth-conf"); SaslServer ss = Sasl.createSaslServer("GSSAPI", "server", bound? name: null, srvprops, - new CallbackHandler() { - public void handle(Callback[] callbacks) - throws IOException, UnsupportedCallbackException { - for (Callback cb : callbacks) { - if (cb instanceof RealmCallback) { - ((RealmCallback) cb).setText(OneKDC.REALM); - } else if (cb instanceof AuthorizeCallback) { - ((AuthorizeCallback) cb).setAuthorized(true); - } + callbacks -> { + for (Callback cb : callbacks) { + if (cb instanceof RealmCallback) { + ((RealmCallback) cb).setText(OneKDC.REALM); + } else if (cb instanceof AuthorizeCallback) { + ((AuthorizeCallback) cb).setAuthorized(true); } } }); @@ -89,28 +85,85 @@ public void handle(Callback[] callbacks) String boundName = (String)ss.getNegotiatedProperty( Sasl.BOUND_SERVER_NAME); if (!boundName.equals(name)) { - throw new Exception("Wrong bound server name"); + throw new RuntimeException("Wrong bound server name"); } } Object key = ss.getNegotiatedProperty( "com.sun.security.jgss.inquiretype.krb5_get_session_key"); if (key == null) { - throw new Exception("Extended negotiated property not read"); + throw new RuntimeException("Extended negotiated property not read"); } if (args[1].equals("auth")) { // 8170732. These are the maximum size bytes after jgss/krb5 wrap. if (lastClientToken[17] != 0 || lastClientToken[18] != 0 || lastClientToken[19] != 0) { - throw new Exception("maximum size for auth must be 0"); + throw new RuntimeException("maximum size for auth must be 0"); } + testWrapUnwrapNoSecLayer(sc, ss); } else { - byte[] hello = "hello".getBytes(); - token = sc.wrap(hello, 0, hello.length); - token = ss.unwrap(token, 0, token.length); - if (!Arrays.equals(hello, token)) { - throw new Exception("Message altered"); - } + testWrapUnwrapWithSecLayer(sc, ss); + } + } + + private static void testWrapUnwrapWithSecLayer(SaslClient sc, SaslServer ss) + throws SaslException { + byte[] token; + byte[] hello = "hello".getBytes(); + + // test client wrap and server unwrap + token = sc.wrap(hello, 0, hello.length); + token = ss.unwrap(token, 0, token.length); + + if (!Arrays.equals(hello, token)) { + throw new RuntimeException("Client message altered"); + } + + // test server wrap and client unwrap + token = ss.wrap(hello, 0, hello.length); + token = sc.unwrap(token, 0, token.length); + + if (!Arrays.equals(hello, token)) { + throw new RuntimeException("Server message altered"); + } + } + + private static void testWrapUnwrapNoSecLayer(SaslClient sc, SaslServer ss) + throws SaslException { + byte[] clntBuf = new byte[]{0, 1, 2, 3}; + byte[] srvBuf = new byte[]{10, 11, 12, 13}; + String expectedError = "No security layer negotiated"; + + try { + sc.wrap(clntBuf, 0, clntBuf.length); + throw new RuntimeException( + "client wrap should not be allowed w/no security layer"); + } catch (IllegalStateException e) { + assertEquals(expectedError, e.getMessage()); + } + + try { + ss.wrap(srvBuf, 0, srvBuf.length); + throw new RuntimeException( + "server wrap should not be allowed w/no security layer"); + } catch (IllegalStateException e) { + assertEquals(expectedError, e.getMessage()); + } + + try { + sc.unwrap(clntBuf, 0, clntBuf.length); + throw new RuntimeException( + "client unwrap should not be allowed w/no security layer"); + } catch (IllegalStateException e) { + assertEquals(expectedError, e.getMessage()); + } + + try { + ss.unwrap(srvBuf, 0, srvBuf.length); + throw new RuntimeException( + "server unwrap should not be allowed w/no security layer"); + } catch (IllegalStateException e) { + assertEquals(expectedError, e.getMessage()); } } } diff --git a/test/jdk/sun/security/krb5/runNameEquals.sh b/test/jdk/sun/security/krb5/runNameEquals.sh deleted file mode 100644 index ecfd65a2fe4..00000000000 --- a/test/jdk/sun/security/krb5/runNameEquals.sh +++ /dev/null @@ -1,127 +0,0 @@ -# -# Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact 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 6317711 6944847 8024046 -# @summary Ensure the GSSName has the correct impl which respects -# the contract for equals and hashCode across different configurations. - -# set a few environment variables so that the shell-script can run stand-alone -# in the source directory - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi - -if [ "${TESTCLASSES}" = "" ] ; then - TESTCLASSES="." -fi - -if [ "${TESTJAVA}" = "" ] ; then - echo "TESTJAVA not set. Test cannot execute." - echo "FAILED!!!" - exit 1 -fi - -if [ "${COMPILEJAVA}" = "" ]; then - COMPILEJAVA="${TESTJAVA}" -fi - -NATIVE=false - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Linux | Darwin ) - PATHSEP=":" - FILESEP="/" - NATIVE=true - # Not all *nix has native GSS libs installed - krb5-config --libs 2> /dev/null - if [ $? != 0 ]; then - # Fedora has a different path - /usr/kerberos/bin/krb5-config --libs 2> /dev/null - if [ $? != 0 ]; then - NATIVE=false - fi - fi - ;; - AIX ) - PATHSEP=":" - FILESEP="/" - ;; - CYGWIN* ) - PATHSEP=";" - FILESEP="/" - ;; - Windows* ) - PATHSEP=";" - FILESEP="\\" - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -TEST=Krb5NameEquals - -${COMPILEJAVA}${FILESEP}bin${FILESEP}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ - -d ${TESTCLASSES}${FILESEP} \ - ${TESTSRC}${FILESEP}${TEST}.java - -EXIT_STATUS=0 - -if [ "${NATIVE}" = "true" ] ; then - echo "Testing native provider" - ${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} ${TESTJAVAOPTS} \ - -classpath ${TESTCLASSES} \ - -Dsun.security.jgss.native=true \ - ${TEST} - if [ $? != 0 ] ; then - echo "Native provider fails" - EXIT_STATUS=1 - if [ "$OS" = "Linux" -a `arch` = "x86_64" ]; then - ${TESTJAVA}${FILESEP}bin${FILESEP}java -XshowSettings:properties -version 2> allprop - cat allprop | grep sun.arch.data.model | grep 32 - if [ "$?" = "0" ]; then - echo "Running 32-bit JDK on 64-bit Linux. Maybe only 64-bit library is installed." - echo "Please manually check if this is the case. Treated as PASSED now." - EXIT_STATUS=0 - fi - fi - fi -fi - -echo "Testing java provider" -${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} ${TESTJAVAOPTS} \ - -classpath ${TESTCLASSES} \ - -Djava.security.krb5.realm=R \ - -Djava.security.krb5.kdc=127.0.0.1 \ - ${TEST} -if [ $? != 0 ] ; then - echo "Java provider fails" - EXIT_STATUS=1 -fi - -exit ${EXIT_STATUS} diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java b/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java index 1246e13fb23..11160a83800 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ * @run main/othervm -Djava.security.manager=allow SupportedDHKeys sm */ +import jtreg.SkippedException; + import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -63,8 +65,7 @@ private enum SupportedKeySize { @Override public void main(Provider provider) throws Exception { if (provider.getService("KeyPairGenerator", "DiffieHellman") == null) { - System.out.println("No support of DH KeyPairGenerator, skipping"); - return; + throw new SkippedException("No support of DH KeyPairGenerator, skipping"); } for (SupportedKeySize keySize : SupportedKeySize.values()) { diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java b/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java index 13b09d16dcf..d2394b1f650 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestDH.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,14 +39,14 @@ import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import jdk.test.lib.security.SecurityUtils; +import jtreg.SkippedException; public class TestDH extends PKCS11Test { @Override public void main(Provider p) throws Exception { if (p.getService("KeyAgreement", "DH") == null) { - System.out.println("DH not supported, skipping"); - return; + throw new SkippedException("DH not supported, skipping"); } String kpgAlgorithm = "DH"; KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgorithm, p); diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java b/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java index 7f6f79e767b..65dcd1a1bea 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestInterop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 +41,7 @@ import javax.crypto.spec.DHPublicKeySpec; import jdk.test.lib.security.DiffieHellmanGroup; import jdk.test.lib.security.SecurityUtils; +import jtreg.SkippedException; public class TestInterop extends PKCS11Test { @@ -77,8 +78,7 @@ public class TestInterop extends PKCS11Test { @Override public void main(Provider prov) throws Exception { if (prov.getService("KeyAgreement", "DH") == null) { - System.out.println("DH not supported, skipping"); - return; + throw new SkippedException("DH not supported, skipping"); } try { System.out.println("testing generateSecret()"); diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java b/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java index 0639c06b7d8..1cec208e965 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/TestShort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 +32,8 @@ * @run main/othervm -Djava.security.manager=allow TestShort sm */ +import jtreg.SkippedException; + import java.math.BigInteger; import java.security.KeyFactory; import java.security.PrivateKey; @@ -91,12 +93,10 @@ public class TestShort extends PKCS11Test { @Override public void main(Provider provider) throws Exception { if (provider.getService("KeyAgreement", "DH") == null) { - System.out.println("DH not supported, skipping"); - return; + throw new SkippedException("DH not supported, skipping"); } + try { - DHPublicKeySpec publicSpec; - DHPrivateKeySpec privateSpec; KeyFactory kf = KeyFactory.getInstance("DH", provider); KeyAgreement ka = KeyAgreement.getInstance("DH", provider); @@ -107,7 +107,7 @@ public void main(Provider provider) throws Exception { ka.init(pr1); ka.doPhase(pu2, true); byte[] n2 = ka.generateSecret(); - if (Arrays.equals(s2, n2) == false) { + if (!Arrays.equals(s2, n2)) { throw new Exception("mismatch 2"); } System.out.println("short ok"); @@ -115,7 +115,7 @@ public void main(Provider provider) throws Exception { ka.init(pr1); ka.doPhase(pu3, true); byte[] n3 = ka.generateSecret(); - if (Arrays.equals(s3, n3) == false) { + if (!Arrays.equals(s3, n3)) { throw new Exception("mismatch 3"); } System.out.println("normal ok"); @@ -124,27 +124,6 @@ public void main(Provider provider) throws Exception { ex.printStackTrace(); throw ex; } - -/* - KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", provider); - kpg.initialize(512); -// KeyPair kp1 = kpg.generateKeyPair(); -// System.out.println(kp1.getPublic()); -// System.out.println(kp1.getPrivate()); - while (true) { - KeyAgreement ka = KeyAgreement.getInstance("DH", provider); - ka.init(pr1); - KeyPair kp2 = kpg.generateKeyPair(); - ka.doPhase(kp2.getPublic(), true); - byte[] sec = ka.generateSecret(); - if (sec.length == 64) { - System.out.println(kp2.getPrivate()); - System.out.println(kp2.getPublic()); - System.out.println(toString(sec)); - break; - } - } -/**/ } public static void main(String[] args) throws Exception { diff --git a/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java b/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java index af1734dcd80..56052c017af 100644 --- a/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java +++ b/test/jdk/sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ * @run main/othervm -Djava.security.manager=allow UnsupportedDHKeys sm */ +import jtreg.SkippedException; + import java.security.InvalidParameterException; import java.security.KeyPairGenerator; import java.security.Provider; @@ -60,8 +62,7 @@ private enum UnsupportedKeySize { @Override public void main(Provider provider) throws Exception { if (provider.getService("KeyPairGenerator", "DiffieHellman") == null) { - System.out.println("No supported of DH KeyPairGenerator, skipping"); - return; + throw new SkippedException("DH (DiffieHellman) is not supported in KeyPairGenerator, skipping"); } for (UnsupportedKeySize keySize : UnsupportedKeySize.values()) { diff --git a/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java b/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java index c08c224c620..0221156926f 100644 --- a/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java +++ b/test/jdk/sun/security/pkcs11/KeyGenerator/DESParity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ * @run main/othervm -Djava.security.manager=allow DESParity sm */ +import jtreg.SkippedException; + import java.security.Provider; import java.util.Random; import javax.crypto.SecretKey; @@ -46,8 +48,7 @@ public class DESParity extends PKCS11Test { @Override public void main(Provider p) throws Exception { if (p.getService("SecretKeyFactory", "DES") == null) { - System.out.println("Not supported by provider, skipping"); - return; + throw new SkippedException("Not supported by provider, skipping"); } Random random = new Random(); SecretKeyFactory kf; @@ -58,7 +59,7 @@ public void main(Provider p) throws Exception { random.nextBytes(b); SecretKeySpec spec = new SecretKeySpec(b, "DES"); SecretKey key = kf.generateSecret(spec); - if (DESKeySpec.isParityAdjusted(key.getEncoded(), 0) == false) { + if (!DESKeySpec.isParityAdjusted(key.getEncoded(), 0)) { throw new Exception("DES key not parity adjusted"); } } @@ -69,7 +70,7 @@ public void main(Provider p) throws Exception { random.nextBytes(b); SecretKeySpec spec = new SecretKeySpec(b, "DESede"); SecretKey key = kf.generateSecret(spec); - if (DESedeKeySpec.isParityAdjusted(key.getEncoded(), 0) == false) { + if (!DESedeKeySpec.isParityAdjusted(key.getEncoded(), 0)) { throw new Exception("DESede key not parity adjusted"); } } diff --git a/test/jdk/sun/security/pkcs11/KeyGenerator/TestAES.java b/test/jdk/sun/security/pkcs11/KeyGenerator/TestAES.java index e74007a65e3..66078be30bd 100644 --- a/test/jdk/sun/security/pkcs11/KeyGenerator/TestAES.java +++ b/test/jdk/sun/security/pkcs11/KeyGenerator/TestAES.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * 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,13 +30,14 @@ * @library /test/lib .. * @run main TestAES */ +import jtreg.SkippedException; +import sun.security.util.SecurityProviderConstants; + import java.security.Provider; -import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; import java.security.NoSuchAlgorithmException; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; -import static sun.security.util.SecurityProviderConstants.*; public class TestAES extends PKCS11Test { @@ -53,17 +54,16 @@ public void main(Provider p) throws Exception { try { kg = KeyGenerator.getInstance(ALGO, p); } catch (NoSuchAlgorithmException nsae) { - System.out.println("Skip; no support for " + ALGO); - return; + throw new SkippedException("Skip; no support for " + ALGO, nsae); } // first try w/o setting a key length and check if the generated key // length matches SecretKey key = kg.generateKey(); byte[] keyValue = key.getEncoded(); - if (key.getEncoded().length != getDefAESKeySize() >> 3) { + if (key.getEncoded().length != SecurityProviderConstants.getDefAESKeySize() >> 3) { throw new RuntimeException("Default AES key length should be " + - getDefAESKeySize()); + SecurityProviderConstants.getDefAESKeySize()); } for (int keySize : new int[] { 16, 32, 64, 128, 256, 512, 1024 }) { diff --git a/test/jdk/sun/security/pkcs11/KeyGenerator/TestChaCha20.java b/test/jdk/sun/security/pkcs11/KeyGenerator/TestChaCha20.java index a21571cd957..0eaab538655 100644 --- a/test/jdk/sun/security/pkcs11/KeyGenerator/TestChaCha20.java +++ b/test/jdk/sun/security/pkcs11/KeyGenerator/TestChaCha20.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 +29,8 @@ * @library /test/lib .. * @run main/othervm TestChaCha20 */ +import jtreg.SkippedException; + import java.security.Provider; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; @@ -54,8 +56,7 @@ public void main(Provider p) throws Exception { try { kg = KeyGenerator.getInstance(ALGO, p); } catch (NoSuchAlgorithmException nsae) { - System.out.println("Skip; no support for " + ALGO); - return; + throw new SkippedException("Skip; no support for " + ALGO, nsae); } try { diff --git a/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java b/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java index ccf86444564..d055630e91c 100644 --- a/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java +++ b/test/jdk/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java index f251c443c18..59b2465ce7b 100644 --- a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java +++ b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDH2048.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 +32,8 @@ * @run main/othervm -Djava.security.manager=allow TestDH2048 sm */ +import jtreg.SkippedException; + import java.security.InvalidParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -51,8 +53,7 @@ private static void checkUnsupportedKeySize(KeyPairGenerator kpg, int ks) @Override public void main(Provider p) throws Exception { if (p.getService("KeyPairGenerator", "DH") == null) { - System.out.println("KPG for DH not supported, skipping"); - return; + throw new SkippedException("KPG for DH not supported, skipping"); } KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", p); kpg.initialize(512); diff --git a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDefaultDHPrivateExpSize.java b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDefaultDHPrivateExpSize.java index cb93a96fdd2..3f19a59423b 100644 --- a/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDefaultDHPrivateExpSize.java +++ b/test/jdk/sun/security/pkcs11/KeyPairGenerator/TestDefaultDHPrivateExpSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * 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,12 +21,12 @@ * questions. */ -import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.Provider; -import java.security.PrivateKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.interfaces.DHPrivateKey; + +import jtreg.SkippedException; import sun.security.util.SecurityProviderConstants; import sun.security.provider.ParameterCache; @@ -47,8 +47,7 @@ public void main(Provider p) throws Exception { System.out.println("Testing " + p.getName()); if (p.getService("KeyPairGenerator", "DH") == null) { - System.out.println("Skip, no support for DH KeyPairGenerator"); - return; + throw new SkippedException("Skip, no support for DH KeyPairGenerator"); } KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", p); diff --git a/test/jdk/sun/security/pkcs11/KeyStore/CertChainRemoval.java b/test/jdk/sun/security/pkcs11/KeyStore/CertChainRemoval.java index 0158da0da36..31efbccaeab 100644 --- a/test/jdk/sun/security/pkcs11/KeyStore/CertChainRemoval.java +++ b/test/jdk/sun/security/pkcs11/KeyStore/CertChainRemoval.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * 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,15 +28,17 @@ * @run testng/othervm CertChainRemoval */ import jdk.test.lib.SecurityTools; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; import java.nio.file.Path; -import java.util.*; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.Provider; import java.security.cert.Certificate; +import java.util.Arrays; +import java.util.Enumeration; import jtreg.SkippedException; import org.testng.SkipException; @@ -125,8 +127,7 @@ public void main(Provider p) throws Exception { p11ks.load(null, PKCS11KS.passwd); printKeyStore("Initial PKCS11 KeyStore: ", p11ks); } catch (Exception e) { - System.out.println("Skip test, due to " + e); - return; + throw new SkippedException("Skip test, due to " + e, e); } // get the necessary keys from the temp keystore diff --git a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.java b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.java index 1af1258d173..5d50015880d 100644 --- a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.java +++ b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,8 +260,7 @@ public void main(Provider p) throws Exception { try { javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding", p); } catch (GeneralSecurityException e) { - System.out.println("Not supported by provider, skipping"); - return; + throw new SkippedException("Not supported by provider, skipping"); } this.provider = p; diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java index d19d4a2dbec..c231791e972 100644 --- a/test/jdk/sun/security/pkcs11/PKCS11Test.java +++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java @@ -82,7 +82,7 @@ public abstract class PKCS11Test { // Version of the NSS artifact. This coincides with the version of // the NSS version - private static final String NSS_BUNDLE_VERSION = "3.107"; + private static final String NSS_BUNDLE_VERSION = "3.111"; private static final String NSSLIB = "jpg.tests.jdk.nsslib"; static double nss_version = -1; diff --git a/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestGeneral.java b/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestGeneral.java index bca594c66bd..e59d0b4a1ca 100644 --- a/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestGeneral.java +++ b/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestGeneral.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * 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,10 +30,14 @@ * @run main/othervm TestGeneral */ +import jtreg.SkippedException; + import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.SecureRandom; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; @@ -57,8 +61,11 @@ private void test(String algorithm, SecretKey key, Provider p, try { skf = SecretKeyFactory.getInstance(algorithm, p); } catch (NoSuchAlgorithmException e) { - System.out.println("Not supported, skipping: " + e); - return; + throw new SkippedException("[algorithm: " + algorithm + + ", key: " + key.getAlgorithm() + "]" + + ", provider: " + p.getName() + "]" + + ", expectedTestResult: " + expected + "]" + + "Not supported, skipping: " + e); } try { SecretKey key2 = skf.translateKey(key); @@ -99,21 +106,31 @@ public void main(Provider p) throws Exception { SecretKey bf_128Key = new SecretKeySpec(rawBytes, 0, 16, "Blowfish"); SecretKey cc20Key = new SecretKeySpec(rawBytes, 0, 32, "ChaCha20"); - // fixed key length - test("AES", aes_128Key, p, TestResult.PASS); - test("AES", aes_256Key, p, TestResult.PASS); - test("AES", cc20Key, p, TestResult.FAIL); + List skippedList = new ArrayList<>(); + try { + // fixed key length + test("AES", aes_128Key, p, TestResult.PASS); + test("AES", aes_256Key, p, TestResult.PASS); + test("AES", cc20Key, p, TestResult.FAIL); - test("ChaCha20", aes_128Key, p, TestResult.FAIL); - test("ChaCha20", aes_256Key, p, TestResult.FAIL); - test("ChaCha20", cc20Key, p, TestResult.PASS); + test("ChaCha20", aes_128Key, p, TestResult.FAIL); + test("ChaCha20", aes_256Key, p, TestResult.FAIL); + test("ChaCha20", cc20Key, p, TestResult.PASS); - // variable key length - // Different PKCS11 impls may have different ranges - // of supported key sizes for variable-key-length - // algorithms. - test("Blowfish", aes_128Key, p, TestResult.FAIL); - test("Blowfish", cc20Key, p, TestResult.FAIL); - test("Blowfish", bf_128Key, p, TestResult.PASS); + // variable key length + // Different PKCS11 impls may have different ranges + // of supported key sizes for variable-key-length + // algorithms. + test("Blowfish", aes_128Key, p, TestResult.FAIL); + test("Blowfish", cc20Key, p, TestResult.FAIL); + test("Blowfish", bf_128Key, p, TestResult.PASS); + } catch (SkippedException skippedException){ + skippedException.printStackTrace(); + skippedList.add(skippedException.getMessage()); + } + + if (!skippedList.isEmpty()) { + throw new SkippedException("One or more tests skipped " + skippedList); + } } } diff --git a/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java b/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java index a014ae13a47..c7e7f2b8f02 100644 --- a/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java +++ b/test/jdk/sun/security/pkcs11/SecureRandom/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ * @run main/othervm -Djava.security.manager=allow Basic sm */ +import jtreg.SkippedException; + import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.SecureRandom; @@ -45,9 +47,8 @@ public void main(Provider p) throws Exception { try { random = SecureRandom.getInstance("PKCS11"); } catch (NoSuchAlgorithmException e) { - System.out.println("Provider " + p + " does not support SecureRandom, skipping"); e.printStackTrace(); - return; + throw new SkippedException("Provider " + p + " does not support SecureRandom, skipping", e); } byte[] b = new byte[32]; random.nextBytes(b); diff --git a/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java b/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java index f54ae95f36d..b8d37e2a00e 100644 --- a/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java +++ b/test/jdk/sun/security/pkcs11/SecureRandom/TestDeserialization.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * 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,6 +29,8 @@ * @modules jdk.crypto.cryptoki */ +import jtreg.SkippedException; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; @@ -43,18 +45,16 @@ public class TestDeserialization extends PKCS11Test { public void main(Provider p) throws Exception { // Skip this test for providers not found by java.security.Security if (Security.getProvider(p.getName()) != p) { - System.out.println("Skip test for provider " + p.getName()); - return; + throw new SkippedException("Skip test for provider " + p.getName()); } SecureRandom r; try { r = SecureRandom.getInstance("PKCS11", p); System.out.println("SecureRandom instance " + r); } catch (NoSuchAlgorithmException e) { - System.out.println("Provider " + p + - " does not support SecureRandom, skipping"); e.printStackTrace(); - return; + throw new SkippedException("Provider " + p + + " does not support SecureRandom, skipping"); } r.setSeed(System.currentTimeMillis()); byte[] buf = new byte[16]; diff --git a/test/jdk/sun/security/pkcs11/Serialize/SerializeProvider.java b/test/jdk/sun/security/pkcs11/Serialize/SerializeProvider.java index 495da8e6f38..2b268fe8fea 100644 --- a/test/jdk/sun/security/pkcs11/Serialize/SerializeProvider.java +++ b/test/jdk/sun/security/pkcs11/Serialize/SerializeProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * 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,9 +41,9 @@ public class SerializeProvider extends PKCS11Test { public void main(Provider p) throws Exception { + if (Security.getProvider(p.getName()) != p) { - System.out.println("Provider not installed in Security, skipping"); - return; + Security.addProvider(p); } ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -57,7 +57,7 @@ public void main(Provider p) throws Exception { InputStream in = new ByteArrayInputStream(data); ObjectInputStream oin = new ObjectInputStream(in); - Provider p2 = (Provider)oin.readObject(); + Provider p2 = (Provider) oin.readObject(); System.out.println("Reconstituted: " + p2); diff --git a/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java b/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java index 1f6886f2d69..a91bbac4651 100644 --- a/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java +++ b/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2019, Red Hat, Inc. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +64,7 @@ import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManagerFactory; +import jdk.test.lib.security.SecurityUtils; import sun.security.internal.spec.TlsMasterSecretParameterSpec; import sun.security.internal.spec.TlsPrfParameterSpec; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; @@ -80,6 +82,9 @@ public final class FipsModeTLS12 extends SecmodTest { private static PublicKey publicKey; public static void main(String[] args) throws Exception { + // Re-enable TLS_RSA_* since test depends on it. + SecurityUtils.removeFromDisabledTlsAlgs("TLS_RSA_*"); + try { initialize(); } catch (Exception e) { diff --git a/test/jdk/sun/security/ssl/ClientHandshaker/LengthCheckTest.java b/test/jdk/sun/security/ssl/ClientHandshaker/LengthCheckTest.java index 6c9dd847ee9..3aecb84bd94 100644 --- a/test/jdk/sun/security/ssl/ClientHandshaker/LengthCheckTest.java +++ b/test/jdk/sun/security/ssl/ClientHandshaker/LengthCheckTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -270,8 +270,8 @@ public void execTest() throws Exception { * Main entry point for this test. */ public static void main(String args[]) throws Exception { - // Re-enable TLSv1 since test depends on it. - SecurityUtils.removeFromDisabledTlsAlgs("TLSv1"); + // Re-enable TLSv1 and TLS_RSA_* since test depends on it. + SecurityUtils.removeFromDisabledTlsAlgs("TLSv1", "TLS_RSA_*"); List ccsTests = new ArrayList<>(); diff --git a/test/jdk/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.java b/test/jdk/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.java index 7632fcf462f..1446ad786e4 100644 --- a/test/jdk/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.java +++ b/test/jdk/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,8 +100,8 @@ public static void main(String args[]) throws Exception { System.out.println("Test Passed."); } else { - // Re-enable TLSv1 since test depends on it - SecurityUtils.removeFromDisabledTlsAlgs("TLSv1"); + // Re-enable TLSv1 and TLS_RSA_* since test depends on it + SecurityUtils.removeFromDisabledTlsAlgs("TLSv1", "TLS_RSA_*"); DebugReportsOneExtraByte test = new DebugReportsOneExtraByte(); test.runTest(); diff --git a/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureDTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureDTLS12.java new file mode 100644 index 00000000000..6c597cd2576 --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureDTLS12.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8340321 + * @summary Disable SHA-1 in TLS/DTLS 1.2 signatures. + * This test only covers DTLS 1.2. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSHA1inHandshakeSignatureDTLS12 + */ + +public class DisableSHA1inHandshakeSignatureDTLS12 extends + DisableSHA1inHandshakeSignatureTLS12 { + + protected DisableSHA1inHandshakeSignatureDTLS12() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + new DisableSHA1inHandshakeSignatureDTLS12().run(); + } + + @Override + protected String getProtocol() { + return "DTLSv1.2"; + } + + // No CertificateRequest in DTLS server flight. + @Override + protected void checkCertificateRequest() { + } +} diff --git a/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS12.java new file mode 100644 index 00000000000..0389740b7fe --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS12.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8340321 + * @summary Disable SHA-1 in TLS/DTLS 1.2 signatures. + * This test only covers TLS 1.2. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSHA1inHandshakeSignatureTLS12 + */ + +import static jdk.test.lib.Asserts.assertFalse; +import static jdk.test.lib.Asserts.assertTrue; + +import java.util.List; + +public class DisableSHA1inHandshakeSignatureTLS12 extends + AbstractCheckSignatureSchemes { + + protected DisableSHA1inHandshakeSignatureTLS12() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + new DisableSHA1inHandshakeSignatureTLS12().run(); + } + + @Override + protected String getProtocol() { + return "TLSv1.2"; + } + + // Run things in TLS handshake order. + protected void run() throws Exception { + + // Produce client_hello + clientEngine.wrap(clientOut, cTOs); + cTOs.flip(); + + checkClientHello(); + + // Consume client_hello. + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + // Produce server_hello. + serverEngine.wrap(serverOut, sTOc); + sTOc.flip(); + + checkCertificateRequest(); + } + + // Returns SHA-1 signature schemes supported for TLSv1.2 handshake + protected List getDisabledSignatureSchemes() { + return List.of( + "ecdsa_sha1", + "rsa_pkcs1_sha1", + "dsa_sha1" + ); + } + + protected void checkClientHello() throws Exception { + // Get signature_algorithms extension signature schemes. + List sigAlgsSS = getSigSchemesCliHello( + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_EXT); + + // Should not be present in signature_algorithms extension. + getDisabledSignatureSchemes().forEach(ss -> + assertFalse(sigAlgsSS.contains(ss), + "Signature Scheme " + ss + + " present in ClientHello's signature_algorithms extension")); + + // Get signature_algorithms_cert extension signature schemes. + List sigAlgsCertSS = getSigSchemesCliHello( + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_CERT_EXT); + + // Should be present in signature_algorithms_cert extension. + getDisabledSignatureSchemes().forEach(ss -> + assertTrue(sigAlgsCertSS.contains(ss), + "Signature Scheme " + ss + + " isn't present in ClientHello's" + + " signature_algorithms extension")); + } + + protected void checkCertificateRequest() throws Exception { + // Get CertificateRequest message signature schemes. + List sigAlgsCertSS = getSigSchemesCertReq( + extractHandshakeMsg(sTOc, TLS_HS_CERT_REQ)); + + // Should not be present in CertificateRequest message. + getDisabledSignatureSchemes().forEach(ss -> + assertFalse(sigAlgsCertSS.contains(ss), + "Signature Scheme " + ss + + " present in CertificateRequest")); + } +} diff --git a/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS13.java b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS13.java new file mode 100644 index 00000000000..55f619460d4 --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS13.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8340321 + * @summary Disable SHA-1 in TLS/DTLS 1.2 signatures. + * This test only covers TLS 1.3. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSHA1inHandshakeSignatureTLS13 + */ + +import java.security.Security; +import java.util.List; + +public class DisableSHA1inHandshakeSignatureTLS13 extends + DisableSHA1inHandshakeSignatureTLS12 { + + protected DisableSHA1inHandshakeSignatureTLS13() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + // SHA-1 algorithm MUST NOT be used in any TLSv1.3 handshake signatures. + // This is regardless of jdk.tls.disabledAlgorithms configuration. + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + new DisableSHA1inHandshakeSignatureTLS13().run(); + } + + @Override + protected String getProtocol() { + return "TLSv1.3"; + } + + // Returns SHA-1 signature schemes NOT supported for TLSv1.3 handshake + // signatures, but supported for TLSv1.3 certificate signatures. + @Override + protected List getDisabledSignatureSchemes() { + return List.of("ecdsa_sha1", "rsa_pkcs1_sha1"); + } + + // TLSv1.3 sends CertificateRequest signature schemes in + // signature_algorithms and signature_algorithms_cert extensions. Same as + // ClientHello, but they are encrypted. So we skip CertificateRequest + // signature schemes verification for TLSv1.3. + @Override + protected void checkCertificateRequest() { + } +} diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java index 598c0fe62af..43bc40fabf2 100644 --- a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (C) 2021, 2024 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, 2024, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java index 2ad48f59e83..034af3ac7c5 100644 --- a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/sun/security/tools/jarsigner/VerifyJarEntryName.java b/test/jdk/sun/security/tools/jarsigner/VerifyJarEntryName.java new file mode 100644 index 00000000000..e2554ee0f91 --- /dev/null +++ b/test/jdk/sun/security/tools/jarsigner/VerifyJarEntryName.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact 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 8339280 + * @summary Test that jarsigner -verify emits a warning when the filename of + * an entry in the LOC is changed + * @library /test/lib + * @run junit VerifyJarEntryName + */ + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import jdk.test.lib.SecurityTools; +import static org.junit.jupiter.api.Assertions.fail; + +public class VerifyJarEntryName { + + private static final Path ORIGINAL_JAR = Path.of("test.jar"); + private static final Path MODIFIED_JAR = Path.of("modified_test.jar"); + + @BeforeAll + static void setup() throws Exception { + try (FileOutputStream fos = new FileOutputStream(ORIGINAL_JAR.toFile()); + ZipOutputStream zos = new ZipOutputStream(fos)) { + zos.putNextEntry(new ZipEntry(JarFile.MANIFEST_NAME)); + zos.write("Manifest-Version: 1.0\nCreated-By: Test\n". + getBytes(StandardCharsets.UTF_8)); + zos.closeEntry(); + + // Add hello.txt file + ZipEntry textEntry = new ZipEntry("hello.txt"); + zos.putNextEntry(textEntry); + zos.write("hello".getBytes(StandardCharsets.UTF_8)); + zos.closeEntry(); + } + + SecurityTools.keytool("-genkeypair -keystore ks -storepass changeit " + + "-alias mykey -keyalg rsa -dname CN=me "); + + SecurityTools.jarsigner("-keystore ks -storepass changeit " + + ORIGINAL_JAR + " mykey") + .shouldHaveExitValue(0); + } + + @BeforeEach + void cleanup() throws Exception { + Files.deleteIfExists(MODIFIED_JAR); + } + + /* + * Modify a single byte in "MANIFEST.MF" filename in LOC, and + * validate that jarsigner -verify emits a warning message. + */ + @Test + void verifyManifestEntryName() throws Exception { + modifyJarEntryName(ORIGINAL_JAR, MODIFIED_JAR, "META-INF/MANIFEST.MF"); + SecurityTools.jarsigner("-verify -verbose " + MODIFIED_JAR) + .shouldContain("This JAR file contains internal " + + "inconsistencies that may result in different " + + "contents when reading via JarFile and JarInputStream:") + .shouldContain("- Manifest is missing when " + + "reading via JarInputStream") + .shouldHaveExitValue(0); + } + + /* + * Modify a single byte in signature filename in LOC, and + * validate that jarsigner -verify emits a warning message. + */ + @Test + void verifySignatureEntryName() throws Exception { + modifyJarEntryName(ORIGINAL_JAR, MODIFIED_JAR, "META-INF/MYKEY.SF"); + SecurityTools.jarsigner("-verify -verbose " + MODIFIED_JAR) + .shouldContain("This JAR file contains internal " + + "inconsistencies that may result in different " + + "contents when reading via JarFile and JarInputStream:") + .shouldContain("- Entry XETA-INF/MYKEY.SF is present when reading " + + "via JarInputStream but missing when reading via JarFile") + .shouldHaveExitValue(0); + } + + /* + * Validate that jarsigner -verify on a valid JAR works without + * emitting warnings about internal inconsistencies. + */ + @Test + void verifyOriginalJar() throws Exception { + SecurityTools.jarsigner("-verify -verbose " + ORIGINAL_JAR) + .shouldNotContain("This JAR file contains internal " + + "inconsistencies that may result in different contents when " + + "reading via JarFile and JarInputStream:") + .shouldHaveExitValue(0); + } + + private void modifyJarEntryName(Path origJar, Path modifiedJar, + String entryName) throws Exception { + byte[] jarBytes = Files.readAllBytes(origJar); + byte[] entryNameBytes = entryName.getBytes(StandardCharsets.UTF_8); + int pos = 0; + try { + while (!Arrays.equals(jarBytes, pos, pos + entryNameBytes.length, + entryNameBytes, 0, entryNameBytes.length)) pos++; + } catch (ArrayIndexOutOfBoundsException ignore) { + fail(entryName + " is not present in the JAR"); + } + jarBytes[pos] = 'X'; + Files.write(modifiedJar, jarBytes); + } +} diff --git a/test/jdk/sun/security/util/Resources/TEST.properties b/test/jdk/sun/security/util/Resources/TEST.properties deleted file mode 100644 index 908b451f8ea..00000000000 --- a/test/jdk/sun/security/util/Resources/TEST.properties +++ /dev/null @@ -1,2 +0,0 @@ -# disabled till JDK-8219408 is fixed -allowSmartActionArgs=false diff --git a/test/jdk/sun/security/x509/X509CertImpl/V3Certificate.java b/test/jdk/sun/security/x509/X509CertImpl/V3Certificate.java index 2d3dbfd659c..29c651164d3 100644 --- a/test/jdk/sun/security/x509/X509CertImpl/V3Certificate.java +++ b/test/jdk/sun/security/x509/X509CertImpl/V3Certificate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * 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 8049237 8242151 + * @bug 8049237 8242151 8347841 * @modules java.base/sun.security.x509 * java.base/sun.security.util * jdk.crypto.ec @@ -114,7 +114,7 @@ public static boolean test(String algorithm, String sigAlg, int keyLength) // Validity interval Date firstDate = new Date(); - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST")); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")); cal.set(2014, 03, 10, 12, 30, 30); Date lastDate = cal.getTime(); CertificateValidity interval = new CertificateValidity(firstDate, diff --git a/test/jdk/sun/tools/jcmd/JcmdBase.java b/test/jdk/sun/tools/jcmd/JcmdBase.java index b0315673133..9a0f97f5bf4 100644 --- a/test/jdk/sun/tools/jcmd/JcmdBase.java +++ b/test/jdk/sun/tools/jcmd/JcmdBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,6 +102,8 @@ private static final OutputAnalyzer jcmd(boolean requestToCurrentProcess, launcher.addVMArg(vmArg); } } + // Some command output may be lengthy, disable streaming output to avoid deadlocks + launcher.addVMArg("-Djdk.attach.allowStreamingOutput=false"); if (requestToCurrentProcess) { launcher.addToolArg(Long.toString(ProcessTools.getProcessId())); } diff --git a/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java b/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java index 4fa589c7b27..b533aab5966 100644 --- a/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java +++ b/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * 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 8007572 8008161 8157792 8212970 8224560 + * @bug 8007572 8008161 8157792 8212970 8224560 8324065 * @summary Test whether the TimeZone generated from JSR310 tzdb is the same * as the one from the tz data from javazic * @modules java.base/sun.util.calendar:+open @@ -173,9 +173,9 @@ public static void main(String[] args) throws Throwable { ZoneInfoOld zi = toZoneInfoOld(TimeZone.getTimeZone(zid)); ZoneInfoOld ziOLD = (ZoneInfoOld)ZoneInfoOld.getTimeZone(zid); /* - * Temporary ignoring the failing TimeZones which are having zone - * rules defined till year 2037 and/or above and have negative DST - * save time in IANA tzdata. This bug is tracked via JDK-8223388. + * Ignoring the failing TimeZones which have negative DST + * save time in IANA tzdata, as javazic/ZoneInfoOld cannot + * handle the negative DST. * * These are the zones/rules that employ negative DST in vanguard * format (as of 2019a), Palestine added in 2022d: @@ -185,11 +185,6 @@ public static void main(String[] args) throws Throwable { * - Rule "Namibia" * - Rule "Palestine" * - Zone "Europe/Prague" - * - * Tehran/Iran rule has rules beyond 2037, in which javazic assumes - * to be the last year. Thus javazic's rule is based on year 2037 - * (Mar 20th/Sep 20th are the cutover dates), while the real rule - * has year 2087 where Mar 21st/Sep 21st are the cutover dates. */ if (zid.equals("Africa/Casablanca") || // uses "Morocco" rule zid.equals("Africa/El_Aaiun") || // uses "Morocco" rule @@ -198,10 +193,8 @@ public static void main(String[] args) throws Throwable { zid.equals("Europe/Bratislava") || // link to "Europe/Prague" zid.equals("Europe/Dublin") || // uses "Eire" rule zid.equals("Europe/Prague") || - zid.equals("Asia/Tehran") || // last rule mismatch zid.equals("Asia/Gaza") || // uses "Palestine" rule - zid.equals("Asia/Hebron") || // uses "Palestine" rule - zid.equals("Iran")) { // last rule mismatch + zid.equals("Asia/Hebron")) { // uses "Palestine" rule continue; } if (! zi.equalsTo(ziOLD)) { diff --git a/test/jdk/sun/util/calendar/zi/ZoneInfoOld.java b/test/jdk/sun/util/calendar/zi/ZoneInfoOld.java index 45e8a346946..40f9cb9056c 100644 --- a/test/jdk/sun/util/calendar/zi/ZoneInfoOld.java +++ b/test/jdk/sun/util/calendar/zi/ZoneInfoOld.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * 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,14 +51,14 @@ * for the {@link #getOffset(int,int,int,int,int,int) getOffset} * method that takes Gregorian calendar date fields. *

- * This table covers transitions from 1900 until 2037 (as of version - * 1.4), Before 1900, it assumes that there was no daylight saving + * This table covers transitions from 1900 until 2100 (as of version + * 23), Before 1900, it assumes that there was no daylight saving * time and the getOffset methods always return the * {@link #getRawOffset} value. No Local Mean Time is supported. If a * specified date is beyond the transition table and this time zone is - * supposed to observe daylight saving time in 2037, it delegates + * supposed to observe daylight saving time in 2100, it delegates * operations to a {@link java.util.SimpleTimeZone SimpleTimeZone} - * object created using the daylight saving time schedule as of 2037. + * object created using the daylight saving time schedule as of 2100. *

* The date items, transitions, GMT offset(s), etc. are read from a database * file. See {@link ZoneInfoFile} for details. diff --git a/test/jdk/sun/util/calendar/zi/Zoneinfo.java b/test/jdk/sun/util/calendar/zi/Zoneinfo.java index a68aa7826b0..e125ad2cb87 100644 --- a/test/jdk/sun/util/calendar/zi/Zoneinfo.java +++ b/test/jdk/sun/util/calendar/zi/Zoneinfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ class Zoneinfo { private static final int minYear = 1900; - private static final int maxYear = 2037; + private static final int maxYear = 2100; private static final long minTime = Time.getLocalTime(minYear, Month.JANUARY, 1, 0); private static int startYear = minYear; private static int endYear = maxYear; diff --git a/test/jdk/sun/util/logging/SourceClassName.java b/test/jdk/sun/util/logging/SourceClassName.java index f3023122618..3dbc46f3d11 100644 --- a/test/jdk/sun/util/logging/SourceClassName.java +++ b/test/jdk/sun/util/logging/SourceClassName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * 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,17 +33,21 @@ * @run main/othervm SourceClassName */ +import java.util.Locale; import java.util.logging.*; import java.io.*; import sun.util.logging.PlatformLogger; public class SourceClassName { public static void main(String[] args) throws Exception { + Locale savedLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); File dir = new File(System.getProperty("user.dir", ".")); File log = new File(dir, "testlog.txt"); PrintStream logps = new PrintStream(log); writeLogRecords(logps); checkLogRecords(log); + Locale.setDefault(savedLocale); } private static void writeLogRecords(PrintStream logps) throws Exception { diff --git a/test/jdk/sun/util/resources/TimeZone/Bug4640234.java b/test/jdk/sun/util/resources/TimeZone/Bug4640234.java index da555bbf040..954932003af 100644 --- a/test/jdk/sun/util/resources/TimeZone/Bug4640234.java +++ b/test/jdk/sun/util/resources/TimeZone/Bug4640234.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * 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 4640234 4946057 4938151 4873691 5023181 + * @bug 4640234 4946057 4938151 4873691 5023181 8347841 * @summary Verifies the translation of time zone names, this test will catch * presence of country name for english and selected locales for all * ISO country codes. @@ -42,6 +42,8 @@ import java.text.MessageFormat; import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.util.Arrays; import java.util.Date; import java.util.Locale; import java.util.Enumeration; @@ -49,6 +51,7 @@ import java.util.Map; import java.util.ResourceBundle; import java.util.TimeZone; +import java.util.function.Predicate; import sun.util.resources.LocaleData; @@ -83,7 +86,9 @@ public static void main(String[] args) throws Exception { StringBuffer errors = new StringBuffer(""); StringBuffer warnings = new StringBuffer(""); - String[] timezones = TimeZone.getAvailableIDs(); + String[] timezones = Arrays.stream(TimeZone.getAvailableIDs()) + .filter(Predicate.not(ZoneId.SHORT_IDS::containsKey)) + .toArray(String[]::new); String[] countries = locEn.getISOCountries(); String[] languages = locEn.getISOLanguages(); diff --git a/test/jdk/sun/util/resources/cldr/Bug8134384.java b/test/jdk/sun/util/resources/cldr/Bug8134384.java index eac8238bdd2..f27b587ca98 100644 --- a/test/jdk/sun/util/resources/cldr/Bug8134384.java +++ b/test/jdk/sun/util/resources/cldr/Bug8134384.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * 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 8134384 8234347 8236548 + * @bug 8134384 8234347 8236548 8347841 * @summary Tests CLDR TimeZoneNames has English names for all tzids * @run main/othervm -Djava.locale.providers=CLDR Bug8134384 */ @@ -38,6 +38,9 @@ public static void main(String [] args) { try { for (String tz : TimeZone.getAvailableIDs() ) { + if (ZoneId.SHORT_IDS.containsKey(tz)) { + continue; + } TimeZone.setDefault(TimeZone.getTimeZone(tz)); // Summer solstice String date1 = Date.from(Instant.parse("2015-06-21T00:00:00.00Z")).toString(); diff --git a/test/jdk/sun/util/resources/cldr/Bug8202764.java b/test/jdk/sun/util/resources/cldr/Bug8202764.java index f2c614b6df0..6f3e40e6201 100644 --- a/test/jdk/sun/util/resources/cldr/Bug8202764.java +++ b/test/jdk/sun/util/resources/cldr/Bug8202764.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * 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 8202764 + * @bug 8202764 8347841 * @modules jdk.localedata * @summary Checks time zone names are consistent with aliased ids, * between DateFormatSymbols.getZoneStrings() and getDisplayName() @@ -49,6 +49,7 @@ public class Bug8202764 { public void testAliasedTZs() { Set zoneIds = ZoneId.getAvailableZoneIds(); Arrays.stream(DateFormatSymbols.getInstance(Locale.US).getZoneStrings()) + .filter(zone -> !ZoneId.SHORT_IDS.containsKey(zone[0])) .forEach(zone -> { System.out.println(zone[0]); TimeZone tz = TimeZone.getTimeZone(zone[0]); diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java new file mode 100644 index 00000000000..2d23f49cdd7 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.jpackage.test; + +import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; +import java.lang.reflect.Method; +import java.nio.file.Path; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import static java.util.stream.Collectors.toMap; +import java.util.stream.Stream; +import jdk.internal.util.OperatingSystem; +import static jdk.internal.util.OperatingSystem.LINUX; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterSupplier; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.Annotations.Test; +import static jdk.jpackage.test.Functional.ThrowingSupplier.toSupplier; + +/* + * @test + * @summary Test jpackage test library's annotation processor + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.* + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.AnnotationsTest + */ +public class AnnotationsTest { + + public static void main(String... args) { + runTests(BasicTest.class, ParameterizedInstanceTest.class); + for (var os : OperatingSystem.values()) { + try { + TestBuilderConfig.setOperatingSystem(os); + TKit.log("Current operating system: " + os); + runTests(IfOSTest.class); + } finally { + TestBuilderConfig.setDefaults(); + } + } + } + + public static class BasicTest extends TestExecutionRecorder { + @Test + public void testNoArg() { + recordTestCase(); + } + + @Test + @Parameter("TRUE") + public int testNoArg(boolean v) { + recordTestCase(v); + return 0; + } + + @Test + @Parameter({}) + @Parameter("a") + @Parameter({"b", "c"}) + public void testVarArg(Path ... paths) { + recordTestCase((Object[]) paths); + } + + @Test + @Parameter({"12", "foo"}) + @Parameter({"-89", "bar", "more"}) + @Parameter({"-89", "bar", "more", "moore"}) + public void testVarArg2(int a, String b, String ... other) { + recordTestCase(a, b, other); + } + + @Test + @ParameterSupplier("dateSupplier") + @ParameterSupplier("jdk.jpackage.test.AnnotationsTest.dateSupplier") + public void testDates(LocalDate v) { + recordTestCase(v); + } + + public static Set getExpectedTestDescs() { + return Set.of( + "().testNoArg()", + "().testNoArg(true)", + "().testVarArg()", + "().testVarArg(a)", + "().testVarArg(b, c)", + "().testVarArg2(-89, bar, [more, moore](length=2))", + "().testVarArg2(-89, bar, [more](length=1))", + "().testVarArg2(12, foo, [](length=0))", + "().testDates(2018-05-05)", + "().testDates(2018-07-11)", + "().testDates(2034-05-05)", + "().testDates(2056-07-11)" + ); + } + + public static Collection dateSupplier() { + return List.of(new Object[][] { + { LocalDate.parse("2018-05-05") }, + { LocalDate.parse("2018-07-11") }, + }); + } + } + + public static class ParameterizedInstanceTest extends TestExecutionRecorder { + public ParameterizedInstanceTest(String... args) { + super((Object[]) args); + } + + public ParameterizedInstanceTest(int o) { + super(o); + } + + public ParameterizedInstanceTest(int a, Boolean[] b, String c, String ... other) { + super(a, b, c, other); + } + + @Test + public void testNoArgs() { + recordTestCase(); + } + + @Test + @ParameterSupplier("jdk.jpackage.test.AnnotationsTest.dateSupplier") + public void testDates(LocalDate v) { + recordTestCase(v); + } + + @Test + @Parameter("a") + public static void staticTest(String arg) { + staticRecorder.recordTestCase(arg); + } + + @Parameters + public static Collection input() { + return List.of(new Object[][] { + {}, + {55, new Boolean[]{false, true, false}, "foo", "bar"}, + {78}, + }); + } + + @Parameters + public static Collection input2() { + return List.of(new Object[][] { + {51, new boolean[]{true, true, true}, "foo"}, + {33}, + {55, null, null }, + {55, null, null, "1" }, + }); + } + + public static Set getExpectedTestDescs() { + return Set.of( + "().testNoArgs()", + "(33).testNoArgs()", + "(78).testNoArgs()", + "(55, [false, true, false](length=3), foo, [bar](length=1)).testNoArgs()", + "(51, [true, true, true](length=3), foo, [](length=0)).testNoArgs()", + "().testDates(2034-05-05)", + "().testDates(2056-07-11)", + "(33).testDates(2034-05-05)", + "(33).testDates(2056-07-11)", + "(51, [true, true, true](length=3), foo, [](length=0)).testDates(2034-05-05)", + "(51, [true, true, true](length=3), foo, [](length=0)).testDates(2056-07-11)", + "(55, [false, true, false](length=3), foo, [bar](length=1)).testDates(2034-05-05)", + "(55, [false, true, false](length=3), foo, [bar](length=1)).testDates(2056-07-11)", + "(78).testDates(2034-05-05)", + "(78).testDates(2056-07-11)", + "(55, null, null, [1](length=1)).testDates(2034-05-05)", + "(55, null, null, [1](length=1)).testDates(2056-07-11)", + "(55, null, null, [1](length=1)).testNoArgs()", + "(55, null, null, [](length=0)).testDates(2034-05-05)", + "(55, null, null, [](length=0)).testDates(2056-07-11)", + "(55, null, null, [](length=0)).testNoArgs()", + "().staticTest(a)" + ); + } + + private final static TestExecutionRecorder staticRecorder = new TestExecutionRecorder(ParameterizedInstanceTest.class); + } + + public static class IfOSTest extends TestExecutionRecorder { + public IfOSTest(int a, String b) { + super(a, b); + } + + @Test(ifOS = OperatingSystem.LINUX) + public void testNoArgs() { + recordTestCase(); + } + + @Test(ifNotOS = OperatingSystem.LINUX) + public void testNoArgs2() { + recordTestCase(); + } + + @Test + @Parameter(value = "foo", ifOS = OperatingSystem.LINUX) + @Parameter(value = {"foo", "bar"}, ifOS = { OperatingSystem.LINUX, OperatingSystem.MACOS }) + @Parameter(value = {}, ifNotOS = { OperatingSystem.WINDOWS }) + public void testVarArgs(String ... args) { + recordTestCase((Object[]) args); + } + + @Test + @ParameterSupplier(value = "jdk.jpackage.test.AnnotationsTest.dateSupplier", ifOS = OperatingSystem.WINDOWS) + public void testDates(LocalDate v) { + recordTestCase(v); + } + + @Parameters(ifOS = OperatingSystem.LINUX) + public static Collection input() { + return Set.of(new Object[][] { + {7, null}, + }); + } + + @Parameters(ifNotOS = {OperatingSystem.LINUX, OperatingSystem.MACOS}) + public static Collection input2() { + return Set.of(new Object[][] { + {10, "hello"}, + }); + } + + @Parameters(ifNotOS = OperatingSystem.LINUX) + public static Collection input3() { + return Set.of(new Object[][] { + {15, "bye"}, + }); + } + + public static Set getExpectedTestDescs() { + switch (TestBuilderConfig.getDefault().getOperatingSystem()) { + case LINUX -> { + return Set.of( + "(7, null).testNoArgs()", + "(7, null).testVarArgs()", + "(7, null).testVarArgs(foo)", + "(7, null).testVarArgs(foo, bar)" + ); + } + + case MACOS -> { + return Set.of( + "(15, bye).testNoArgs2()", + "(15, bye).testVarArgs()", + "(15, bye).testVarArgs(foo, bar)" + ); + } + + case WINDOWS -> { + return Set.of( + "(15, bye).testDates(2034-05-05)", + "(15, bye).testDates(2056-07-11)", + "(15, bye).testNoArgs2()", + "(10, hello).testDates(2034-05-05)", + "(10, hello).testDates(2056-07-11)", + "(10, hello).testNoArgs2()" + ); + } + + case AIX -> { + return Set.of( + ); + } + } + + throw new UnsupportedOperationException(); + } + } + + public static Collection dateSupplier() { + return List.of(new Object[][] { + { LocalDate.parse("2034-05-05") }, + { LocalDate.parse("2056-07-11") }, + }); + } + + private static void runTests(Class... tests) { + ACTUAL_TEST_DESCS.get().clear(); + + var expectedTestDescs = Stream.of(tests) + .map(AnnotationsTest::getExpectedTestDescs) + .flatMap(x -> x) + // Collect in the map to check for collisions for free + .collect(toMap(x -> x, x -> "")) + .keySet(); + + var args = Stream.of(tests).map(test -> { + return String.format("--jpt-run=%s", test.getName()); + }).toArray(String[]::new); + + try { + Main.main(args); + assertRecordedTestDescs(expectedTestDescs); + } catch (Throwable t) { + t.printStackTrace(System.err); + System.exit(1); + } + } + + private static Stream getExpectedTestDescs(Class type) { + return toSupplier(() -> { + var method = type.getMethod("getExpectedTestDescs"); + var testDescPefix = type.getName(); + return ((Set)method.invoke(null)).stream().map(desc -> { + return testDescPefix + desc; + }); + }).get(); + } + + private static void assertRecordedTestDescs(Set expectedTestDescs) { + var comm = Comm.compare(expectedTestDescs, ACTUAL_TEST_DESCS.get()); + if (!comm.unique1().isEmpty()) { + System.err.println("Missing test case signatures:"); + comm.unique1().stream().sorted().sequential().forEachOrdered(System.err::println); + System.err.println("<>"); + } + + if (!comm.unique2().isEmpty()) { + System.err.println("Unexpected test case signatures:"); + comm.unique2().stream().sorted().sequential().forEachOrdered(System.err::println); + System.err.println("<>"); + } + + if (!comm.unique2().isEmpty() || !comm.unique1().isEmpty()) { + // Don't use TKit asserts as this call is outside the test execution + throw new AssertionError("Test case signatures mismatched"); + } + } + + private static class TestExecutionRecorder { + protected TestExecutionRecorder(Object ... args) { + this.testClass = getClass(); + this.testDescBuilder = TestInstance.TestDesc.createBuilder().ctorArgs(args); + } + + TestExecutionRecorder(Class testClass) { + this.testClass = testClass; + this.testDescBuilder = TestInstance.TestDesc.createBuilder().ctorArgs(); + } + + protected void recordTestCase(Object ... args) { + testDescBuilder.methodArgs(args).method(getCurrentTestCase()); + var testCaseDescs = ACTUAL_TEST_DESCS.get(); + var testCaseDesc = testDescBuilder.get().testFullName(); + TKit.assertTrue(!testCaseDescs.contains(testCaseDesc), String.format( + "Check this test case is executed for the first time", + testCaseDesc)); + TKit.assertTrue(!executed, "Check this test case instance is not reused"); + executed = true; + testCaseDescs.add(testCaseDesc); + } + + private Method getCurrentTestCase() { + return StackWalker.getInstance(RETAIN_CLASS_REFERENCE).walk(frames -> { + return frames.map(frame -> { + var methodType = frame.getMethodType(); + var methodName = frame.getMethodName(); + var methodReturn = methodType.returnType(); + var methodParameters = methodType.parameterArray(); + return Stream.of(testClass.getDeclaredMethods()).filter(method -> { + return method.getName().equals(methodName) + && method.getReturnType().equals(methodReturn) + && Arrays.equals(method.getParameterTypes(), methodParameters) + && method.isAnnotationPresent(Test.class); + }).findFirst(); + }).dropWhile(Optional::isEmpty).map(Optional::get).findFirst(); + }).get(); + } + + private boolean executed; + private final TestInstance.TestDesc.Builder testDescBuilder; + private final Class testClass; + } + + private static final ThreadLocal> ACTUAL_TEST_DESCS = new ThreadLocal<>() { + @Override + protected Set initialValue() { + return new HashSet<>(); + } + }; +} diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JavaAppDescTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JavaAppDescTest.java new file mode 100644 index 00000000000..a2cde44f009 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JavaAppDescTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.jpackage.test; + +import java.nio.file.Path; +import java.util.List; +import java.util.function.UnaryOperator; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameters; + +public class JavaAppDescTest { + + public JavaAppDescTest(JavaAppDesc expectedAppDesc, JavaAppDesc actualAppDesc) { + this.expectedAppDesc = expectedAppDesc; + this.actualAppDesc = actualAppDesc; + } + + @Test + public void test() { + TKit.assertEquals(expectedAppDesc.toString(), actualAppDesc.toString(), null); + TKit.assertTrue(expectedAppDesc.equals(actualAppDesc), null); + } + + @Test + @Parameter({"Foo", "Foo.class"}) + @Parameter({"com.bar.A", "com/bar/A.class"}) + @Parameter({"module/com.bar.A", "com/bar/A.class"}) + public static void testClassFilePath(String... args) { + var appDesc = args[0]; + var expectedClassFilePath = Path.of(args[1]); + TKit.assertEquals(expectedClassFilePath.toString(), JavaAppDesc.parse( + appDesc).classFilePath().toString(), null); + } + + @Parameters + public static List input() { + return List.of(new Object[][] { + createTestCase("", "hello.jar:Hello"), + createTestCase("foo.jar*", "foo.jar*hello.jar:Hello"), + createTestCase("Bye", "hello.jar:Bye"), + createTestCase("bye.jar:", "bye.jar:Hello"), + createTestCase("duke.jar:com.other/com.other.foo.bar.Buz!@3.7", appDesc -> { + return appDesc + .setBundleFileName("duke.jar") + .setModuleName("com.other") + .setClassName("com.other.foo.bar.Buz") + .setWithMainClass(true) + .setModuleVersion("3.7"); + }), + }); + } + + private static JavaAppDesc[] createTestCase(String inputAppDesc, String expectedAppDescStr) { + return createTestCase(inputAppDesc, appDesc -> { + return stripDefaultSrcJavaPath(JavaAppDesc.parse(expectedAppDescStr)); + }); + } + + private static JavaAppDesc stripDefaultSrcJavaPath(JavaAppDesc appDesc) { + var defaultAppDesc = HelloApp.createDefaltAppDesc(); + if (appDesc.srcJavaPath().equals(defaultAppDesc.srcJavaPath())) { + appDesc.setSrcJavaPath(null); + } + return appDesc; + } + + private static JavaAppDesc[] createTestCase(String appDesc, UnaryOperator config) { + var actualAppDesc = stripDefaultSrcJavaPath(JavaAppDesc.parse(appDesc)); + + var expectedAppDesc = config.apply(stripDefaultSrcJavaPath(HelloApp.createDefaltAppDesc())); + + return new JavaAppDesc[] {expectedAppDesc, actualAppDesc}; + } + + private final JavaAppDesc expectedAppDesc; + private final JavaAppDesc actualAppDesc; +} diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java new file mode 100644 index 00000000000..3f55c3c50ae --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.jpackage.test; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Functional.ThrowingRunnable; +import static jdk.jpackage.test.Functional.ThrowingRunnable.toRunnable; +import static jdk.jpackage.test.Functional.ThrowingSupplier.toSupplier; + +public class TKitTest { + + @Parameters + public static Collection assertTestsData() { + List data = new ArrayList<>(); + + var assertFunc = MethodCallConfig.build("assertTrue", boolean.class, String.class); + data.addAll(List.of(assertFunc.args(true).pass().expectLog("assertTrue()").createForMessage("Catbird"))); + data.addAll(List.of(assertFunc.args(false).fail().expectLog("Failed").createForMessage("Catbird"))); + + assertFunc = MethodCallConfig.build("assertFalse", boolean.class, String.class); + data.addAll(List.of(assertFunc.args(false).pass().expectLog("assertFalse()").createForMessage("Stork"))); + data.addAll(List.of(assertFunc.args(true).fail().expectLog("Failed").createForMessage("Stork"))); + + assertFunc = MethodCallConfig.build("assertEquals", String.class, String.class, String.class); + data.addAll(List.of(assertFunc.args("a", "a").pass().expectLog("assertEquals(a)").createForMessage("Crow"))); + data.addAll(List.of(assertFunc.args("a", "b").fail().expectLog("Expected [a]. Actual [b]").createForMessage("Crow"))); + + assertFunc = MethodCallConfig.build("assertEquals", long.class, long.class, String.class); + data.addAll(List.of(assertFunc.args(7, 7).pass().expectLog("assertEquals(7)").createForMessage("Owl"))); + data.addAll(List.of(assertFunc.args(7, 10).fail().expectLog("Expected [7]. Actual [10]").createForMessage("Owl"))); + + assertFunc = MethodCallConfig.build("assertNotEquals", String.class, String.class, String.class); + data.addAll(List.of(assertFunc.args("a", "b").pass().expectLog("assertNotEquals(a, b)").createForMessage("Tit"))); + data.addAll(List.of(assertFunc.args("a", "a").fail().expectLog("Unexpected [a] value").createForMessage("Tit"))); + + assertFunc = MethodCallConfig.build("assertNotEquals", long.class, long.class, String.class); + data.addAll(List.of(assertFunc.args(7, 10).pass().expectLog("assertNotEquals(7, 10)").createForMessage("Duck"))); + data.addAll(List.of(assertFunc.args(7, 7).fail().expectLog("Unexpected [7] value").createForMessage("Duck"))); + + assertFunc = MethodCallConfig.build("assertNull", Object.class, String.class); + data.addAll(List.of(assertFunc.args((Object) null).pass().expectLog("assertNull()").createForMessage("Ibis"))); + data.addAll(List.of(assertFunc.args("v").fail().expectLog("Unexpected not null value [v]").createForMessage("Ibis"))); + + assertFunc = MethodCallConfig.build("assertNotNull", Object.class, String.class); + data.addAll(List.of(assertFunc.args("v").pass().expectLog("assertNotNull(v)").createForMessage("Pigeon"))); + data.addAll(List.of(assertFunc.args((Object) null).fail().expectLog("Unexpected null value").createForMessage("Pigeon"))); + + assertFunc = MethodCallConfig.build("assertStringListEquals", List.class, List.class, String.class); + data.addAll(List.of(assertFunc.args(List.of(), List.of()).pass().expectLog( + "assertStringListEquals()").createForMessage("Gull"))); + + data.addAll(List.of(assertFunc.args(List.of("a", "b"), List.of("a", "b")).pass().expectLog( + "assertStringListEquals()", + "assertStringListEquals(1, a)", + "assertStringListEquals(2, b)").createForMessage("Pelican"))); + + assertFunc.fail().withAutoExpectLogPrefix(false); + for (var msg : new String[] { "Raven", null }) { + data.addAll(List.of(assertFunc.args(List.of("a"), List.of("a", "b"), msg).expectLog( + concatMessages("TRACE: assertStringListEquals()", msg), + "TRACE: assertStringListEquals(1, a)", + concatMessages("ERROR: Actual list is longer than expected by 1 elements", msg) + ).create())); + + data.addAll(List.of(assertFunc.args(List.of("n", "m"), List.of("n"), msg).expectLog( + concatMessages("TRACE: assertStringListEquals()", msg), + "TRACE: assertStringListEquals(1, n)", + concatMessages("ERROR: Actual list is shorter than expected by 1 elements", msg) + ).create())); + + data.addAll(List.of(assertFunc.args(List.of("a", "b"), List.of("n", "m"), msg).expectLog( + concatMessages("TRACE: assertStringListEquals()", msg), + concatMessages("ERROR: (1) Expected [a]. Actual [n]", msg) + ).create())); + } + + return data.stream().map(v -> { + return new Object[]{v}; + }).toList(); + } + + public record MethodCallConfig(Method method, Object[] args, boolean expectFail, String[] expectLog) { + @Override + public String toString() { + return String.format("%s%s%s", method.getName(), Arrays.toString(args), expectFail ? "!" : ""); + } + + static Builder build(String name, Class ... parameterTypes) { + return new Builder(name, parameterTypes); + } + + private static class Builder { + Builder(Method method) { + Objects.requireNonNull(method); + this.method = method; + } + + Builder(String name, Class ... parameterTypes) { + method = toSupplier(() -> TKit.class.getMethod(name, parameterTypes)).get(); + } + + MethodCallConfig create() { + String[] effectiveExpectLog; + if (!withAutoExpectLogPrefix) { + effectiveExpectLog = expectLog; + } else { + var prefix = expectFail ? "ERROR: " : "TRACE: "; + effectiveExpectLog = Stream.of(expectLog).map(line -> { + return prefix + line; + }).toArray(String[]::new); + } + return new MethodCallConfig(method, args, expectFail, effectiveExpectLog); + } + + MethodCallConfig[] createForMessage(String msg) { + return Arrays.asList(msg, null).stream().map(curMsg -> { + var builder = new Builder(method); + builder.expectFail = expectFail; + builder.withAutoExpectLogPrefix = withAutoExpectLogPrefix; + builder.args = Stream.concat(Stream.of(args), Stream.of(curMsg)).toArray(); + builder.expectLog = Arrays.copyOf(expectLog, expectLog.length); + builder.expectLog[0] = concatMessages(builder.expectLog[0], curMsg); + return builder.create(); + }).toArray(MethodCallConfig[]::new); + } + + Builder fail() { + expectFail = true; + return this; + } + + Builder pass() { + expectFail = false; + return this; + } + + Builder args(Object ... v) { + args = v; + return this; + } + + Builder expectLog(String expectLogFirstStr, String ... extra) { + expectLog = Stream.concat(Stream.of(expectLogFirstStr), Stream.of(extra)).toArray(String[]::new); + return this; + } + + Builder withAutoExpectLogPrefix(boolean v) { + withAutoExpectLogPrefix = v; + return this; + } + + private final Method method; + private Object[] args = new Object[0]; + private boolean expectFail; + private String[] expectLog; + private boolean withAutoExpectLogPrefix = true; + } + } + + public TKitTest(MethodCallConfig methodCall) { + this.methodCall = methodCall; + } + + @Test + public void test() { + runAssertWithExpectedLogOutput(() -> { + methodCall.method.invoke(null, methodCall.args); + }, methodCall.expectFail, methodCall.expectLog); + } + + private static void runAssertWithExpectedLogOutput(ThrowingRunnable action, + boolean expectFail, String... expectLogStrings) { + runWithExpectedLogOutput(() -> { + TKit.assertAssert(!expectFail, toRunnable(action)); + }, expectLogStrings); + } + + private static void runWithExpectedLogOutput(ThrowingRunnable action, + String... expectLogStrings) { + final var buf = new ByteArrayOutputStream(); + try (PrintStream ps = new PrintStream(buf, true, StandardCharsets.UTF_8)) { + TKit.withExtraLogStream(action, ps); + } finally { + toRunnable(() -> { + var output = new BufferedReader(new InputStreamReader( + new ByteArrayInputStream(buf.toByteArray()), + StandardCharsets.UTF_8)).lines().map(line -> { + // Skip timestamp + return line.substring(LOG_MSG_TIMESTAMP_LENGTH); + }).toList(); + if (output.size() == 1 && expectLogStrings.length == 1) { + TKit.assertEquals(expectLogStrings[0], output.get(0), null); + } else { + TKit.assertStringListEquals(List.of(expectLogStrings), output, null); + } + }).run(); + } + } + + private static String concatMessages(String msg, String msg2) { + if (msg2 != null && !msg2.isBlank()) { + return msg + ": " + msg2; + } + return msg; + } + + private final MethodCallConfig methodCall; + + private static final int LOG_MSG_TIMESTAMP_LENGTH = "[HH:mm:ss.SSS] ".length(); +} diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TestSuite.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TestSuite.java new file mode 100644 index 00000000000..f9dda851414 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TestSuite.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.jpackage.test; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +/* + * @test + * @summary Unit tests for jpackage test library + * @library /test/jdk/tools/jpackage/helpers + * @library /test/jdk/tools/jpackage/helpers-test + * @build jdk.jpackage.test.* + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.TestSuite + */ + +public final class TestSuite { + public static void main(String args[]) throws Throwable { + final var pkgName = TestSuite.class.getPackageName(); + final var javaSuffix = ".java"; + final var testSrcNameSuffix = "Test" + javaSuffix; + + final var unitTestDir = TKit.TEST_SRC_ROOT.resolve(Path.of("helpers-test", pkgName.split("\\."))); + + final List runTestArgs = new ArrayList<>(); + runTestArgs.addAll(List.of(args)); + + try (var javaSources = Files.list(unitTestDir)) { + runTestArgs.addAll(javaSources.filter(path -> { + return path.getFileName().toString().endsWith(testSrcNameSuffix); + }).map(path -> { + var filename = path.getFileName().toString(); + return String.join(".", pkgName, filename.substring(0, filename.length() - javaSuffix.length())); + }).map(testClassName -> { + return "--jpt-run=" + testClassName; + }).toList()); + } + + Main.main(runTestArgs.toArray(String[]::new)); + } +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Annotations.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Annotations.java index d29133ee3e1..ad1e77b4171 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Annotations.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Annotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jdk.internal.util.OperatingSystem; public class Annotations { @@ -43,6 +44,14 @@ public class Annotations { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test { + + OperatingSystem[] ifOS() default { + OperatingSystem.LINUX, + OperatingSystem.WINDOWS, + OperatingSystem.MACOS + }; + + OperatingSystem[] ifNotOS() default {}; } @Retention(RetentionPolicy.RUNTIME) @@ -51,6 +60,14 @@ public class Annotations { public @interface Parameter { String[] value(); + + OperatingSystem[] ifOS() default { + OperatingSystem.LINUX, + OperatingSystem.WINDOWS, + OperatingSystem.MACOS + }; + + OperatingSystem[] ifNotOS() default {}; } @Retention(RetentionPolicy.RUNTIME) @@ -60,8 +77,39 @@ public class Annotations { Parameter[] value(); } + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + @Repeatable(ParameterSupplierGroup.class) + public @interface ParameterSupplier { + + String value(); + + OperatingSystem[] ifOS() default { + OperatingSystem.LINUX, + OperatingSystem.WINDOWS, + OperatingSystem.MACOS + }; + + OperatingSystem[] ifNotOS() default {}; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface ParameterSupplierGroup { + + ParameterSupplier[] value(); + } + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Parameters { + + OperatingSystem[] ifOS() default { + OperatingSystem.LINUX, + OperatingSystem.WINDOWS, + OperatingSystem.MACOS + }; + + OperatingSystem[] ifNotOS() default {}; } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index 4afd96cdf88..e94cbc79aac 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -36,6 +36,7 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.Supplier; import java.util.regex.Pattern; @@ -77,6 +78,10 @@ public Executor setToolProvider(JavaTool v) { return setToolProvider(v.asToolProvider()); } + public Optional getExecutable() { + return Optional.ofNullable(executable); + } + public Executor setDirectory(Path v) { directory = v; return this; @@ -174,10 +179,10 @@ public Executor dumpOutput(boolean v) { return this; } - public class Result { + public record Result(int exitCode, List output, Supplier cmdline) { - Result(int exitCode) { - this.exitCode = exitCode; + public Result { + Objects.requireNonNull(cmdline); } public String getFirstLineOfOutput() { @@ -188,14 +193,10 @@ public List getOutput() { return output; } - public String getPrintableCommandLine() { - return Executor.this.getPrintableCommandLine(); - } - public Result assertExitCodeIs(int expectedExitCode) { TKit.assertEquals(expectedExitCode, exitCode, String.format( "Check command %s exited with %d code", - getPrintableCommandLine(), expectedExitCode)); + cmdline.get(), expectedExitCode)); return this; } @@ -206,9 +207,6 @@ public Result assertExitCodeIsZero() { public int getExitCode() { return exitCode; } - - final int exitCode; - private List output; } public Result executeWithoutExitCodeCheck() { @@ -406,28 +404,34 @@ private Result runExecutable() throws IOException, InterruptedException { } } - Result reply = new Result(process.waitFor()); - trace("Done. Exit code: " + reply.exitCode); + final int exitCode = process.waitFor(); + trace("Done. Exit code: " + exitCode); + final List output; if (outputLines != null) { - reply.output = Collections.unmodifiableList(outputLines); + output = Collections.unmodifiableList(outputLines); + } else { + output = null; } - return reply; + return createResult(exitCode, output); } - private Result runToolProvider(PrintStream out, PrintStream err) { + private int runToolProvider(PrintStream out, PrintStream err) { trace("Execute " + getPrintableCommandLine() + "..."); - Result reply = new Result(toolProvider.run(out, err, args.toArray( - String[]::new))); - trace("Done. Exit code: " + reply.exitCode); - return reply; + final int exitCode = toolProvider.run(out, err, args.toArray( + String[]::new)); + trace("Done. Exit code: " + exitCode); + return exitCode; } + private Result createResult(int exitCode, List output) { + return new Result(exitCode, output, this::getPrintableCommandLine); + } private Result runToolProvider() throws IOException { if (!withSavedOutput()) { if (saveOutputType.contains(SaveOutputType.DUMP)) { - return runToolProvider(System.out, System.err); + return createResult(runToolProvider(System.out, System.err), null); } PrintStream nullPrintStream = new PrintStream(new OutputStream() { @@ -436,36 +440,40 @@ public void write(int b) { // Nop } }); - return runToolProvider(nullPrintStream, nullPrintStream); + return createResult(runToolProvider(nullPrintStream, nullPrintStream), null); } try (ByteArrayOutputStream buf = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(buf)) { - Result reply = runToolProvider(ps, ps); + final var exitCode = runToolProvider(ps, ps); ps.flush(); + final List output; try (BufferedReader bufReader = new BufferedReader(new StringReader( buf.toString()))) { if (saveOutputType.contains(SaveOutputType.FIRST_LINE)) { String firstLine = bufReader.lines().findFirst().orElse(null); if (firstLine != null) { - reply.output = List.of(firstLine); + output = List.of(firstLine); + } else { + output = null; } } else if (saveOutputType.contains(SaveOutputType.FULL)) { - reply.output = bufReader.lines().collect( - Collectors.toUnmodifiableList()); + output = bufReader.lines().collect(Collectors.toUnmodifiableList()); + } else { + output = null; } if (saveOutputType.contains(SaveOutputType.DUMP)) { Stream lines; if (saveOutputType.contains(SaveOutputType.FULL)) { - lines = reply.output.stream(); + lines = output.stream(); } else { lines = bufReader.lines(); } lines.forEach(System.out::println); } } - return reply; + return createResult(exitCode, output); } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Functional.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Functional.java index 87718c1394c..a57caa92cb2 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Functional.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Functional.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -151,12 +151,16 @@ public ExceptionBox(Throwable throwable) { @SuppressWarnings("unchecked") public static RuntimeException rethrowUnchecked(Throwable throwable) throws ExceptionBox { - if (throwable instanceof RuntimeException) { - throw (RuntimeException)throwable; + if (throwable instanceof RuntimeException err) { + throw err; } - if (throwable instanceof InvocationTargetException) { - throw new ExceptionBox(throwable.getCause()); + if (throwable instanceof Error err) { + throw err; + } + + if (throwable instanceof InvocationTargetException err) { + throw rethrowUnchecked(err.getCause()); } throw new ExceptionBox(throwable); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java index 3bd3b42d595..bc722e7acd9 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java @@ -22,7 +22,6 @@ */ package jdk.jpackage.test; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -57,15 +56,10 @@ public final class HelloApp { private JarBuilder prepareSources(Path srcDir) throws IOException { final String srcClassName = appDesc.srcClassName(); - - final String qualifiedClassName = appDesc.className(); - - final String className = qualifiedClassName.substring( - qualifiedClassName.lastIndexOf('.') + 1); + final String className = appDesc.shortClassName(); final String packageName = appDesc.packageName(); - final Path srcFile = srcDir.resolve(Path.of(String.join( - File.separator, qualifiedClassName.split("\\.")) + ".java")); + final Path srcFile = srcDir.resolve(appDesc.classNameAsPath(".java")); Files.createDirectories(srcFile.getParent()); JarBuilder jarBuilder = createJarBuilder().addSourceFile(srcFile); @@ -351,7 +345,7 @@ public static AppOutputVerifier assertMainLauncher(JPackageCommand cmd, } - public final static class AppOutputVerifier { + public static final class AppOutputVerifier { AppOutputVerifier(Path helloAppLauncher) { this.launcherPath = helloAppLauncher; this.outputFilePath = TKit.workDir().resolve(OUTPUT_FILENAME); @@ -493,13 +487,13 @@ public static AppOutputVerifier assertApp(Path helloAppLauncher) { return new AppOutputVerifier(helloAppLauncher); } - final static String OUTPUT_FILENAME = "appOutput.txt"; + static final String OUTPUT_FILENAME = "appOutput.txt"; private final JavaAppDesc appDesc; private static final Path HELLO_JAVA = TKit.TEST_SRC_ROOT.resolve( "apps/Hello.java"); - private final static String CLASS_NAME = HELLO_JAVA.getFileName().toString().split( + private static final String CLASS_NAME = HELLO_JAVA.getFileName().toString().split( "\\.", 2)[0]; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index fd62d6c7d88..28bdc483afd 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -59,7 +59,7 @@ * anything. The simplest is to compile test application and pack in a jar for * use on jpackage command line. */ -public final class JPackageCommand extends CommandArguments { +public class JPackageCommand extends CommandArguments { public JPackageCommand() { prerequisiteActions = new Actions(); @@ -791,7 +791,7 @@ public Executor.Result execute(int expectedExitCode) { .createExecutor() .execute(expectedExitCode); - if (result.exitCode == 0) { + if (result.exitCode() == 0) { executeVerifyActions(); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaAppDesc.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaAppDesc.java index 6a798012ca7..c0807deef3b 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaAppDesc.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaAppDesc.java @@ -22,8 +22,9 @@ */ package jdk.jpackage.test; -import java.io.File; import java.nio.file.Path; +import java.util.Objects; +import java.util.stream.Stream; public final class JavaAppDesc { @@ -73,9 +74,18 @@ public String className() { return qualifiedClassName; } + public String shortClassName() { + return qualifiedClassName.substring(qualifiedClassName.lastIndexOf('.') + 1); + } + + Path classNameAsPath(String extension) { + final String[] pathComponents = qualifiedClassName.split("\\."); + pathComponents[pathComponents.length - 1] = shortClassName() + extension; + return Stream.of(pathComponents).map(Path::of).reduce(Path::resolve).get(); + } + public Path classFilePath() { - return Path.of(qualifiedClassName.replace(".", File.separator) - + ".class"); + return classNameAsPath(".class"); } public String moduleName() { @@ -124,6 +134,48 @@ public boolean isWithMainClass() { return withMainClass; } + @Override + public int hashCode() { + int hash = 5; + hash = 79 * hash + Objects.hashCode(this.srcJavaPath); + hash = 79 * hash + Objects.hashCode(this.qualifiedClassName); + hash = 79 * hash + Objects.hashCode(this.moduleName); + hash = 79 * hash + Objects.hashCode(this.bundleFileName); + hash = 79 * hash + Objects.hashCode(this.moduleVersion); + hash = 79 * hash + (this.withMainClass ? 1 : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final JavaAppDesc other = (JavaAppDesc) obj; + if (this.withMainClass != other.withMainClass) { + return false; + } + if (!Objects.equals(this.qualifiedClassName, other.qualifiedClassName)) { + return false; + } + if (!Objects.equals(this.moduleName, other.moduleName)) { + return false; + } + if (!Objects.equals(this.bundleFileName, other.bundleFileName)) { + return false; + } + if (!Objects.equals(this.moduleVersion, other.moduleVersion)) { + return false; + } + return Objects.equals(this.srcJavaPath, other.srcJavaPath); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -216,7 +268,9 @@ public static JavaAppDesc parse(final String javaAppDesc) { components[0].length() - 1); desc.setWithMainClass(true); } - desc.setClassName(components[0]); + if (!components[0].isEmpty()) { + desc.setClassName(components[0]); + } if (components.length == 2) { desc.setModuleVersion(components[1]); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index 44212587f7d..e779cef8bfc 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.jpackage.internal.ApplicationLayout; import jdk.jpackage.internal.IOUtils; import jdk.jpackage.test.Functional.ThrowingConsumer; import jdk.jpackage.test.PackageTest.PackageHandlers; @@ -399,6 +400,15 @@ static void addBundleDesktopIntegrationVerifier(PackageTest test, private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile) throws IOException { TKit.trace(String.format("Check [%s] file BEGIN", desktopFile)); + + var launcherName = Stream.of(List.of(cmd.name()), cmd.addLauncherNames()).flatMap(List::stream).filter(name -> { + return getDesktopFile(cmd, name).equals(desktopFile); + }).findAny(); + if (!cmd.hasArgument("--app-image")) { + TKit.assertTrue(launcherName.isPresent(), + "Check the desktop file corresponds to one of app launchers"); + } + List lines = Files.readAllLines(desktopFile); TKit.assertEquals("[Desktop Entry]", lines.get(0), "Check file header"); @@ -428,7 +438,7 @@ private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile) "Check value of [%s] key", key)); } - // Verify value of `Exec` property in .desktop files are escaped if required + // Verify the value of `Exec` key is escaped if required String launcherPath = data.get("Exec"); if (Pattern.compile("\\s").matcher(launcherPath).find()) { TKit.assertTrue(launcherPath.startsWith("\"") @@ -437,10 +447,25 @@ private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile) launcherPath = launcherPath.substring(1, launcherPath.length() - 1); } - Stream.of(launcherPath, data.get("Icon")) - .map(Path::of) - .map(cmd::pathToUnpackedPackageFile) - .forEach(TKit::assertFileExists); + if (launcherName.isPresent()) { + TKit.assertEquals(launcherPath, cmd.pathToPackageFile( + cmd.appLauncherPath(launcherName.get())).toString(), + String.format( + "Check the value of [Exec] key references [%s] app launcher", + launcherName.get())); + } + + for (var e : List.>, Function>>of( + Map.entry(Map.entry("Exec", Optional.of(launcherPath)), ApplicationLayout::launchersDirectory), + Map.entry(Map.entry("Icon", Optional.empty()), ApplicationLayout::destktopIntegrationDirectory))) { + var path = e.getKey().getValue().or(() -> Optional.of(data.get( + e.getKey().getKey()))).map(Path::of).get(); + TKit.assertFileExists(cmd.pathToUnpackedPackageFile(path)); + Path expectedDir = cmd.pathToPackageFile(e.getValue().apply(cmd.appLayout())); + TKit.assertTrue(path.getParent().equals(expectedDir), String.format( + "Check the value of [%s] key references a file in [%s] folder", + e.getKey().getKey(), expectedDir)); + } TKit.trace(String.format("Check [%s] file END", desktopFile)); } @@ -720,10 +745,10 @@ private static Method initGetServiceUnitFileName() { private static Map archs; - private final static Pattern XDG_CMD_ICON_SIZE_PATTERN = Pattern.compile("\\s--size\\s+(\\d+)\\b"); + private static final Pattern XDG_CMD_ICON_SIZE_PATTERN = Pattern.compile("\\s--size\\s+(\\d+)\\b"); // Values grabbed from https://linux.die.net/man/1/xdg-icon-resource - private final static Set XDG_CMD_VALID_ICON_SIZES = Set.of(16, 22, 32, 48, 64, 128); + private static final Set XDG_CMD_VALID_ICON_SIZES = Set.of(16, 22, 32, 48, 64, 128); - private final static Method getServiceUnitFileName = initGetServiceUnitFileName(); + private static final Method getServiceUnitFileName = initGetServiceUnitFileName(); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java index 37aca48ac17..5919d8361c4 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * 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,17 @@ package jdk.jpackage.test; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Comparator; +import java.util.Deque; import java.util.List; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; +import static java.util.stream.Collectors.toCollection; +import java.util.stream.Stream; import static jdk.jpackage.test.TestBuilder.CMDLINE_ARG_PREFIX; @@ -36,7 +42,9 @@ public static void main(String args[]) throws Throwable { boolean listTests = false; List tests = new ArrayList<>(); try (TestBuilder testBuilder = new TestBuilder(tests::add)) { - for (var arg : args) { + Deque argsAsList = new ArrayDeque<>(List.of(args)); + while (!argsAsList.isEmpty()) { + var arg = argsAsList.pop(); TestBuilder.trace(String.format("Parsing [%s]...", arg)); if ((CMDLINE_ARG_PREFIX + "list").equals(arg)) { @@ -44,6 +52,29 @@ public static void main(String args[]) throws Throwable { continue; } + if (arg.startsWith("@")) { + // Command file + // @=args will read arguments from the "args" file, one argument per line + // @args will read arguments from the "args" file, splitting lines into arguments at whitespaces + arg = arg.substring(1); + var oneArgPerLine = arg.startsWith("="); + if (oneArgPerLine) { + arg = arg.substring(1); + } + + var newArgsStream = Files.readAllLines(Path.of(arg)).stream(); + if (!oneArgPerLine) { + newArgsStream.map(line -> { + return Stream.of(line.split("\\s+")); + }).flatMap(x -> x); + } + + var newArgs = newArgsStream.collect(toCollection(ArrayDeque::new)); + newArgs.addAll(argsAsList); + argsAsList = newArgs; + continue; + } + boolean success = false; try { testBuilder.processCmdLineArg(arg); @@ -62,12 +93,11 @@ public static void main(String args[]) throws Throwable { // Order tests by their full names to have stable test sequence. List orderedTests = tests.stream() - .sorted((a, b) -> a.fullName().compareTo(b.fullName())) - .collect(Collectors.toList()); + .sorted(Comparator.comparing(TestInstance::fullName)).toList(); if (listTests) { // Just list the tests - orderedTests.stream().forEach(test -> System.out.println(String.format( + orderedTests.forEach(test -> System.out.println(String.format( "%s; workDir=[%s]", test.fullName(), test.workDir()))); return; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java index 2aaba054a9b..d5b8bd702c8 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * 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,34 +22,33 @@ */ package jdk.jpackage.test; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; -import java.util.List; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Collectors; +import java.util.function.Predicate; +import java.util.stream.IntStream; import java.util.stream.Stream; import jdk.jpackage.test.Functional.ThrowingConsumer; import jdk.jpackage.test.TestInstance.TestDesc; class MethodCall implements ThrowingConsumer { - MethodCall(Object[] instanceCtorArgs, Method method) { - this.ctorArgs = Optional.ofNullable(instanceCtorArgs).orElse( - DEFAULT_CTOR_ARGS); - this.method = method; - this.methodArgs = new Object[0]; - } + MethodCall(Object[] instanceCtorArgs, Method method, Object ... args) { + Objects.requireNonNull(instanceCtorArgs); + Objects.requireNonNull(method); - MethodCall(Object[] instanceCtorArgs, Method method, Object arg) { - this.ctorArgs = Optional.ofNullable(instanceCtorArgs).orElse( - DEFAULT_CTOR_ARGS); + this.ctorArgs = instanceCtorArgs; this.method = method; - this.methodArgs = new Object[]{arg}; + this.methodArgs = args; } TestDesc createDescription() { @@ -76,78 +75,195 @@ Object newInstance() throws NoSuchMethodException, InstantiationException, return null; } - Constructor ctor = findRequiredConstructor(method.getDeclaringClass(), - ctorArgs); - if (ctor.isVarArgs()) { - // Assume constructor doesn't have fixed, only variable parameters. - return ctor.newInstance(new Object[]{ctorArgs}); - } + var ctor = findMatchingConstructor(method.getDeclaringClass(), ctorArgs); - return ctor.newInstance(ctorArgs); + return ctor.newInstance(mapArgs(ctor, ctorArgs)); + } + + static Object[] mapArgs(Executable executable, final Object ... args) { + return mapPrimitiveTypeArgs(executable, mapVarArgs(executable, args)); } void checkRequiredConstructor() throws NoSuchMethodException { if ((method.getModifiers() & Modifier.STATIC) == 0) { - findRequiredConstructor(method.getDeclaringClass(), ctorArgs); + findMatchingConstructor(method.getDeclaringClass(), ctorArgs); } } - private static Constructor findVarArgConstructor(Class type) { - return Stream.of(type.getConstructors()).filter( - Constructor::isVarArgs).findFirst().orElse(null); - } - - private Constructor findRequiredConstructor(Class type, Object... ctorArgs) + private static Constructor findMatchingConstructor(Class type, Object... ctorArgs) throws NoSuchMethodException { - Supplier notFoundException = () -> { - return new NoSuchMethodException(String.format( + var ctors = filterMatchingExecutablesForParameterValues(Stream.of( + type.getConstructors()), ctorArgs).toList(); + + if (ctors.size() != 1) { + // No public constructors that can handle the given arguments. + throw new NoSuchMethodException(String.format( "No public contructor in %s for %s arguments", type, Arrays.deepToString(ctorArgs))); - }; - - if (Stream.of(ctorArgs).allMatch(Objects::nonNull)) { - // No `null` in constructor args, take easy path - try { - return type.getConstructor(Stream.of(ctorArgs).map( - Object::getClass).collect(Collectors.toList()).toArray( - Class[]::new)); - } catch (NoSuchMethodException ex) { - // Failed to find ctor that can take the given arguments. - Constructor varArgCtor = findVarArgConstructor(type); - if (varArgCtor != null) { - // There is one with variable number of arguments. Use it. - return varArgCtor; - } - throw notFoundException.get(); + } + + return ctors.get(0); + } + + @Override + public void accept(Object thiz) throws Throwable { + method.invoke(thiz, methodArgs); + } + + private static Object[] mapVarArgs(Executable executable, final Object ... args) { + if (executable.isVarArgs()) { + var paramTypes = executable.getParameterTypes(); + Class varArgParamType = paramTypes[paramTypes.length - 1]; + + Object[] newArgs; + if (paramTypes.length - args.length == 1) { + // Empty var args + + // "args" can be of type String[] if the "executable" is "foo(String ... str)" + newArgs = Arrays.copyOf(args, args.length + 1, Object[].class); + newArgs[newArgs.length - 1] = Array.newInstance(varArgParamType.componentType(), 0); + } else { + var varArgs = Arrays.copyOfRange(args, paramTypes.length - 1, + args.length, varArgParamType); + + // "args" can be of type String[] if the "executable" is "foo(String ... str)" + newArgs = Arrays.copyOfRange(args, 0, paramTypes.length, Object[].class); + newArgs[newArgs.length - 1] = varArgs; } + return newArgs; } - List ctors = Stream.of(type.getConstructors()) - .filter(ctor -> ctor.getParameterCount() == ctorArgs.length) - .collect(Collectors.toList()); + return args; + } - if (ctors.isEmpty()) { - // No public constructors that can handle the given arguments. - throw notFoundException.get(); + private static Object[] mapPrimitiveTypeArgs(Executable executable, final Object ... args) { + var paramTypes = executable.getParameterTypes(); + if (paramTypes.length != args.length) { + throw new IllegalArgumentException( + "The number of arguments must be equal to the number of parameters of the executable"); } - if (ctors.size() == 1) { - return ctors.iterator().next(); + if (IntStream.range(0, args.length).allMatch(idx -> { + return Optional.ofNullable(args[idx]).map(Object::getClass).map(paramTypes[idx]::isAssignableFrom).orElse(true); + })) { + return args; + } else { + final var newArgs = Arrays.copyOf(args, args.length, Object[].class); + for (var idx = 0; idx != args.length; ++idx) { + final var paramType = paramTypes[idx]; + final var argValue = args[idx]; + newArgs[idx] = Optional.ofNullable(argValue).map(Object::getClass).map(argType -> { + if(argType.isArray() && !paramType.isAssignableFrom(argType)) { + var length = Array.getLength(argValue); + var newArray = Array.newInstance(paramType.getComponentType(), length); + for (var arrayIdx = 0; arrayIdx != length; ++arrayIdx) { + Array.set(newArray, arrayIdx, Array.get(argValue, arrayIdx)); + } + return newArray; + } else { + return argValue; + } + }).orElse(argValue); + } + + return newArgs; } + } - // Revisit this tricky case when it will start bothering. - throw notFoundException.get(); + private static Stream filterMatchingExecutablesForParameterValues( + Stream executables, Object... args) { + return filterMatchingExecutablesForParameterTypes( + executables, + Stream.of(args) + .map(arg -> arg != null ? arg.getClass() : null) + .toArray(Class[]::new)); } - @Override - public void accept(Object thiz) throws Throwable { - method.invoke(thiz, methodArgs); + private static Stream filterMatchingExecutablesForParameterTypes( + Stream executables, Class... argTypes) { + return executables.filter(executable -> { + var parameterTypes = executable.getParameterTypes(); + + final int checkArgTypeCount; + if (parameterTypes.length <= argTypes.length) { + checkArgTypeCount = parameterTypes.length; + } else if (parameterTypes.length - argTypes.length == 1 && executable.isVarArgs()) { + // Empty optional arguments. + checkArgTypeCount = argTypes.length; + } else { + // Not enough mandatory arguments. + return false; + } + + var unmatched = IntStream.range(0, checkArgTypeCount).dropWhile(idx -> { + return new ParameterTypeMatcher(parameterTypes[idx]).test(argTypes[idx]); + }).toArray(); + + if (argTypes.length == parameterTypes.length && unmatched.length == 0) { + // Number of argument types equals to the number of parameters + // of the executable and all types match. + return true; + } + + if (executable.isVarArgs()) { + var varArgType = parameterTypes[parameterTypes.length - 1].componentType(); + return IntStream.of(unmatched).allMatch(idx -> { + return new ParameterTypeMatcher(varArgType).test(argTypes[idx]); + }); + } + + return false; + }); + } + + private static final class ParameterTypeMatcher implements Predicate> { + ParameterTypeMatcher(Class parameterType) { + Objects.requireNonNull(parameterType); + this.parameterType = NORM_TYPES.getOrDefault(parameterType, parameterType); + } + + @Override + public boolean test(Class paramaterValueType) { + if (paramaterValueType == null) { + return true; + } + + paramaterValueType = NORM_TYPES.getOrDefault(paramaterValueType, paramaterValueType); + return parameterType.isAssignableFrom(paramaterValueType); + } + + private final Class parameterType; } private final Object[] methodArgs; private final Method method; private final Object[] ctorArgs; - final static Object[] DEFAULT_CTOR_ARGS = new Object[0]; + private static final Map, Class> NORM_TYPES; + + static { + Map, Class> primitives = Map.of( + boolean.class, Boolean.class, + byte.class, Byte.class, + short.class, Short.class, + int.class, Integer.class, + long.class, Long.class, + float.class, Float.class, + double.class, Double.class); + + Map, Class> primitiveArrays = Map.of( + boolean[].class, Boolean[].class, + byte[].class, Byte[].class, + short[].class, Short[].class, + int[].class, Integer[].class, + long[].class, Long[].class, + float[].class, Float[].class, + double[].class, Double[].class); + + Map, Class> combined = new HashMap<>(primitives); + combined.putAll(primitiveArrays); + + NORM_TYPES = Collections.unmodifiableMap(combined); + } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java index d597c62d83f..d8930745847 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -22,9 +22,7 @@ */ package jdk.jpackage.test; -import java.awt.Desktop; import java.awt.GraphicsEnvironment; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -778,7 +776,7 @@ private static Map createDefaultPackageHandlers() private Set namedInitializers; private Map packageHandlers; - private final static File BUNDLE_OUTPUT_DIR; + private static final Path BUNDLE_OUTPUT_DIR; static { final String propertyName = "output"; @@ -786,9 +784,9 @@ private static Map createDefaultPackageHandlers() if (val == null) { BUNDLE_OUTPUT_DIR = null; } else { - BUNDLE_OUTPUT_DIR = new File(val).getAbsoluteFile(); + BUNDLE_OUTPUT_DIR = Path.of(val).toAbsolutePath(); - if (!BUNDLE_OUTPUT_DIR.isDirectory()) { + if (!Files.isDirectory(BUNDLE_OUTPUT_DIR)) { throw new IllegalArgumentException(String.format("Invalid value of %s sytem property: [%s]. Should be existing directory", TKit.getConfigPropertyName(propertyName), BUNDLE_OUTPUT_DIR)); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index 04d2bff94b1..d9b97165cce 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -23,7 +23,6 @@ package jdk.jpackage.test; import java.io.Closeable; -import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; @@ -107,14 +106,21 @@ static void withExtraLogStream(ThrowingRunnable action) { ThrowingRunnable.toRunnable(action).run(); } else { try (PrintStream logStream = openLogStream()) { - extraLogStream = logStream; - ThrowingRunnable.toRunnable(action).run(); - } finally { - extraLogStream = null; + withExtraLogStream(action, logStream); } } } + static void withExtraLogStream(ThrowingRunnable action, PrintStream logStream) { + var oldExtraLogStream = extraLogStream; + try { + extraLogStream = logStream; + ThrowingRunnable.toRunnable(action).run(); + } finally { + extraLogStream = oldExtraLogStream; + } + } + static void runTests(List tests) { if (currentTest != null) { throw new IllegalStateException( @@ -187,11 +193,7 @@ public static boolean isLinux() { } public static boolean isLinuxAPT() { - if (!isLinux()) { - return false; - } - File aptFile = new File("/usr/bin/apt-get"); - return aptFile.exists(); + return isLinux() && Files.exists(Path.of("/usr/bin/apt-get")); } private static String addTimestamp(String msg) { @@ -275,6 +277,22 @@ public static void error(String v) { throw new AssertionError(v); } + static void assertAssert(boolean expectedSuccess, Runnable runnable) { + try { + runnable.run(); + } catch (AssertionError err) { + if (expectedSuccess) { + assertUnexpected("Assertion failed"); + } else { + return; + } + } + + if (!expectedSuccess) { + assertUnexpected("Assertion passed"); + } + } + private final static String TEMP_FILE_PREFIX = null; private static Path createUniqueFileName(String defaultName) { @@ -580,7 +598,7 @@ public static void assertEquals(long expected, long actual, String msg) { msg)); } - traceAssert(String.format("assertEquals(%d): %s", expected, msg)); + traceAssert(concatMessages(String.format("assertEquals(%d)", expected), msg)); } public static void assertNotEquals(long expected, long actual, String msg) { @@ -590,8 +608,8 @@ public static void assertNotEquals(long expected, long actual, String msg) { msg)); } - traceAssert(String.format("assertNotEquals(%d, %d): %s", expected, - actual, msg)); + traceAssert(concatMessages(String.format("assertNotEquals(%d, %d)", expected, + actual), msg)); } public static void assertEquals(String expected, String actual, String msg) { @@ -603,7 +621,7 @@ public static void assertEquals(String expected, String actual, String msg) { msg)); } - traceAssert(String.format("assertEquals(%s): %s", expected, msg)); + traceAssert(concatMessages(String.format("assertEquals(%s)", expected), msg)); } public static void assertNotEquals(String expected, String actual, String msg) { @@ -611,8 +629,8 @@ public static void assertNotEquals(String expected, String actual, String msg) { if ((actual != null && !actual.equals(expected)) || (expected != null && !expected.equals(actual))) { - traceAssert(String.format("assertNotEquals(%s, %s): %s", expected, - actual, msg)); + traceAssert(concatMessages(String.format("assertNotEquals(%s, %s)", expected, + actual), msg)); return; } @@ -626,7 +644,7 @@ public static void assertNull(Object value, String msg) { value), msg)); } - traceAssert(String.format("assertNull(): %s", msg)); + traceAssert(concatMessages("assertNull()", msg)); } public static void assertNotNull(Object value, String msg) { @@ -635,7 +653,7 @@ public static void assertNotNull(Object value, String msg) { error(concatMessages("Unexpected null value", msg)); } - traceAssert(String.format("assertNotNull(%s): %s", value, msg)); + traceAssert(concatMessages(String.format("assertNotNull(%s)", value), msg)); } public static void assertTrue(boolean actual, String msg) { @@ -655,7 +673,7 @@ public static void assertTrue(boolean actual, String msg, Runnable onFail) { error(concatMessages("Failed", msg)); } - traceAssert(String.format("assertTrue(): %s", msg)); + traceAssert(concatMessages("assertTrue()", msg)); } public static void assertFalse(boolean actual, String msg, Runnable onFail) { @@ -667,7 +685,7 @@ public static void assertFalse(boolean actual, String msg, Runnable onFail) { error(concatMessages("Failed", msg)); } - traceAssert(String.format("assertFalse(): %s", msg)); + traceAssert(concatMessages("assertFalse()", msg)); } public static void assertPathExists(Path path, boolean exists) { @@ -826,7 +844,7 @@ public static void assertStringListEquals(List expected, List actual, String msg) { currentTest.notifyAssert(); - traceAssert(String.format("assertStringListEquals(): %s", msg)); + traceAssert(concatMessages("assertStringListEquals()", msg)); String idxFieldFormat = Functional.identity(() -> { int listSize = expected.size(); @@ -856,7 +874,7 @@ public static void assertStringListEquals(List expected, expectedStr)); }); - if (expected.size() < actual.size()) { + if (actual.size() > expected.size()) { // Actual string list is longer than expected error(concatMessages(String.format( "Actual list is longer than expected by %d elements", @@ -866,7 +884,7 @@ public static void assertStringListEquals(List expected, if (actual.size() < expected.size()) { // Actual string list is shorter than expected error(concatMessages(String.format( - "Actual list is longer than expected by %d elements", + "Actual list is shorter than expected by %d elements", expected.size() - actual.size()), msg)); } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java index bb699ba3b9c..c2fc1789a25 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * 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,32 +23,28 @@ package jdk.jpackage.test; -import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Collection; +import java.util.Comparator; 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.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import java.util.function.Function; import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.test.Annotations.AfterEach; import jdk.jpackage.test.Annotations.BeforeEach; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.ParameterGroup; -import jdk.jpackage.test.Annotations.Parameters; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.Functional.ThrowingConsumer; +import static jdk.jpackage.test.Functional.ThrowingConsumer.toConsumer; import jdk.jpackage.test.Functional.ThrowingFunction; +import jdk.jpackage.test.TestMethodSupplier.InvalidAnnotationException; +import static jdk.jpackage.test.TestMethodSupplier.MethodQuery.fromQualifiedMethodName; final class TestBuilder implements AutoCloseable { @@ -58,6 +54,7 @@ public void close() throws Exception { } TestBuilder(Consumer testConsumer) { + this.testMethodSupplier = TestBuilderConfig.getDefault().createTestMethodSupplier(); argProcessors = Map.of( CMDLINE_ARG_PREFIX + "after-run", arg -> getJavaMethodsFromArg(arg).map( @@ -70,7 +67,7 @@ public void close() throws Exception { CMDLINE_ARG_PREFIX + "run", arg -> addTestGroup(getJavaMethodsFromArg(arg).map( ThrowingFunction.toFunction( - TestBuilder::toMethodCalls)).flatMap(s -> s).collect( + this::toMethodCalls)).flatMap(s -> s).collect( Collectors.toList())), CMDLINE_ARG_PREFIX + "exclude", @@ -219,23 +216,29 @@ private static Stream selectFrameMethods(Class type, Class annotationTyp .filter(m -> m.getParameterCount() == 0) .filter(m -> !m.isAnnotationPresent(Test.class)) .filter(m -> m.isAnnotationPresent(annotationType)) - .sorted((a, b) -> a.getName().compareTo(b.getName())); + .sorted(Comparator.comparing(Method::getName)); } - private static Stream cmdLineArgValueToMethodNames(String v) { + private Stream cmdLineArgValueToMethodNames(String v) { List result = new ArrayList<>(); String defaultClassName = null; for (String token : v.split(",")) { Class testSet = probeClass(token); if (testSet != null) { + if (testMethodSupplier.isTestClass(testSet)) { + toConsumer(testMethodSupplier::verifyTestClass).accept(testSet); + } + // Test set class specified. Pull in all public methods // from the class with @Test annotation removing name duplicates. // Overloads will be handled at the next phase of processing. defaultClassName = token; - Stream.of(testSet.getMethods()).filter( - m -> m.isAnnotationPresent(Test.class)).map( - Method::getName).distinct().forEach( - name -> result.add(String.join(".", token, name))); + result.addAll(Stream.of(testSet.getMethods()) + .filter(m -> m.isAnnotationPresent(Test.class)) + .filter(testMethodSupplier::isEnabled) + .map(Method::getName).distinct() + .map(name -> String.join(".", token, name)) + .toList()); continue; } @@ -246,7 +249,7 @@ private static Stream cmdLineArgValueToMethodNames(String v) { qualifiedMethodName = token; defaultClassName = token.substring(0, lastDotIdx); } else if (defaultClassName == null) { - throw new ParseException("Default class name not found in"); + throw new ParseException("Missing default class name in"); } else { qualifiedMethodName = String.join(".", defaultClassName, token); } @@ -255,155 +258,43 @@ private static Stream cmdLineArgValueToMethodNames(String v) { return result.stream(); } - private static boolean filterMethod(String expectedMethodName, Method method) { - if (!method.getName().equals(expectedMethodName)) { - return false; - } - switch (method.getParameterCount()) { - case 0: - return !isParametrized(method); - case 1: - return isParametrized(method); - } - return false; - } - - private static boolean isParametrized(Method method) { - return method.isAnnotationPresent(ParameterGroup.class) || method.isAnnotationPresent( - Parameter.class); - } - - private static List getJavaMethodFromString( - String qualifiedMethodName) { + private List getJavaMethodFromString(String qualifiedMethodName) { int lastDotIdx = qualifiedMethodName.lastIndexOf('.'); if (lastDotIdx == -1) { - throw new ParseException("Class name not found in"); - } - String className = qualifiedMethodName.substring(0, lastDotIdx); - String methodName = qualifiedMethodName.substring(lastDotIdx + 1); - Class methodClass; - try { - methodClass = Class.forName(className); - } catch (ClassNotFoundException ex) { - throw new ParseException(String.format("Class [%s] not found;", - className)); - } - // Get the list of all public methods as need to deal with overloads. - List methods = Stream.of(methodClass.getMethods()).filter( - (m) -> filterMethod(methodName, m)).collect(Collectors.toList()); - if (methods.isEmpty()) { - throw new ParseException(String.format( - "Method [%s] not found in [%s] class;", - methodName, className)); + throw new ParseException("Missing class name in"); } - trace(String.format("%s -> %s", qualifiedMethodName, methods)); - return methods; - } - - private static Stream getJavaMethodsFromArg(String argValue) { - return cmdLineArgValueToMethodNames(argValue).map( - ThrowingFunction.toFunction( - TestBuilder::getJavaMethodFromString)).flatMap( - List::stream).sequential(); - } - - private static Parameter[] getMethodParameters(Method method) { - if (method.isAnnotationPresent(ParameterGroup.class)) { - return ((ParameterGroup) method.getAnnotation(ParameterGroup.class)).value(); - } - - if (method.isAnnotationPresent(Parameter.class)) { - return new Parameter[]{(Parameter) method.getAnnotation( - Parameter.class)}; - } - - // Unexpected - return null; - } - - private static Stream toCtorArgs(Method method) throws - IllegalAccessException, InvocationTargetException { - Class type = method.getDeclaringClass(); - List paremetersProviders = Stream.of(type.getMethods()) - .filter(m -> m.getParameterCount() == 0) - .filter(m -> (m.getModifiers() & Modifier.STATIC) != 0) - .filter(m -> m.isAnnotationPresent(Parameters.class)) - .sorted() - .collect(Collectors.toList()); - if (paremetersProviders.isEmpty()) { - // Single instance using the default constructor. - return Stream.ofNullable(MethodCall.DEFAULT_CTOR_ARGS); - } - - // Pick the first method from the list. - Method paremetersProvider = paremetersProviders.iterator().next(); - if (paremetersProviders.size() > 1) { - trace(String.format( - "Found %d public static methods without arguments with %s annotation. Will use %s", - paremetersProviders.size(), Parameters.class, - paremetersProvider)); - paremetersProviders.stream().map(Method::toString).forEach( - TestBuilder::trace); + try { + return testMethodSupplier.findNullaryLikeMethods( + fromQualifiedMethodName(qualifiedMethodName)); + } catch (NoSuchMethodException ex) { + throw new ParseException(ex.getMessage() + ";", ex); } - - // Construct collection of arguments for test class instances. - return ((Collection) paremetersProvider.invoke(null)).stream(); } - private static Stream toMethodCalls(Method method) throws - IllegalAccessException, InvocationTargetException { - return toCtorArgs(method).map(v -> toMethodCalls(v, method)).flatMap( - s -> s).peek(methodCall -> { - // Make sure required constructor is accessible if the one is needed. - // Need to probe all methods as some of them might be static - // and some class members. - // Only class members require ctors. - try { - methodCall.checkRequiredConstructor(); - } catch (NoSuchMethodException ex) { - throw new ParseException(ex.getMessage() + "."); - } - }); + private Stream getJavaMethodsFromArg(String argValue) { + var methods = cmdLineArgValueToMethodNames(argValue) + .map(this::getJavaMethodFromString) + .flatMap(List::stream).toList(); + trace(String.format("%s -> %s", argValue, methods)); + return methods.stream(); } - private static Stream toMethodCalls(Object[] ctorArgs, Method method) { - if (!isParametrized(method)) { - return Stream.of(new MethodCall(ctorArgs, method)); - } - Parameter[] annotations = getMethodParameters(method); - if (annotations.length == 0) { - return Stream.of(new MethodCall(ctorArgs, method)); - } - return Stream.of(annotations).map((a) -> { - Class paramType = method.getParameterTypes()[0]; - final Object annotationValue; - if (!paramType.isArray()) { - annotationValue = fromString(a.value()[0], paramType); - } else { - Class paramComponentType = paramType.getComponentType(); - annotationValue = Array.newInstance(paramComponentType, a.value().length); - var idx = new AtomicInteger(-1); - Stream.of(a.value()).map(v -> fromString(v, paramComponentType)).sequential().forEach( - v -> Array.set(annotationValue, idx.incrementAndGet(), v)); + private Stream toMethodCalls(Method method) throws + IllegalAccessException, InvocationTargetException, InvalidAnnotationException { + return testMethodSupplier.mapToMethodCalls(method).peek(methodCall -> { + // Make sure required constructor is accessible if the one is needed. + // Need to probe all methods as some of them might be static + // and some class members. + // Only class members require ctors. + try { + methodCall.checkRequiredConstructor(); + } catch (NoSuchMethodException ex) { + throw new ParseException(ex.getMessage() + ".", ex); } - return new MethodCall(ctorArgs, method, annotationValue); }); } - private static Object fromString(String value, Class toType) { - if (toType.isEnum()) { - return Enum.valueOf(toType, value); - } - Function converter = conv.get(toType); - if (converter == null) { - throw new RuntimeException(String.format( - "Failed to find a conversion of [%s] string to %s type", - value, toType)); - } - return converter.apply(value); - } - // Wraps Method.invike() into ThrowingRunnable.run() private ThrowingConsumer wrap(Method method) { return (test) -> { @@ -427,6 +318,10 @@ private static class ParseException extends IllegalArgumentException { super(msg); } + ParseException(String msg, Exception ex) { + super(msg, ex); + } + void setContext(String badCmdLineArg) { this.badCmdLineArg = badCmdLineArg; } @@ -448,8 +343,9 @@ static void trace(String msg) { } } + private final TestMethodSupplier testMethodSupplier; private final Map> argProcessors; - private Consumer testConsumer; + private final Consumer testConsumer; private List testGroup; private List beforeActions; private List afterActions; @@ -458,14 +354,5 @@ static void trace(String msg) { private String spaceSubstitute; private boolean dryRun; - private final static Map> conv = Map.of( - boolean.class, Boolean::valueOf, - Boolean.class, Boolean::valueOf, - int.class, Integer::valueOf, - Integer.class, Integer::valueOf, - long.class, Long::valueOf, - Long.class, Long::valueOf, - String.class, String::valueOf); - - final static String CMDLINE_ARG_PREFIX = "--jpt-"; + static final String CMDLINE_ARG_PREFIX = "--jpt-"; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilderConfig.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilderConfig.java new file mode 100644 index 00000000000..baeaec32546 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilderConfig.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.jpackage.test; + +import java.util.Objects; +import jdk.internal.util.OperatingSystem; + +final class TestBuilderConfig { + TestBuilderConfig() { + } + + TestMethodSupplier createTestMethodSupplier() { + return new TestMethodSupplier(os); + } + + OperatingSystem getOperatingSystem() { + return os; + } + + static TestBuilderConfig getDefault() { + return DEFAULT.get(); + } + + static void setOperatingSystem(OperatingSystem os) { + Objects.requireNonNull(os); + DEFAULT.get().os = os; + } + + static void setDefaults() { + DEFAULT.set(new TestBuilderConfig()); + } + + private OperatingSystem os = OperatingSystem.current(); + + private static final ThreadLocal DEFAULT = new ThreadLocal<>() { + @Override + protected TestBuilderConfig initialValue() { + return new TestBuilderConfig(); + } + }; +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java index 105c8f707cd..f619c9e222e 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * 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,8 +32,10 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -50,7 +52,7 @@ private TestDesc() { String testFullName() { StringBuilder sb = new StringBuilder(); - sb.append(clazz.getSimpleName()); + sb.append(clazz.getName()); if (instanceArgs != null) { sb.append('(').append(instanceArgs).append(')'); } @@ -78,12 +80,12 @@ Builder method(Method v) { } Builder ctorArgs(Object... v) { - ctorArgs = ofNullable(v); + ctorArgs = Arrays.asList(v); return this; } Builder methodArgs(Object... v) { - methodArgs = ofNullable(v); + methodArgs = Arrays.asList(v); return this; } @@ -107,22 +109,18 @@ private static String formatArgs(List values) { } return values.stream().map(v -> { if (v != null && v.getClass().isArray()) { - return String.format("%s(length=%d)", - Arrays.deepToString((Object[]) v), - Array.getLength(v)); + String asString; + if (v.getClass().getComponentType().isPrimitive()) { + asString = PRIMITIVE_ARRAY_FORMATTERS.get(v.getClass()).apply(v); + } else { + asString = Arrays.deepToString((Object[]) v); + } + return String.format("%s(length=%d)", asString, Array.getLength(v)); } return String.format("%s", v); }).collect(Collectors.joining(", ")); } - private static List ofNullable(Object... values) { - List result = new ArrayList(); - for (var v: values) { - result.add(v); - } - return result; - } - private List ctorArgs; private List methodArgs; private Method method; @@ -331,7 +329,7 @@ public String toString() { private final boolean dryRun; private final Path workDir; - private final static Set KEEP_WORK_DIR = Functional.identity( + private static final Set KEEP_WORK_DIR = Functional.identity( () -> { final String propertyName = "keep-work-dir"; Set keepWorkDir = TKit.tokenizeConfigProperty( @@ -355,4 +353,15 @@ public String toString() { return Collections.unmodifiableSet(result); }).get(); + private static final Map, Function> PRIMITIVE_ARRAY_FORMATTERS = Map.of( + boolean[].class, v -> Arrays.toString((boolean[])v), + byte[].class, v -> Arrays.toString((byte[])v), + char[].class, v -> Arrays.toString((char[])v), + short[].class, v -> Arrays.toString((short[])v), + int[].class, v -> Arrays.toString((int[])v), + long[].class, v -> Arrays.toString((long[])v), + float[].class, v -> Arrays.toString((float[])v), + double[].class, v -> Arrays.toString((double[])v) + ); + } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java new file mode 100644 index 00000000000..83b1c19bd95 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.jpackage.test; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import jdk.internal.util.OperatingSystem; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterGroup; +import jdk.jpackage.test.Annotations.ParameterSupplier; +import jdk.jpackage.test.Annotations.ParameterSupplierGroup; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.Annotations.Test; +import static jdk.jpackage.test.Functional.ThrowingFunction.toFunction; +import static jdk.jpackage.test.Functional.ThrowingSupplier.toSupplier; +import static jdk.jpackage.test.MethodCall.mapArgs; + +final class TestMethodSupplier { + + TestMethodSupplier(OperatingSystem os) { + Objects.requireNonNull(os); + this.os = os; + } + + record MethodQuery(String className, String methodName) { + + List lookup() throws ClassNotFoundException { + final Class methodClass = Class.forName(className); + + // Get the list of all public methods as need to deal with overloads. + return Stream.of(methodClass.getMethods()).filter(method -> { + return method.getName().equals(methodName); + }).toList(); + } + + static MethodQuery fromQualifiedMethodName(String qualifiedMethodName) { + int lastDotIdx = qualifiedMethodName.lastIndexOf('.'); + if (lastDotIdx == -1) { + throw new IllegalArgumentException("Class name not specified"); + } + + var className = qualifiedMethodName.substring(0, lastDotIdx); + var methodName = qualifiedMethodName.substring(lastDotIdx + 1); + + return new MethodQuery(className, methodName); + } + } + + List findNullaryLikeMethods(MethodQuery query) throws NoSuchMethodException { + List methods; + + try { + methods = query.lookup(); + } catch (ClassNotFoundException ex) { + throw new NoSuchMethodException( + String.format("Class [%s] not found", query.className())); + } + + if (methods.isEmpty()) { + throw new NoSuchMethodException(String.format( + "Public method [%s] not found in [%s] class", + query.methodName(), query.className())); + } + + methods = methods.stream().filter(method -> { + if (isParameterized(method) && isTest(method)) { + // Always accept test method with annotations producing arguments for its invocation. + return true; + } else { + return method.getParameterCount() == 0; + } + }).filter(this::isEnabled).toList(); + + if (methods.isEmpty()) { + throw new NoSuchMethodException(String.format( + "Suitable public method [%s] not found in [%s] class", + query.methodName(), query.className())); + } + + return methods; + } + + boolean isTestClass(Class type) { + var typeStatus = processedTypes.get(type); + if (typeStatus == null) { + typeStatus = Verifier.isTestClass(type) ? TypeStatus.TEST_CLASS : TypeStatus.NOT_TEST_CLASS; + processedTypes.put(type, typeStatus); + } + + return !TypeStatus.NOT_TEST_CLASS.equals(typeStatus); + } + + void verifyTestClass(Class type) throws InvalidAnnotationException { + var typeStatus = processedTypes.get(type); + if (typeStatus == null) { + // The "type" has not been verified yet. + try { + Verifier.verifyTestClass(type); + processedTypes.put(type, TypeStatus.VALID_TEST_CLASS); + return; + } catch (InvalidAnnotationException ex) { + processedTypes.put(type, TypeStatus.TEST_CLASS); + throw ex; + } + } + + switch (typeStatus) { + case NOT_TEST_CLASS -> Verifier.throwNotTestClassException(type); + case TEST_CLASS -> Verifier.verifyTestClass(type); + case VALID_TEST_CLASS -> {} + } + } + + boolean isEnabled(Method method) { + return Stream.of(Test.class, Parameters.class) + .filter(method::isAnnotationPresent) + .findFirst() + .map(method::getAnnotation) + .map(this::canRunOnTheOperatingSystem) + .orElse(true); + } + + Stream mapToMethodCalls(Method method) throws + IllegalAccessException, InvocationTargetException { + return toCtorArgs(method).map(v -> toMethodCalls(v, method)).flatMap(x -> x); + } + + private Stream toCtorArgs(Method method) throws + IllegalAccessException, InvocationTargetException { + + if ((method.getModifiers() & Modifier.STATIC) != 0) { + // Static method, no instance + return Stream.ofNullable(DEFAULT_CTOR_ARGS); + } + + final var type = method.getDeclaringClass(); + + final var paremeterSuppliers = filterParameterSuppliers(type) + .filter(m -> m.isAnnotationPresent(Parameters.class)) + .filter(this::isEnabled) + .sorted(Comparator.comparing(Method::getName)).toList(); + if (paremeterSuppliers.isEmpty()) { + // Single instance using the default constructor. + return Stream.ofNullable(DEFAULT_CTOR_ARGS); + } + + // Construct collection of arguments for test class instances. + return createArgs(paremeterSuppliers.toArray(Method[]::new)); + } + + private Stream toMethodCalls(Object[] ctorArgs, Method method) { + if (!isParameterized(method)) { + return Stream.of(new MethodCall(ctorArgs, method)); + } + + var fromParameter = Stream.of(getMethodParameters(method)).map(a -> { + return createArgsForAnnotation(method, a); + }).flatMap(List::stream); + + var fromParameterSupplier = Stream.of(getMethodParameterSuppliers(method)).map(a -> { + return toSupplier(() -> createArgsForAnnotation(method, a)).get(); + }).flatMap(List::stream); + + return Stream.concat(fromParameter, fromParameterSupplier).map(args -> { + return new MethodCall(ctorArgs, method, args); + }); + } + + private List createArgsForAnnotation(Executable exec, Parameter a) { + if (!canRunOnTheOperatingSystem(a)) { + return List.of(); + } + + final var annotationArgs = a.value(); + final var execParameterTypes = exec.getParameterTypes(); + + if (execParameterTypes.length > annotationArgs.length) { + if (execParameterTypes.length - annotationArgs.length == 1 && exec.isVarArgs()) { + } else { + throw new RuntimeException(String.format( + "Not enough annotation values %s for [%s]", + List.of(annotationArgs), exec)); + } + } + + final Class[] argTypes; + if (exec.isVarArgs()) { + List> argTypesBuilder = new ArrayList<>(); + var lastExecParameterTypeIdx = execParameterTypes.length - 1; + argTypesBuilder.addAll(List.of(execParameterTypes).subList(0, + lastExecParameterTypeIdx)); + argTypesBuilder.addAll(Collections.nCopies( + Integer.max(0, annotationArgs.length - lastExecParameterTypeIdx), + execParameterTypes[lastExecParameterTypeIdx].componentType())); + argTypes = argTypesBuilder.toArray(Class[]::new); + } else { + argTypes = execParameterTypes; + } + + if (argTypes.length < annotationArgs.length) { + throw new RuntimeException(String.format( + "Too many annotation values %s for [%s]", + List.of(annotationArgs), exec)); + } + + var args = mapArgs(exec, IntStream.range(0, argTypes.length).mapToObj(idx -> { + return fromString(annotationArgs[idx], argTypes[idx]); + }).toArray(Object[]::new)); + + return List.of(args); + } + + private List createArgsForAnnotation(Executable exec, + ParameterSupplier a) throws IllegalAccessException, + InvocationTargetException { + if (!canRunOnTheOperatingSystem(a)) { + return List.of(); + } + + final Class execClass = exec.getDeclaringClass(); + final var supplierFuncName = a.value(); + + final MethodQuery methodQuery; + if (!a.value().contains(".")) { + // No class name specified + methodQuery = new MethodQuery(execClass.getName(), a.value()); + } else { + methodQuery = MethodQuery.fromQualifiedMethodName(supplierFuncName); + } + + final Method supplierMethod; + try { + final var parameterSupplierCandidates = findNullaryLikeMethods(methodQuery); + final Function classForName = toFunction(Class::forName); + final var supplierMethodClass = classForName.apply(methodQuery.className()); + if (parameterSupplierCandidates.isEmpty()) { + throw new RuntimeException(String.format( + "No parameter suppliers in [%s] class", + supplierMethodClass.getName())); + } + + var allParameterSuppliers = filterParameterSuppliers(supplierMethodClass).toList(); + + supplierMethod = findNullaryLikeMethods(methodQuery) + .stream() + .filter(allParameterSuppliers::contains) + .findFirst().orElseThrow(() -> { + var msg = String.format( + "No suitable parameter supplier found for %s(%s) annotation", + a, supplierFuncName); + trace(String.format( + "%s. Parameter suppliers of %s class:", msg, + execClass.getName())); + IntStream.range(0, allParameterSuppliers.size()).mapToObj(idx -> { + return String.format(" [%d/%d] %s()", idx + 1, + allParameterSuppliers.size(), + allParameterSuppliers.get(idx).getName()); + }).forEachOrdered(TestMethodSupplier::trace); + + return new RuntimeException(msg); + }); + } catch (NoSuchMethodException ex) { + throw new RuntimeException(String.format( + "Method not found for %s(%s) annotation", a, supplierFuncName)); + } + + return createArgs(supplierMethod).map(args -> { + return mapArgs(exec, args); + }).toList(); + } + + private boolean canRunOnTheOperatingSystem(Annotation a) { + switch (a) { + case Test t -> { + return canRunOnTheOperatingSystem(os, t.ifOS(), t.ifNotOS()); + } + case Parameters t -> { + return canRunOnTheOperatingSystem(os, t.ifOS(), t.ifNotOS()); + } + case Parameter t -> { + return canRunOnTheOperatingSystem(os, t.ifOS(), t.ifNotOS()); + } + case ParameterSupplier t -> { + return canRunOnTheOperatingSystem(os, t.ifOS(), t.ifNotOS()); + } + default -> { + return true; + } + } + } + + private static boolean isParameterized(Method method) { + return Stream.of( + Parameter.class, ParameterGroup.class, + ParameterSupplier.class, ParameterSupplierGroup.class + ).anyMatch(method::isAnnotationPresent); + } + + private static boolean isTest(Method method) { + return method.isAnnotationPresent(Test.class); + } + + private static boolean canRunOnTheOperatingSystem(OperatingSystem value, + OperatingSystem[] include, OperatingSystem[] exclude) { + Set suppordOperatingSystems = new HashSet<>(); + suppordOperatingSystems.addAll(List.of(include)); + suppordOperatingSystems.removeAll(List.of(exclude)); + return suppordOperatingSystems.contains(value); + } + + private static Parameter[] getMethodParameters(Method method) { + if (method.isAnnotationPresent(ParameterGroup.class)) { + return ((ParameterGroup) method.getAnnotation(ParameterGroup.class)).value(); + } + + if (method.isAnnotationPresent(Parameter.class)) { + return new Parameter[]{(Parameter) method.getAnnotation(Parameter.class)}; + } + + return new Parameter[0]; + } + + private static ParameterSupplier[] getMethodParameterSuppliers(Method method) { + if (method.isAnnotationPresent(ParameterSupplierGroup.class)) { + return ((ParameterSupplierGroup) method.getAnnotation(ParameterSupplierGroup.class)).value(); + } + + if (method.isAnnotationPresent(ParameterSupplier.class)) { + return new ParameterSupplier[]{(ParameterSupplier) method.getAnnotation( + ParameterSupplier.class)}; + } + + return new ParameterSupplier[0]; + } + + private static Stream filterParameterSuppliers(Class type) { + return Stream.of(type.getMethods()) + .filter(m -> m.getParameterCount() == 0) + .filter(m -> (m.getModifiers() & Modifier.STATIC) != 0) + .sorted(Comparator.comparing(Method::getName)); + } + + private static Stream createArgs(Method ... parameterSuppliers) throws + IllegalAccessException, InvocationTargetException { + List args = new ArrayList<>(); + for (var parameterSupplier : parameterSuppliers) { + args.addAll((Collection) parameterSupplier.invoke(null)); + } + return args.stream(); + } + + private static Object fromString(String value, Class toType) { + if (toType.isEnum()) { + return Enum.valueOf(toType, value); + } + Function converter = FROM_STRING.get(toType); + if (converter == null) { + throw new RuntimeException(String.format( + "Failed to find a conversion of [%s] string to %s type", + value, toType.getName())); + } + return converter.apply(value); + } + + private static void trace(String msg) { + if (TKit.VERBOSE_TEST_SETUP) { + TKit.log(msg); + } + } + + static class InvalidAnnotationException extends Exception { + InvalidAnnotationException(String msg) { + super(msg); + } + } + + private static class Verifier { + static boolean isTestClass(Class type) { + for (var method : type.getDeclaredMethods()) { + if (isParameterized(method) || isTest(method)) { + return true; + } + } + return false; + } + + static void verifyTestClass(Class type) throws InvalidAnnotationException { + boolean withTestAnnotations = false; + for (var method : type.getDeclaredMethods()) { + if (!withTestAnnotations && (isParameterized(method) || isTest(method))) { + withTestAnnotations = true; + } + verifyAnnotationsCorrect(method); + } + + if (!withTestAnnotations) { + throwNotTestClassException(type); + } + } + + static void throwNotTestClassException(Class type) throws InvalidAnnotationException { + throw new InvalidAnnotationException(String.format( + "Type [%s] is not a test class", type.getName())); + } + + private static void verifyAnnotationsCorrect(Method method) throws + InvalidAnnotationException { + var parameterized = isParameterized(method); + if (parameterized && !isTest(method)) { + throw new InvalidAnnotationException(String.format( + "Missing %s annotation on [%s] method", Test.class.getName(), method)); + } + + var isPublic = Modifier.isPublic(method.getModifiers()); + + if (isTest(method) && !isPublic) { + throw new InvalidAnnotationException(String.format( + "Non-public method [%s] with %s annotation", + method, Test.class.getName())); + } + + if (method.isAnnotationPresent(Parameters.class) && !isPublic) { + throw new InvalidAnnotationException(String.format( + "Non-public method [%s] with %s annotation", + method, Test.class.getName())); + } + } + } + + private enum TypeStatus { + NOT_TEST_CLASS, + TEST_CLASS, + VALID_TEST_CLASS, + } + + private final OperatingSystem os; + private final Map, TypeStatus> processedTypes = new HashMap<>(); + + private static final Object[] DEFAULT_CTOR_ARGS = new Object[0]; + + private static final Map> FROM_STRING; + + static { + Map> primitives = Map.of( + boolean.class, Boolean::valueOf, + byte.class, Byte::valueOf, + short.class, Short::valueOf, + int.class, Integer::valueOf, + long.class, Long::valueOf, + float.class, Float::valueOf, + double.class, Double::valueOf); + + Map> boxed = Map.of( + Boolean.class, Boolean::valueOf, + Byte.class, Byte::valueOf, + Short.class, Short::valueOf, + Integer.class, Integer::valueOf, + Long.class, Long::valueOf, + Float.class, Float::valueOf, + Double.class, Double::valueOf); + + Map> other = Map.of( + String.class, String::valueOf, + Path.class, Path::of); + + Map> combined = new HashMap<>(primitives); + combined.putAll(other); + combined.putAll(boxed); + + FROM_STRING = Collections.unmodifiableMap(combined); + } +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 86a68484c0b..ebf4494aa79 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -66,7 +66,7 @@ private static void runMsiexecWithRetries(Executor misexec) { for (int attempt = 0; attempt < 8; ++attempt) { result = misexec.executeWithoutExitCodeCheck(); - if (result.exitCode == 1605) { + if (result.exitCode() == 1605) { // ERROR_UNKNOWN_PRODUCT, attempt to uninstall not installed // package return; @@ -75,7 +75,7 @@ private static void runMsiexecWithRetries(Executor misexec) { // The given Executor may either be of an msiexec command or an // unpack.bat script containing the msiexec command. In the later // case, when misexec returns 1618, the unpack.bat may return 1603 - if ((result.exitCode == 1618) || (result.exitCode == 1603)) { + if ((result.exitCode() == 1618) || (result.exitCode() == 1603)) { // Another installation is already in progress. // Wait a little and try again. Long timeout = 1000L * (attempt + 3); // from 3 to 10 seconds @@ -360,7 +360,7 @@ static String queryRegistryValue(String keyPath, String valueName) { var status = Executor.of("reg", "query", keyPath, "/v", valueName) .saveOutput() .executeWithoutExitCodeCheck(); - if (status.exitCode == 1) { + if (status.exitCode() == 1) { // Should be the case of no such registry value or key String lookupString = "ERROR: The system was unable to find the specified registry key or value."; TKit.assertTextStream(lookupString) diff --git a/test/jdk/tools/jpackage/share/AddLShortcutTest.java b/test/jdk/tools/jpackage/share/AddLShortcutTest.java index 92784abd5cc..5b55d906cf1 100644 --- a/test/jdk/tools/jpackage/share/AddLShortcutTest.java +++ b/test/jdk/tools/jpackage/share/AddLShortcutTest.java @@ -22,8 +22,6 @@ */ import java.nio.file.Path; -import java.io.File; -import java.util.Map; import java.lang.invoke.MethodHandles; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.FileAssociations; @@ -109,6 +107,6 @@ public void test() { packageTest.run(); } - private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of( + private static final Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of( "resources", "icon" + TKit.ICON_SUFFIX)); } diff --git a/test/jdk/tools/jpackage/share/AddLauncherTest.java b/test/jdk/tools/jpackage/share/AddLauncherTest.java index ae774b86f3a..af0efc4fb86 100644 --- a/test/jdk/tools/jpackage/share/AddLauncherTest.java +++ b/test/jdk/tools/jpackage/share/AddLauncherTest.java @@ -22,7 +22,6 @@ */ import java.nio.file.Path; -import java.io.File; import java.util.Map; import java.lang.invoke.MethodHandles; import jdk.jpackage.test.PackageTest; @@ -229,11 +228,11 @@ public void testMainLauncherIsModular(boolean mainLauncherIsModular) { TKit.assertEquals(ExpectedCN, mainClass, String.format("Check value of app.mainclass=[%s]" + "in NonModularAppLauncher cfg file is as expected", ExpectedCN)); - TKit.assertTrue(classpath.startsWith("$APPDIR" + File.separator - + nonModularAppDesc.jarFileName()), + TKit.assertTrue(classpath.startsWith(Path.of("$APPDIR", + nonModularAppDesc.jarFileName()).toString()), "Check app.classpath value in ModularAppLauncher cfg file"); } - private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of( + private static final Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of( "resources", "icon" + TKit.ICON_SUFFIX)); } diff --git a/test/jdk/tools/jpackage/share/InstallDirTest.java b/test/jdk/tools/jpackage/share/InstallDirTest.java index 7047f35e87b..23539589bcc 100644 --- a/test/jdk/tools/jpackage/share/InstallDirTest.java +++ b/test/jdk/tools/jpackage/share/InstallDirTest.java @@ -22,13 +22,12 @@ */ import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; +import jdk.internal.util.OperatingSystem; import jdk.jpackage.test.TKit; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.Functional; import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.Test; /** * Test --install-dir parameter. Output of the test should be @@ -76,28 +75,18 @@ */ public class InstallDirTest { - public static void testCommon() { - final Map INSTALL_DIRS = Functional.identity(() -> { - Map reply = new HashMap<>(); - reply.put(PackageType.WIN_MSI, Path.of("TestVendor\\InstallDirTest1234")); - reply.put(PackageType.WIN_EXE, reply.get(PackageType.WIN_MSI)); - - reply.put(PackageType.LINUX_DEB, Path.of("/opt/jpackage")); - reply.put(PackageType.LINUX_RPM, reply.get(PackageType.LINUX_DEB)); - - reply.put(PackageType.MAC_PKG, Path.of("/Applications/jpackage")); - reply.put(PackageType.MAC_DMG, reply.get(PackageType.MAC_PKG)); - - return reply; - }).get(); - + @Test + @Parameter(value = "TestVendor\\InstallDirTest1234", ifOS = OperatingSystem.WINDOWS) + @Parameter(value = "/opt/jpackage", ifOS = OperatingSystem.LINUX) + @Parameter(value = "/Applications/jpackage", ifOS = OperatingSystem.MACOS) + public static void testCommon(Path installDir) { new PackageTest().configureHelloApp() .addInitializer(cmd -> { - cmd.addArguments("--install-dir", INSTALL_DIRS.get( - cmd.packageType())); + cmd.addArguments("--install-dir", installDir); }).run(); } + @Test(ifOS = OperatingSystem.LINUX) @Parameter("/") @Parameter(".") @Parameter("foo") diff --git a/test/jdk/tools/launcher/TooSmallStackSize.java b/test/jdk/tools/launcher/TooSmallStackSize.java index 8485f115d6e..8133dbf4550 100644 --- a/test/jdk/tools/launcher/TooSmallStackSize.java +++ b/test/jdk/tools/launcher/TooSmallStackSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ * @bug 6762191 8222334 * @summary Setting stack size to 16K causes segmentation fault * @compile TooSmallStackSize.java + * @comment VM fails to launch with minimum allowed stack size of 136k when asan is enabled + * @requires !vm.asan * @run main TooSmallStackSize */ diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 59acf27716c..5ef0fddd392 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -128,7 +128,7 @@ public Map call() { map.put("vm.graal.enabled", this::isGraalEnabled); map.put("vm.compiler1.enabled", this::isCompiler1Enabled); map.put("vm.compiler2.enabled", this::isCompiler2Enabled); - map.put("docker.support", this::dockerSupport); + map.put("container.support", this::containerSupport); map.put("systemd.support", this::systemdSupport); map.put("vm.musl", this::isMusl); map.put("vm.asan", this::isAsanEnabled); @@ -535,16 +535,16 @@ protected String isCompiler2Enabled() { } /** - * A simple check for docker support + * A simple check for container support * - * @return true if docker is supported in a given environment + * @return true if container is supported in a given environment */ - protected String dockerSupport() { - log("Entering dockerSupport()"); + protected String containerSupport() { + log("Entering containerSupport()"); boolean isSupported = false; if (Platform.isLinux()) { - // currently docker testing is only supported for Linux, + // currently container testing is only supported for Linux, // on certain platforms String arch = System.getProperty("os.arch"); @@ -560,17 +560,17 @@ protected String dockerSupport() { } } - log("dockerSupport(): platform check: isSupported = " + isSupported); + log("containerSupport(): platform check: isSupported = " + isSupported); if (isSupported) { try { - isSupported = checkProgramSupport("checkDockerSupport()", Container.ENGINE_COMMAND); + isSupported = checkProgramSupport("checkContainerSupport()", Container.ENGINE_COMMAND); } catch (Exception e) { isSupported = false; } } - log("dockerSupport(): returning isSupported = " + isSupported); + log("containerSupport(): returning isSupported = " + isSupported); return "" + isSupported; } diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/CrashOnNonExistingMethodTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/CrashOnNonExistingMethodTest.java new file mode 100644 index 00000000000..da2174640d9 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/CrashOnNonExistingMethodTest.java @@ -0,0 +1,22 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8334756 + * @summary javac crashes on call to non-existent generic method with explicit annotated type arg + * @compile/fail/ref=CrashOnNonExistingMethodTest.out -XDrawDiagnostics -XDdev CrashOnNonExistingMethodTest.java + */ + +import static java.lang.annotation.ElementType.TYPE_USE; +import java.lang.annotation.Target; + +class CrashOnNonExistingMethodTest { + @Target(TYPE_USE) + @interface Nullable {} + + static T identity(T t) { + return t; + } + + static void test() { + CrashOnNonExistingMethodTest.<@Nullable Object>nonNullIdentity(null); + } +} diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/CrashOnNonExistingMethodTest.out b/test/langtools/tools/javac/annotations/typeAnnotations/CrashOnNonExistingMethodTest.out new file mode 100644 index 00000000000..376c06c93b0 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/CrashOnNonExistingMethodTest.out @@ -0,0 +1,2 @@ +CrashOnNonExistingMethodTest.java:20:37: compiler.err.cant.resolve.location.args.params: kindname.method, nonNullIdentity, java.lang.Object, compiler.misc.type.null, (compiler.misc.location: kindname.class, CrashOnNonExistingMethodTest, null) +1 error diff --git a/test/langtools/tools/javac/jvm/ClassRefDupInConstantPoolTest.java b/test/langtools/tools/javac/jvm/ClassRefDupInConstantPoolTest.java index a84c87245af..34fbefa9883 100644 --- a/test/langtools/tools/javac/jvm/ClassRefDupInConstantPoolTest.java +++ b/test/langtools/tools/javac/jvm/ClassRefDupInConstantPoolTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ * @bug 8015927 * @summary Class reference duplicates in constant pool * @modules jdk.jdeps/com.sun.tools.classfile - * @clean ClassRefDupInConstantPoolTest$Duplicates + * @clean ClassRefDupInConstantPoolTest ClassRefDupInConstantPoolTest$Duplicates * @run main ClassRefDupInConstantPoolTest */ diff --git a/test/langtools/tools/javac/parser/ExtraImportSemicolon.java b/test/langtools/tools/javac/parser/ExtraImportSemicolon.java index 54304833fa6..11c5decdf1e 100644 --- a/test/langtools/tools/javac/parser/ExtraImportSemicolon.java +++ b/test/langtools/tools/javac/parser/ExtraImportSemicolon.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 5059679 + * @bug 8027682 * @summary Verify proper error reporting of extra semicolon before import statement * @compile/fail/ref=ExtraImportSemicolon.out1 -XDrawDiagnostics ExtraImportSemicolon.java * @compile/ref=ExtraImportSemicolon.out2 --release 20 -XDrawDiagnostics ExtraImportSemicolon.java diff --git a/test/langtools/tools/javac/processing/model/type/AnnotatedTypeToString/AnnotatedTypeToString.java b/test/langtools/tools/javac/processing/model/type/AnnotatedTypeToString/AnnotatedTypeToString.java index 54538e44346..6967f271dcd 100644 --- a/test/langtools/tools/javac/processing/model/type/AnnotatedTypeToString/AnnotatedTypeToString.java +++ b/test/langtools/tools/javac/processing/model/type/AnnotatedTypeToString/AnnotatedTypeToString.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8284220 + * @bug 8284220 8342934 * @summary Tests DeclaredType.toString with type annotations present, for example that '@A * Map.Entry' is printed as 'java.util.@A Map.Entry' (and not '@A java.util.Map.Entry' or * 'java.util.@A Entry'). diff --git a/test/langtools/tools/javac/processing/model/type/AnnotatedTypeToString/Test.java b/test/langtools/tools/javac/processing/model/type/AnnotatedTypeToString/Test.java index 570407a363a..8311344ea9d 100644 --- a/test/langtools/tools/javac/processing/model/type/AnnotatedTypeToString/Test.java +++ b/test/langtools/tools/javac/processing/model/type/AnnotatedTypeToString/Test.java @@ -32,6 +32,10 @@ @Target(ElementType.TYPE_USE) @interface A {} +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE_USE) +@interface B {} + public class Test { static class StaticNested { static class InnerMostStaticNested {} @@ -41,8 +45,8 @@ class Inner { class InnerMost {} } - @ExpectedToString("p.Test.@p.A StaticNested") - @A StaticNested i; + @ExpectedToString("p.Test.@p.A @p.B StaticNested") + @A @B StaticNested i; @ExpectedToString("p.Test.StaticNested.@p.A InnerMostStaticNested") StaticNested.@A InnerMostStaticNested j; diff --git a/test/lib-test/jdk/test/whitebox/vm_flags/SizeTTest.java b/test/lib-test/jdk/test/whitebox/vm_flags/SizeTTest.java index ae57d6701fd..e66af775b08 100644 --- a/test/lib-test/jdk/test/whitebox/vm_flags/SizeTTest.java +++ b/test/lib-test/jdk/test/whitebox/vm_flags/SizeTTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ import jdk.test.lib.Platform; public class SizeTTest { - private static final String FLAG_NAME = "ArrayAllocatorMallocLimit"; + private static final String FLAG_NAME = "LargePageHeapSizeThreshold"; private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE, (1L << 32L) - 1L, 1L << 32L}; private static final Long[] EXPECTED_64 = TESTS; diff --git a/test/lib/jdk/test/lib/Container.java b/test/lib/jdk/test/lib/Container.java index e0ca4851e14..83fd265980f 100644 --- a/test/lib/jdk/test/lib/Container.java +++ b/test/lib/jdk/test/lib/Container.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2019, Red Hat Inc. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * 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 +24,9 @@ package jdk.test.lib; public class Container { - // Use this property to specify docker location on your system. + // Use this property to specify container runtime location (e.g. docker) on your system. // E.g.: "/usr/local/bin/docker". We define this constant here so - // that it can be used in VMProps as well which checks docker support + // that it can be used in VMProps as well which checks container support // via this command public static final String ENGINE_COMMAND = System.getProperty("jdk.test.container.command", "docker"); diff --git a/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java b/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java index 31cff4b8c25..6e65a3277d5 100644 --- a/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java +++ b/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java @@ -122,8 +122,8 @@ public static void verifyJVMStartup(String expectedMessages[], outputAnalyzer.shouldHaveExitValue(exitCode.value); } catch (RuntimeException e) { String errorMessage = String.format( - "JVM process should have exit value '%d'.%n%s", - exitCode.value, exitErrorMessage); + "JVM process should have exit value '%d', but has '%d'.%n%s", + exitCode.value, outputAnalyzer.getExitValue(), exitErrorMessage); throw new AssertionError(errorMessage, e); } @@ -300,9 +300,12 @@ public static void verifyOptionValue(String optionName, CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, optionName, expectedValue)); } catch (RuntimeException e) { + String observedValue = outputAnalyzer.firstMatch(String.format( + CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, + optionName, "\\S")); String errorMessage = String.format( - "Option '%s' is expected to have '%s' value%n%s", - optionName, expectedValue, + "Option '%s' is expected to have '%s' value, but is '%s'.%n%s", + optionName, expectedValue, observedValue, optionErrorString); throw new AssertionError(errorMessage, e); } diff --git a/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java b/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java new file mode 100644 index 00000000000..0d1c3a358ab --- /dev/null +++ b/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Methods and definitions related to container runtime version to test container in this directory + */ + +package jdk.test.lib.containers.docker; + +import jdk.test.lib.Container; +import jdk.test.lib.process.OutputAnalyzer; +import jtreg.SkippedException; + +public class ContainerRuntimeVersionTestUtils implements Comparable { + private final int major; + private final int minor; + private final int micro; + private static final boolean IS_DOCKER = Container.ENGINE_COMMAND.contains("docker"); + private static final boolean IS_PODMAN = Container.ENGINE_COMMAND.contains("podman"); + public static final ContainerRuntimeVersionTestUtils DOCKER_MINIMAL_SUPPORTED_VERSION_CGROUPNS = new ContainerRuntimeVersionTestUtils(20, 10, 0); + public static final ContainerRuntimeVersionTestUtils PODMAN_MINIMAL_SUPPORTED_VERSION_CGROUPNS = new ContainerRuntimeVersionTestUtils(1, 5, 0); + + private ContainerRuntimeVersionTestUtils(int major, int minor, int micro) { + this.major = major; + this.minor = minor; + this.micro = micro; + } + + public static void checkContainerVersionSupported() { + if (IS_DOCKER && ContainerRuntimeVersionTestUtils.DOCKER_MINIMAL_SUPPORTED_VERSION_CGROUPNS.compareTo(ContainerRuntimeVersionTestUtils.getContainerRuntimeVersion()) > 0) { + throw new SkippedException("Docker version too old for this test. Expected >= 20.10.0"); + } + if (IS_PODMAN && ContainerRuntimeVersionTestUtils.PODMAN_MINIMAL_SUPPORTED_VERSION_CGROUPNS.compareTo(ContainerRuntimeVersionTestUtils.getContainerRuntimeVersion()) > 0) { + throw new SkippedException("Podman version too old for this test. Expected >= 1.5.0"); + } + } + + @Override + public int compareTo(ContainerRuntimeVersionTestUtils other) { + if (this.major > other.major) { + return 1; + } else if (this.major < other.major) { + return -1; + } else if (this.minor > other.minor) { + return 1; + } else if (this.minor < other.minor) { + return -1; + } else if (this.micro > other.micro) { + return 1; + } else if (this.micro < other.micro) { + return -1; + } else { + // equal majors, minors, micro + return 0; + } + } + + public static ContainerRuntimeVersionTestUtils fromVersionString(String version) { + try { + // Example 'docker version 20.10.0 or podman version 4.9.4-rhel' + String versNums = version.split("\\s+", 3)[2]; + // On some docker implementations e.g. RHEL8 ppc64le we have the following version output: + // Docker version v25.0.3, build 4debf41 + // Trim potentially leading 'v' and trailing ',' + if (versNums.startsWith("v")) { + versNums = versNums.substring(1); + } + int cidx = versNums.indexOf(','); + versNums = (cidx != -1) ? versNums.substring(0, cidx) : versNums; + + String[] numbers = versNums.split("-")[0].split("\\.", 3); + return new ContainerRuntimeVersionTestUtils(Integer.parseInt(numbers[0]), + Integer.parseInt(numbers[1]), + Integer.parseInt(numbers[2])); + } catch (Exception e) { + throw new RuntimeException("Failed to parse container runtime version: " + version, e); + } + } + + public static String getContainerRuntimeVersionStr() { + try { + ProcessBuilder pb = new ProcessBuilder(Container.ENGINE_COMMAND, "--version"); + OutputAnalyzer out = new OutputAnalyzer(pb.start()) + .shouldHaveExitValue(0); + String result = out.asLines().get(0); + System.out.println(Container.ENGINE_COMMAND + " --version returning: " + result); + return result; + } catch (Exception e) { + throw new RuntimeException(Container.ENGINE_COMMAND + " --version command failed."); + } + } + + public static ContainerRuntimeVersionTestUtils getContainerRuntimeVersion() { + return ContainerRuntimeVersionTestUtils.fromVersionString(getContainerRuntimeVersionStr()); + } +} diff --git a/test/lib/jdk/test/lib/security/CertificateBuilder.java b/test/lib/jdk/test/lib/security/CertificateBuilder.java index 951b6cb9d2e..a1078185560 100644 --- a/test/lib/jdk/test/lib/security/CertificateBuilder.java +++ b/test/lib/jdk/test/lib/security/CertificateBuilder.java @@ -24,12 +24,12 @@ package jdk.test.lib.security; import java.io.*; +import java.security.cert.*; +import java.security.cert.Extension; import java.util.*; import java.security.*; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.Extension; +import java.time.temporal.ChronoUnit; +import java.time.Instant; import javax.security.auth.x500.X500Principal; import java.math.BigInteger; @@ -41,6 +41,7 @@ import sun.security.x509.AlgorithmId; import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.IPAddressName; import sun.security.x509.SubjectKeyIdentifierExtension; import sun.security.x509.BasicConstraintsExtension; import sun.security.x509.ExtendedKeyUsageExtension; @@ -54,6 +55,7 @@ import sun.security.x509.KeyIdentifier; import sun.security.x509.X500Name; + /** * Helper class that builds and signs X.509 certificates. * @@ -98,6 +100,89 @@ public class CertificateBuilder { private byte[] tbsCertBytes; private byte[] signatureBytes; + public enum KeyUsage { + DIGITAL_SIGNATURE, + NONREPUDIATION, + KEY_ENCIPHERMENT, + DATA_ENCIPHERMENT, + KEY_AGREEMENT, + KEY_CERT_SIGN, + CRL_SIGN, + ENCIPHER_ONLY, + DECIPHER_ONLY; + } + + /** + * Create a new CertificateBuilder instance. This method sets the subject name, + * public key, authority key id, and serial number. + * + * @param subjectName entity associated with the public key + * @param publicKey the entity's public key + * @param caKey public key of certificate signer + * @param keyUsages list of key uses + * @return + * @throws CertificateException + * @throws IOException + */ + public static CertificateBuilder newCertificateBuilder(String subjectName, + PublicKey publicKey, PublicKey caKey, KeyUsage... keyUsages) + throws CertificateException, IOException { + SecureRandom random = new SecureRandom(); + + boolean [] keyUsage = new boolean[KeyUsage.values().length]; + for (KeyUsage ku : keyUsages) { + keyUsage[ku.ordinal()] = true; + } + + CertificateBuilder builder = new CertificateBuilder() + .setSubjectName(subjectName) + .setPublicKey(publicKey) + .setSerialNumber(BigInteger.valueOf(random.nextLong(1000000)+1)) + .addSubjectKeyIdExt(publicKey) + .addAuthorityKeyIdExt(caKey); + if (keyUsages.length != 0) { + builder.addKeyUsageExt(keyUsage); + } + return builder; + } + + /** + * Create a Subject Alternative Name extension for the given DNS name + * @param critical Sets the extension to critical or non-critical + * @param dnsName DNS name to use in the extension + * @throws IOException + */ + public static SubjectAlternativeNameExtension createDNSSubjectAltNameExt( + boolean critical, String dnsName) throws IOException { + GeneralNames gns = new GeneralNames(); + gns.add(new GeneralName(new DNSName(dnsName))); + return new SubjectAlternativeNameExtension(critical, gns); + } + + /** + * Create a Subject Alternative Name extension for the given IP address + * @param critical Sets the extension to critical or non-critical + * @param ipAddress IP address to use in the extension + * @throws IOException + */ + public static SubjectAlternativeNameExtension createIPSubjectAltNameExt( + boolean critical, String ipAddress) throws IOException { + GeneralNames gns = new GeneralNames(); + gns.add(new GeneralName(new IPAddressName(ipAddress))); + return new SubjectAlternativeNameExtension(critical, gns); + } + + public static void printCertificate(X509Certificate certificate, PrintStream ps) { + try { + Base64.Encoder encoder = Base64.getEncoder(); + ps.println("-----BEGIN CERTIFICATE-----"); + ps.println(encoder.encodeToString(certificate.getEncoded())); + ps.println("-----END CERTIFICATE-----"); + } catch (CertificateEncodingException exc) { + exc.printStackTrace(ps); + } + } + /** * Default constructor for a {@code CertificateBuilder} object. * @@ -191,6 +276,11 @@ public CertificateBuilder setValidity(Date nbDate, Date naDate) { return setNotBefore(nbDate).setNotAfter(naDate); } + public CertificateBuilder setOneHourValidity() { + return setNotBefore(Date.from(Instant.now().minus(5, ChronoUnit.MINUTES))) + .setNotAfter(Date.from(Instant.now().plus(1, ChronoUnit.HOURS))); + } + /** * Set the serial number on the certificate. * diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index b0e2530f7c0..8586434c8ea 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -24,7 +24,11 @@ package jdk.test.whitebox; import java.lang.management.MemoryUsage; +import java.lang.ref.Reference; import java.lang.reflect.Executable; +import java.lang.reflect.InaccessibleObjectException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; @@ -526,6 +530,53 @@ public void clearInlineCaches(boolean preserve_static_stubs) { // Force Full GC public native void fullGC(); + // Infrastructure for waitForReferenceProcessing() + private static volatile Method waitForReferenceProcessingMethod = null; + + private static Method getWaitForReferenceProcessingMethod() { + Method wfrp = waitForReferenceProcessingMethod; + if (wfrp == null) { + try { + wfrp = Reference.class.getDeclaredMethod("waitForReferenceProcessing"); + wfrp.setAccessible(true); + assert wfrp.getReturnType() == Boolean.class; + Class[] ev = wfrp.getExceptionTypes(); + assert ev.length == 1; + assert ev[0] == InterruptedException.class; + waitForReferenceProcessingMethod = wfrp; + } catch (InaccessibleObjectException e) { + throw new RuntimeException("Need to add @modules java.base/java.lang.ref:open to test?", e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + return wfrp; + } + + /** + * Wait for reference processing, via Reference.waitForReferenceProcessing(). + * Callers of this method will need the + * @modules java.base/java.lang.ref:open + * jtreg tag. + * + * This method should usually be called after a call to WhiteBox.fullGC(). + */ + public boolean waitForReferenceProcessing() throws InterruptedException { + try { + Method wfrp = getWaitForReferenceProcessingMethod(); + return (Boolean) wfrp.invoke(null); + } catch (IllegalAccessException e) { + throw new RuntimeException("Shouldn't happen, we call setAccessible()", e); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof InterruptedException) { + throw (InterruptedException) cause; + } else { + throw new RuntimeException(e); + } + } + } + // Returns true if the current GC supports concurrent collection control. public native boolean supportsConcurrentGCBreakpoints(); @@ -727,7 +778,8 @@ public Object getMethodOption(Executable method, String name) { // Container testing public native boolean isContainerized(); - public native int validateCgroup(String procCgroups, + public native int validateCgroup(boolean cgroupsV2Enabled, + String controllersFile, String procSelfCgroup, String procSelfMountinfo); public native void printOsInfo(); diff --git a/test/micro/org/openjdk/bench/java/net/URIAuthorityParsingBenchmark.java b/test/micro/org/openjdk/bench/java/net/URIAuthorityParsingBenchmark.java new file mode 100644 index 00000000000..8e75b9e35ac --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/URIAuthorityParsingBenchmark.java @@ -0,0 +1,62 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.openjdk.bench.java.net; + +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.net.URI; +import java.util.concurrent.TimeUnit; + +/** + * Tests Java.net.URI.create performance on various URI types. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 3) +public class URIAuthorityParsingBenchmark { + + @Param({ + "https://98765432101.abc.xyz.com", + "https://ABCDEFGHIJK.abc.xyz.com" + }) + private String uri; + + @Benchmark + public void create(Blackhole blackhole) { + blackhole.consume(URI.create(uri)); + } + +} diff --git a/test/micro/org/openjdk/bench/java/security/Signatures.java b/test/micro/org/openjdk/bench/java/security/Signatures.java index 1bd72334343..1216e253663 100644 --- a/test/micro/org/openjdk/bench/java/security/Signatures.java +++ b/test/micro/org/openjdk/bench/java/security/Signatures.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -194,4 +194,3 @@ public void setup() throws Exception { } } } - diff --git a/test/micro/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java b/test/micro/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java index ddf3f69c83d..5580033f249 100644 --- a/test/micro/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java +++ b/test/micro/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.infra.ThreadParams; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -55,7 +56,7 @@ @Fork(3) public class ProducerConsumer { - @Param("100") + @Param("100") // Will be expanded to at least the number of threads used private int capacity; @Param @@ -65,7 +66,9 @@ public class ProducerConsumer { private Producer prod; @Setup - public void prepare() { + public void prepare(ThreadParams params) { + capacity = Math.max(params.getThreadCount(), capacity); + switch (type) { case ABQ_F: q = new ArrayBlockingQueue<>(capacity, true); diff --git a/test/micro/org/openjdk/bench/java/util/concurrent/Queues.java b/test/micro/org/openjdk/bench/java/util/concurrent/Queues.java index 533754419bc..9ea4a05807a 100644 --- a/test/micro/org/openjdk/bench/java/util/concurrent/Queues.java +++ b/test/micro/org/openjdk/bench/java/util/concurrent/Queues.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.infra.ThreadParams; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -49,7 +50,7 @@ @Fork(3) public class Queues { - @Param("100") + @Param("100") // Will be expanded to at least the number of threads used private int capacity; @Param @@ -65,7 +66,9 @@ public enum QueueType { private BlockingQueue q; @Setup - public void setup() { + public void setup(ThreadParams params) { + capacity = Math.max(params.getThreadCount(), capacity); + switch (type) { case ABQ_F: q = new ArrayBlockingQueue<>(capacity, true); diff --git a/test/micro/org/openjdk/bench/vm/compiler/AutoVectorization2DArray.java b/test/micro/org/openjdk/bench/vm/compiler/AutoVectorization2DArray.java index a2a4654b40a..e41b1e7a4d0 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/AutoVectorization2DArray.java +++ b/test/micro/org/openjdk/bench/vm/compiler/AutoVectorization2DArray.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/micro/org/openjdk/bench/vm/compiler/LoopUnroll.java b/test/micro/org/openjdk/bench/vm/compiler/LoopUnroll.java index cbb216bbaa6..2e7e1da4ba9 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/LoopUnroll.java +++ b/test/micro/org/openjdk/bench/vm/compiler/LoopUnroll.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2021, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it