diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index b6a1ed32a4d..fc7ad9a0f03 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1290,7 +1290,10 @@ static boolean explicitAnnotationProcessingRequested(Options options) { options.isSet(PROCESSOR_PATH) || options.isSet(PROCESSOR_MODULE_PATH) || options.isSet(PROC, "only") || + options.isSet(PROC, "full") || + options.isSet(A) || options.isSet(XPRINT); + // Skipping -XprintRounds and -XprintProcessorInfo } public void setDeferredDiagnosticHandler(Log.DeferredDiagnosticHandler deferredDiagnosticHandler) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index c4504974623..821706a167c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -81,6 +81,11 @@ * {@code handleOption} then calls {@link #process process} providing a suitable * {@link OptionHelper} to provide access the compiler state. * + * + *

Maintenance note: when adding new annotation processing related + * options, the list of options regarded as requesting explicit + * annotation processing in JavaCompiler should be updated. + * *

This is NOT part of any supported API. * If you write code that depends on this, you do so at your own * risk. This code and its internal interfaces are subject to change diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java index a277086bcf6..14d1b880206 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java @@ -80,7 +80,7 @@ private void initializeJVMEventTypes() { // annotations, such as Period and Threshold. if (pEventType.hasPeriod()) { pEventType.setEventHook(true); - if (!(Type.EVENT_NAME_PREFIX + "ExecutionSample").equals(type.getName())) { + if (!pEventType.isMethodSampling()) { requestHooks.add(new RequestHook(pEventType)); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java index e6f98eb0e31..b6aae10dd91 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java @@ -278,4 +278,8 @@ public boolean isCommitable() { public int getStackTraceOffset() { return stackTraceOffset; } + + public boolean isMethodSampling() { + return isMethodSampling; + } } diff --git a/test/hotspot/jtreg/compiler/unsafe/UnsafeGetStableArrayElement.java b/test/hotspot/jtreg/compiler/unsafe/UnsafeGetStableArrayElement.java index 6c3f9d54f93..4a043c3f9ab 100644 --- a/test/hotspot/jtreg/compiler/unsafe/UnsafeGetStableArrayElement.java +++ b/test/hotspot/jtreg/compiler/unsafe/UnsafeGetStableArrayElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -224,12 +224,12 @@ static void testMatched(Callable c, Runnable setDefaultAction) throws Excepti } static void testMismatched(Callable c, Runnable setDefaultAction) throws Exception { - testMismatched(c, setDefaultAction, false); + testMismatched(c, setDefaultAction, false, true); } - static void testMismatched(Callable c, Runnable setDefaultAction, boolean objectArray) throws Exception { - if (Compiler.isGraalEnabled() && !objectArray) { - // Graal will constant fold mismatched reads from primitive stable arrays + static void testMismatched(Callable c, Runnable setDefaultAction, boolean objectArray, boolean aligned) throws Exception { + if (Compiler.isGraalEnabled() && !objectArray && aligned) { + // Graal will constant fold mismatched reads from primitive stable arrays, except unaligned ones run(c, setDefaultAction, null); } else { run(c, null, setDefaultAction); @@ -319,15 +319,15 @@ static void testUnsafeAccess() throws Exception { testMatched( Test::testD_D, Test::changeD); // Object[], aligned accesses - testMismatched(Test::testL_J, Test::changeL, true); // long & double are always as large as an OOP - testMismatched(Test::testL_D, Test::changeL, true); + testMismatched(Test::testL_J, Test::changeL, true, true); // long & double are always as large as an OOP + testMismatched(Test::testL_D, Test::changeL, true, true); testMatched( Test::testL_L, Test::changeL); // Unaligned accesses - testMismatched(Test::testS_U, Test::changeS); - testMismatched(Test::testC_U, Test::changeC); - testMismatched(Test::testI_U, Test::changeI); - testMismatched(Test::testJ_U, Test::changeJ); + testMismatched(Test::testS_U, Test::changeS, false, false); + testMismatched(Test::testC_U, Test::changeC, false, false); + testMismatched(Test::testI_U, Test::changeI, false, false); + testMismatched(Test::testJ_U, Test::changeJ, true, false); // No way to reliably check the expected behavior: // (1) OOPs change during GC; diff --git a/test/hotspot/jtreg/gc/g1/ihop/TestIHOPErgo.java b/test/hotspot/jtreg/gc/g1/ihop/TestIHOPErgo.java index 43dcdeeb788..a93232dd82e 100644 --- a/test/hotspot/jtreg/gc/g1/ihop/TestIHOPErgo.java +++ b/test/hotspot/jtreg/gc/g1/ihop/TestIHOPErgo.java @@ -30,6 +30,7 @@ * @requires !vm.flightRecorder * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @requires vm.opt.MaxGCPauseMillis == "null" + * @requires vm.compMode != "Xcomp" * @library /test/lib / * @modules java.base/jdk.internal.misc * @modules java.management diff --git a/test/hotspot/jtreg/gc/g1/ihop/TestIHOPStatic.java b/test/hotspot/jtreg/gc/g1/ihop/TestIHOPStatic.java index dd86af6ce36..22ce0eadf6d 100644 --- a/test/hotspot/jtreg/gc/g1/ihop/TestIHOPStatic.java +++ b/test/hotspot/jtreg/gc/g1/ihop/TestIHOPStatic.java @@ -28,6 +28,8 @@ * @requires vm.gc.G1 * @requires !vm.flightRecorder * @requires vm.opt.ExplicitGCInvokesConcurrent != true + * @requires !vm.graal.enabled + * @requires vm.compMode != "Xcomp" * @requires os.maxMemory > 1G * @library /test/lib / * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/jni/abstractMethod/AbstractMethodClass.jasm b/test/hotspot/jtreg/runtime/jni/abstractMethod/AbstractMethodClass.jasm new file mode 100644 index 00000000000..24c53f2032d --- /dev/null +++ b/test/hotspot/jtreg/runtime/jni/abstractMethod/AbstractMethodClass.jasm @@ -0,0 +1,43 @@ +/* + * 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. + * + */ +/* + * This is a non-abstract class with an abstract method. + * + */ +super public class AbstractMethodClass + extends java/lang/Object + version 51:0 // Java 7 version +{ + + public Method "":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + + public abstract Method "abstractM":"()V"; + +} diff --git a/test/hotspot/jtreg/runtime/jni/abstractMethod/TestJNIAbstractMethod.java b/test/hotspot/jtreg/runtime/jni/abstractMethod/TestJNIAbstractMethod.java new file mode 100644 index 00000000000..2384f6d5aef --- /dev/null +++ b/test/hotspot/jtreg/runtime/jni/abstractMethod/TestJNIAbstractMethod.java @@ -0,0 +1,68 @@ +/* + * 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 8323243 + * @summary Test that invocation of an abstract method from JNI works correctly + * @compile AbstractMethodClass.jasm + * @run main/othervm/native TestJNIAbstractMethod + */ + +/** + * We are testing invocation of an abstract method from JNI - which should + * simply result in throwning AbstractMethodError. To invoke an abstract method + * we must have an instance method (as abstract static methods are illegal), + * but instantiating an abstract class is also illegal at the Java language + * level, so we have to use a custom jasm class that contains an abstract method + * declaration, but which is not itself declared as an abstract class. + */ +public class TestJNIAbstractMethod { + + // Invokes an abstract method from JNI and throws AbstractMethodError. + private static native void invokeAbstractM(Class AMclass, + AbstractMethodClass receiver); + + static { + System.loadLibrary("JNIAbstractMethod"); + } + + public static void main(String[] args) { + AbstractMethodClass obj = new AbstractMethodClass(); + try { + System.out.println("Attempting direct invocation via Java"); + obj.abstractM(); + throw new RuntimeException("Did not get AbstractMethodError from Java!"); + } catch (AbstractMethodError expected) { + System.out.println("ok - got expected exception: " + expected); + } + try { + System.out.println("Attempting direct invocation via JNI"); + invokeAbstractM(obj.getClass(), obj); + throw new RuntimeException("Did not get AbstractMethodError from JNI!"); + } catch (AbstractMethodError expected) { + System.out.println("ok - got expected exception: " + expected); + } + } +} diff --git a/test/hotspot/jtreg/runtime/jni/abstractMethod/libJNIAbstractMethod.c b/test/hotspot/jtreg/runtime/jni/abstractMethod/libJNIAbstractMethod.c new file mode 100644 index 00000000000..35a28f7029a --- /dev/null +++ b/test/hotspot/jtreg/runtime/jni/abstractMethod/libJNIAbstractMethod.c @@ -0,0 +1,43 @@ +/* + * 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. + * + */ +#include +#include +#include + +JNIEXPORT void JNICALL Java_TestJNIAbstractMethod_invokeAbstractM(JNIEnv* env, + jclass this_cls, + jclass target_cls, + jobject receiver) { + + jmethodID mid = (*env)->GetMethodID(env, target_cls, "abstractM", "()V"); + if (mid == NULL) { + fprintf(stderr, "Error looking up method abstractM\n"); + (*env)->ExceptionDescribe(env); + exit(1); + } + + printf("Invoking abstract method ...\n"); + (*env)->CallVoidMethod(env, receiver, mid); // Should raise exception + +} diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/MHTransformationGen.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/MHTransformationGen.java index d2b2fe7252c..0cfaa300726 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/MHTransformationGen.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/MHTransformationGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import jdk.test.lib.Platform; + import nsk.share.test.LazyIntArrayToString; import nsk.share.test.TestUtils; import vm.mlvm.meth.share.transform.v2.MHArrayEnvelopeTFPair; @@ -70,45 +72,66 @@ public class MHTransformationGen { private static final boolean USE_SAM = false; // Disabled in JDK7 private static final boolean USE_THROW_CATCH = false; // Test bugs - private static final Optional NON_SEGMENTED_CODE_CACHE_POOL; - private static final Optional NON_NMETHODS_POOL; - private static final Optional PROFILED_NMETHODS_POOL; - private static final Optional NON_PROFILED_NMETHODS_POOL ; - - // Limit numbers are arbitrary, feel free to change if arguably necessary - private static final int NON_SEGMENTED_CACHE_ALLOWANCE = 2_000_000; - private static final int SEGMENTED_CACHE_ALLOWANCE = 1_000_000; - - static { - var pools = ManagementFactory.getMemoryPoolMXBeans(); - NON_SEGMENTED_CODE_CACHE_POOL = pools.stream() - .filter(pool -> pool.getName().equals("CodeCache")).findFirst(); - NON_NMETHODS_POOL = pools.stream() - .filter(pool -> pool.getName().equals("CodeHeap 'non-nmethods'")).findFirst(); - PROFILED_NMETHODS_POOL = pools.stream() - .filter(pool -> pool.getName().equals("CodeHeap 'profiled nmethods'")).findFirst(); - NON_PROFILED_NMETHODS_POOL = pools.stream() - .filter(pool -> pool.getName().equals("CodeHeap 'non-profiled nmethods'")).findFirst(); - } + /** + * The class is used for periodical checks if a code-cache consuming operation + * could be executed (i.e. if code cache has enought free space for a typical operation). + */ + private static class CodeCacheMonitor { + + private static final Optional NON_SEGMENTED_CODE_CACHE_POOL; + private static final Optional NON_NMETHODS_POOL; + private static final Optional PROFILED_NMETHODS_POOL; + private static final Optional NON_PROFILED_NMETHODS_POOL; + + // Trial runs show up that maximal increase in code cache consumption between checks (for one + // cycle/tree build in MHTransformationGen::createSequence), falls within the following intervals: + // + // | Threads number | Without Xcomp | With Xcomp | + // |----------------|---------------|------------| + // | 1 | 100-200 K | 400-500 K | + // | 10 | 1 - 2 M | 5-6 M | + // + // Those numbers are approximate (since trees are generated randomly and the total consumption + // between checks depends on how threads are aligned - for example, if all threads finish up their + // cycles approximately at one time, the consumption increase will be the highest, like with a + // resonance's amplitude) + // The 10 threads is chosen as it is a typical number for multi-threaded tests. + // + // Based on these numbers, values of 10 M for Xcomp and 5 M for non-Xcomp, were suggested. + private static final int NON_SEGMENTED_CACHE_ALLOWANCE = Platform.isComp() ? 10_000_000 : 5_000_000; + private static final int SEGMENTED_CACHE_ALLOWANCE = Platform.isComp() ? 10_000_000 : 5_000_000; + + static { + var pools = ManagementFactory.getMemoryPoolMXBeans(); + NON_SEGMENTED_CODE_CACHE_POOL = pools.stream() + .filter(pool -> pool.getName().equals("CodeCache")).findFirst(); + NON_NMETHODS_POOL = pools.stream() + .filter(pool -> pool.getName().equals("CodeHeap 'non-nmethods'")).findFirst(); + PROFILED_NMETHODS_POOL = pools.stream() + .filter(pool -> pool.getName().equals("CodeHeap 'profiled nmethods'")).findFirst(); + NON_PROFILED_NMETHODS_POOL = pools.stream() + .filter(pool -> pool.getName().equals("CodeHeap 'non-profiled nmethods'")).findFirst(); + } - public static class ThrowCatchTestException extends Throwable { - private static final long serialVersionUID = -6749961303738648241L; - } + public static final boolean isCodeCacheEffectivelyFull() { + var result = new Object() { boolean value = false; }; - private static final boolean isCodeCacheEffectivelyFull() { - var result = new Object() { boolean value = false; }; + BiConsumer check = (pool, limit) -> { + var usage = pool.getUsage(); + result.value |= usage.getMax() - usage.getUsed() < limit; + }; - BiConsumer check = (pool, limit) -> { - var usage = pool.getUsage(); - result.value |= usage.getMax() - usage.getUsed() < limit; - }; + NON_SEGMENTED_CODE_CACHE_POOL.ifPresent(pool -> check.accept(pool, NON_SEGMENTED_CACHE_ALLOWANCE)); + NON_NMETHODS_POOL.ifPresent(pool -> check.accept(pool, SEGMENTED_CACHE_ALLOWANCE)); + PROFILED_NMETHODS_POOL.ifPresent(pool -> check.accept(pool, SEGMENTED_CACHE_ALLOWANCE)); + NON_PROFILED_NMETHODS_POOL.ifPresent(pool -> check.accept(pool, SEGMENTED_CACHE_ALLOWANCE)); - NON_SEGMENTED_CODE_CACHE_POOL.ifPresent(pool -> check.accept(pool, NON_SEGMENTED_CACHE_ALLOWANCE)); - NON_NMETHODS_POOL.ifPresent(pool -> check.accept(pool, SEGMENTED_CACHE_ALLOWANCE)); - PROFILED_NMETHODS_POOL.ifPresent(pool -> check.accept(pool, SEGMENTED_CACHE_ALLOWANCE)); - NON_PROFILED_NMETHODS_POOL.ifPresent(pool -> check.accept(pool, SEGMENTED_CACHE_ALLOWANCE)); + return result.value; + } + }; - return result.value; + public static class ThrowCatchTestException extends Throwable { + private static final long serialVersionUID = -6749961303738648241L; } @SuppressWarnings("unused") @@ -133,7 +156,7 @@ public static MHMacroTF createSequence(Argument finalRetVal, Object boundObj, Me final int cyclesToBuild = nextInt(MAX_CYCLES); for ( int i = 0; i < cyclesToBuild; i++) { - if (isCodeCacheEffectivelyFull()) { + if (CodeCacheMonitor.isCodeCacheEffectivelyFull()) { Env.traceNormal("Not enought code cache to build up MH sequences anymore. " + " Has only been able to achieve " + i + " out of " + cyclesToBuild); break; diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 25d6e8f6bc3..bdebafc0594 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -607,8 +607,6 @@ sun/security/pkcs11/ec/TestKeyFactory.java 8026976 generic- sun/security/pkcs11/KeyStore/ClientAuth.sh 8254806 solaris-all sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic-all -sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all - javax/net/ssl/DTLS/PacketLossRetransmission.java 8169086 macosx-x64 javax/net/ssl/DTLS/RespondToRetransmit.java 8169086 macosx-all javax/net/ssl/DTLS/CipherSuite.java 8202059 macosx-x64 diff --git a/test/jdk/java/awt/Clipboard/DelayedQueryTest.java b/test/jdk/java/awt/Clipboard/DelayedQueryTest.java new file mode 100644 index 00000000000..857a6f79707 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/DelayedQueryTest.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2000, 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 4085183 8000630 + @summary tests that clipboard contents is retrieved even if the app didn't + receive native events for a long time. + @requires (os.family != "mac") + @key headful + @run main DelayedQueryTest +*/ + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +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.event.InputEvent; +import java.io.File; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; + +public class DelayedQueryTest implements ClipboardOwner, Runnable { + int returnCode = Child.CHILD_RETURN_CODE_NOT_READY; + + Process childProcess = null; + Frame frame; + + public static void main(String[] args) + throws InterruptedException, InvocationTargetException { + String osName = System.getProperty("os.name"); + if (osName.toLowerCase().contains("os x")) { + System.out.println("This test is not for MacOS, considered passed."); + return; + } + DelayedQueryTest delayedQueryTest = new DelayedQueryTest(); + EventQueue.invokeAndWait(delayedQueryTest::initAndShowGui); + try { + delayedQueryTest.start(); + } finally { + EventQueue.invokeAndWait(() -> delayedQueryTest.frame.dispose()); + } + } + + public void initAndShowGui(){ + frame = new Frame("DelayedQueryTest"); + frame.add(new Panel()); + frame.setBounds(200,200, 200, 200); + frame.setVisible(true); + } + + public void start() { + try { + Robot robot = new Robot(); + // Some mouse activity to update the Xt time stamp at + // the parent process. + robot.delay(1000); + robot.waitForIdle(); + + Point p = frame.getLocationOnScreen(); + robot.mouseMove(p.x + 100, p.y + 100); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } catch (AWTException e) { + e.printStackTrace(); + throw new RuntimeException("The test failed."); + } + Child.sysClipboard.setContents(Child.transferable, this); + + String javaPath = System.getProperty("java.home", ""); + String[] command = { + javaPath + File.separator + "bin" + File.separator + "java", + "-cp", System.getProperty("test.classes", "."), + "Child" + }; + + try { + Process process = Runtime.getRuntime().exec(command); + childProcess = process; + returnCode = process.waitFor(); + childProcess = null; + + InputStream errorStream = process.getErrorStream(); + int count = errorStream.available(); + if (count > 0) { + byte[] b = new byte[count]; + errorStream.read(b); + System.err.println("========= Child VM System.err ========"); + System.err.print(new String(b)); + System.err.println("======================================"); + } + } catch (Throwable e) { + e.printStackTrace(); + throw new RuntimeException("The test failed."); + } + if (returnCode != Child.CHILD_RETURN_CODE_OK) { + System.err.println("Child VM: returned " + returnCode); + throw new RuntimeException("The test failed."); + } + } // start() + + public void lostOwnership(Clipboard clipboard, + Transferable contents) { + // At this moment the child process has definitely started. + // So we can try to retrieve the clipboard contents set + // by the child process. + new Thread(this).start(); + } + + public void run() { + // We are going to check if it is possible to retrieve the data + // after the child process has set the clipboard contents twice, + // since after the first setting the retrieval is always successful. + // So we wait to let the child process set the clipboard contents + // twice. + try { + Thread.sleep(Child.CHILD_SELECTION_CHANGE_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + try { + String s = (String)Child.sysClipboard + .getContents(null) + .getTransferData(DataFlavor.stringFlavor); + if (!"String".equals(s)) { + System.err.println("Data retrieved: " + s); + throw new RuntimeException("Retrieved data is incorrect."); + } + } catch (Exception e) { + e.printStackTrace(); + if (childProcess != null) { + childProcess.destroy(); + childProcess = null; + } + throw new RuntimeException("Failed to retrieve the data."); + } + Child.sysClipboard.setContents(Child.transferable, null); + } +} + +class Child { + static final Clipboard sysClipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + static final Transferable transferable = new StringSelection("String"); + + /* + * Timeouts. + */ + static final int FRAME_ACTIVATION_TIMEOUT = 1000; + static final int PARENT_TIME_STAMP_TIMEOUT = 1000; + static final int CHILD_SELECTION_CHANGE_TIMEOUT = + FRAME_ACTIVATION_TIMEOUT + PARENT_TIME_STAMP_TIMEOUT + 5000; + static final int PARENT_RETRIEVE_DATA_TIMEOUT = 10000; + + /* + * Child process return codes. + */ + static final int CHILD_RETURN_CODE_NOT_READY = -1; + static final int CHILD_RETURN_CODE_OK = 0; + static final int CHILD_RETURN_CODE_UNEXPECTED_EXCEPTION = 1; + static final int CHILD_RETURN_CODE_OTHER_FAILURE = 2; + static Button button; + + static void initAndShowGui() { + final Frame frame = new Frame(); + button = new Button("button"); + frame.add(button); + frame.pack(); + frame.setLocation(100, 100); + frame.setVisible(true); + } + + public static void main(String[] args) { + sysClipboard.setContents( + new StringSelection("First String"), null); + + // Some mouse activity to update the Xt time stamp at + // the child process. + try { + EventQueue.invokeAndWait(Child::initAndShowGui); + try { + Thread.sleep(FRAME_ACTIVATION_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + System.exit(CHILD_RETURN_CODE_UNEXPECTED_EXCEPTION); + } + + Robot robot = new Robot(); + robot.waitForIdle(); + + Point p = button.getLocationOnScreen(); + robot.mouseMove(p.x + 10, p.y + 10); + // Wait to let the Xt time stamp become out-of-date. + try { + Thread.sleep(PARENT_TIME_STAMP_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + System.exit(CHILD_RETURN_CODE_UNEXPECTED_EXCEPTION); + } + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } catch (Exception e) { + e.printStackTrace(); + System.exit(CHILD_RETURN_CODE_UNEXPECTED_EXCEPTION); + } + + sysClipboard.setContents(transferable, new ClipboardOwner() { + public void lostOwnership(Clipboard clipboard, + Transferable contents) { + System.exit(CHILD_RETURN_CODE_OK); + } + }); + // Wait to let the parent process retrieve the data. + try { + Thread.sleep(PARENT_RETRIEVE_DATA_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // Parent failed to set clipboard contents, so we signal test failure + System.exit(CHILD_RETURN_CODE_OTHER_FAILURE); + } +} diff --git a/test/jdk/java/awt/Clipboard/NullContentsTest.java b/test/jdk/java/awt/Clipboard/NullContentsTest.java new file mode 100644 index 00000000000..6d4031b49eb --- /dev/null +++ b/test/jdk/java/awt/Clipboard/NullContentsTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2000, 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 4378007 4250859 + @summary Verifies that setting the contents of the system Clipboard to null + throws a NullPointerException + @key headful + @run main NullContentsTest +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; + +public class NullContentsTest { + + public static void main(String[] args) { + // Clipboard.setContents(null, foo) should throw an NPE, but + // Clipboard.setContents(bar, foo), where bar.getTransferData(baz) + // returns null, should not. + Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); + try { + clip.setContents(null, null); + } catch (NullPointerException e) { + StringSelection ss = new StringSelection(null); + try { + clip.setContents(ss, null); + } catch (NullPointerException ee) { + throw new RuntimeException("test failed: null transfer data"); + } + System.err.println("test passed"); + return; + } + throw new RuntimeException("test failed: null Transferable"); + } +} diff --git a/test/jdk/java/awt/Clipboard/SerializeLocalFlavorTest.java b/test/jdk/java/awt/Clipboard/SerializeLocalFlavorTest.java new file mode 100644 index 00000000000..90b9f0cd305 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/SerializeLocalFlavorTest.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2006, 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 4696186 + @summary tests that NotSerializableException is not printed in the console if + non-serializable object with DataFlavor.javaJVMLocalObjectMimeType + is set into the clipboard + @key headful + @run main SerializeLocalFlavorTest +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.File; +import java.io.InputStream; +import java.io.Serializable; + + +public class SerializeLocalFlavorTest { + private boolean failed = false; + + public static void main(String[] args) { + new SerializeLocalFlavorTest().start(); + } + + public void start () { + try { + String[] command = { + System.getProperty("java.home", "") + + File.separator + "bin" + File.separator + + "java", + "-cp", + System.getProperty("test.classes", "."), + "Child" + }; + + Process process = Runtime.getRuntime().exec(command); + ProcessResults pres = ProcessResults.doWaitFor(process); + + if (pres.stderr != null && pres.stderr.length() > 0) { + System.err.println("========= Child err ========"); + System.err.print(pres.stderr); + System.err.println("======================================"); + } + + if (pres.stdout != null && pres.stdout.length() > 0) { + System.err.println("========= Child out ========"); + System.err.print(pres.stdout); + System.err.println("======================================"); + } + + if (pres.stderr.indexOf("java.io.NotSerializableException") >= 0) { + failed = true; + } + + } catch (Exception e) { + e.printStackTrace(); + } + + if (failed) { + throw new RuntimeException( + "The test failed: java.io.NotSerializableException printed!"); + } else { + System.err.println("The test passed!"); + } + } +} + +class Child { + public static void main (String [] args) throws Exception { + NotSerializableLocalTransferable t = + new NotSerializableLocalTransferable(new NotSer()); + Toolkit.getDefaultToolkit() + .getSystemClipboard().setContents(t, null); + } +} + +class NotSerializableLocalTransferable implements Transferable { + public final DataFlavor flavor; + + private final DataFlavor[] flavors; + + private final Object data; + + + public NotSerializableLocalTransferable(Object data) throws Exception { + this.data = data; + flavor = new DataFlavor( + DataFlavor.javaJVMLocalObjectMimeType + + ";class=" + "\"" + data.getClass().getName() + "\""); + this.flavors = new DataFlavor[] { flavor }; + } + + public DataFlavor[] getTransferDataFlavors() { + return flavors.clone(); + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return this.flavor.equals(flavor); + } + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException + { + if (this.flavor.equals(flavor)) { + return (Object)data; + } + throw new UnsupportedFlavorException(flavor); + } + +} + +class NotSer implements Serializable { + private Object field = new Object(); // not serializable field +} + +class ProcessResults { + public int exitValue; + public String stdout; + public String stderr; + + public ProcessResults() { + exitValue = -1; + stdout = ""; + stderr = ""; + } + + /** + * Method to perform a "wait" for a process and return its exit value. + * This is a workaround for Process.waitFor() never returning. + */ + public static ProcessResults doWaitFor(Process p) { + ProcessResults pres = new ProcessResults(); + + InputStream in = null; + InputStream err = null; + + try { + in = p.getInputStream(); + err = p.getErrorStream(); + + boolean finished = false; + + while (!finished) { + try { + while (in.available() > 0) { + pres.stdout += (char)in.read(); + } + while (err.available() > 0) { + pres.stderr += (char)err.read(); + } + // Ask the process for its exitValue. If the process + // is not finished, an IllegalThreadStateException + // is thrown. If it is finished, we fall through and + // the variable finished is set to true. + pres.exitValue = p.exitValue(); + finished = true; + } + catch (IllegalThreadStateException e) { + // Process is not finished yet; + // Sleep a little to save on CPU cycles + Thread.sleep(500); + } + } + if (in != null) in.close(); + if (err != null) err.close(); + } + catch (Throwable e) { + System.err.println("doWaitFor(): unexpected exception"); + e.printStackTrace(); + } + return pres; + } +} diff --git a/test/jdk/java/awt/ColorClass/ColorSerializationTest.java b/test/jdk/java/awt/ColorClass/ColorSerializationTest.java new file mode 100644 index 00000000000..b0e661b3cfb --- /dev/null +++ b/test/jdk/java/awt/ColorClass/ColorSerializationTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2006, 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 4330102 + @summary Tests that Color object is serializable + @run main ColorSerializationTest +*/ + +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.IndexColorModel; +import java.io.ObjectOutputStream; +import java.io.ByteArrayOutputStream; + +public class ColorSerializationTest { + + public static void main(String[] args) { + java.awt.Color cobj = new java.awt.Color(255, 255, 255); + try { + cobj.createContext( + new IndexColorModel( + 8, 1, + new byte[]{0}, new byte[]{0}, new byte[]{0}), + new Rectangle(1, 1, 2, 3), + new Rectangle(3, 3), + new AffineTransform(), + new RenderingHints(null)); + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + ObjectOutputStream objos = new ObjectOutputStream(ostream); + objos.writeObject(cobj); + objos.close(); + System.out.println("Test PASSED"); + } catch (java.io.IOException e) { + System.out.println("Test FAILED"); + throw new RuntimeException("Test FAILED: Color is not serializable: " + e.getMessage()); + } + + } +} diff --git a/test/jdk/java/nio/file/Files/CopyAndMove.java b/test/jdk/java/nio/file/Files/CopyAndMove.java index 981fb332fc0..48e06159b45 100644 --- a/test/jdk/java/nio/file/Files/CopyAndMove.java +++ b/test/jdk/java/nio/file/Files/CopyAndMove.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -892,7 +892,7 @@ static void testCopyFileToFile(Path dir1, Path dir2, boolean supportsLinks) if (supportsLinks) { source = createSourceFile(dir1); link = dir1.resolve("link"); - createSymbolicLink(link, source); + createSymbolicLink(link, source.getFileName()); target = getTargetFile(dir2); copyAndVerify(link, target); delete(link); diff --git a/test/jdk/java/security/cert/CertPathBuilder/akiExt/AKISerialNumber.java b/test/jdk/java/security/cert/CertPathBuilder/akiExt/AKISerialNumber.java index e8ab65d78dd..53db87cfe63 100644 --- a/test/jdk/java/security/cert/CertPathBuilder/akiExt/AKISerialNumber.java +++ b/test/jdk/java/security/cert/CertPathBuilder/akiExt/AKISerialNumber.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 @@ -118,6 +118,8 @@ public static void main(String[] args) throws Exception { PKIXBuilderParameters params = new PKIXBuilderParameters (Collections.singleton(anchor), sel); params.setRevocationEnabled(false); + // Set date to 2024-01-01 to satisfy cert constraints + params.setDate(new java.util.Date(1704067200000l)); ArrayList certs = new ArrayList<>(); certs.add(intCert); diff --git a/test/jdk/javax/swing/text/CompositeView/bug4398059.java b/test/jdk/javax/swing/text/CompositeView/bug4398059.java new file mode 100644 index 00000000000..544db4c6827 --- /dev/null +++ b/test/jdk/javax/swing/text/CompositeView/bug4398059.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001, 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. + */ + +import java.awt.Robot; +import java.awt.Shape; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.Position; +import javax.swing.text.StyleConstants; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; +import javax.swing.text.html.HTML; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.ParagraphView; + +/* + * @test + * @bug 4398059 + * @key headful + * @summary Tests that CompositeView doesn't throw NPE. + */ + +public class bug4398059 { + private static JFrame jFrame; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(bug4398059::createAndShowUI); + robot.waitForIdle(); + robot.delay(1000); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (jFrame != null) { + jFrame.dispose(); + } + }); + } + } + + public static void createAndShowUI() { + String text = "

text"; + jFrame = new JFrame("CompositeView Test"); + JEditorPane jep = new JEditorPane(); + jep.setEditorKit(new MyHTMLEditorKit()); + jep.setText(text); + + Document doc = jep.getDocument(); + jep.setCaretPosition(doc.getLength() - 1); + + jFrame.getContentPane().add(jep); + jFrame.setSize(200,200); + jFrame.setVisible(true); + } + + static class MyHTMLEditorKit extends HTMLEditorKit { + private static final ViewFactory defaultFactory = new MyHTMLFactory(); + + public ViewFactory getViewFactory() { + return defaultFactory; + } + + static class MyHTMLFactory extends HTMLEditorKit.HTMLFactory { + public View create(Element elem) { + Object obj = elem.getAttributes().getAttribute(StyleConstants.NameAttribute); + if (obj instanceof HTML.Tag) { + HTML.Tag kind = (HTML.Tag) obj; + if (kind == HTML.Tag.H1) { + return new MyParagraphView(elem); + } + } + return super.create(elem); + } + } + + static class MyParagraphView extends ParagraphView { + public MyParagraphView(Element elem) { + super(elem); + } + + public Shape getChildAllocation(int index, Shape a) { + return null; + } + + public Shape modelToView(int pos, Shape a, Position.Bias b) + throws BadLocationException { + return super.modelToView(pos, a, b); + } + } + } +} diff --git a/test/jdk/javax/swing/text/DefaultCaret/bug4197894.java b/test/jdk/javax/swing/text/DefaultCaret/bug4197894.java new file mode 100644 index 00000000000..11bb163860b --- /dev/null +++ b/test/jdk/javax/swing/text/DefaultCaret/bug4197894.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999, 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. + */ + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4197894 + * @key headful + * @summary Tests if shift-click adjusts selection in text areas. + */ + +public class bug4197894 { + private static JFrame jFrame; + private static JTextArea ta; + + private static volatile Point point = null; + private static volatile Rectangle bounds; + + private static volatile boolean passed = true; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.setAutoWaitForIdle(true); + + SwingUtilities.invokeAndWait(bug4197894::createAndShowUI); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + point = ta.getLocationOnScreen(); + bounds = ta.getBounds(); + }); + robot.waitForIdle(); + robot.delay(300); + + robot.mouseMove((point.x + bounds.width / 4), + (point.y + bounds.height / 4)); + + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.delay(300); + + if (!passed) { + throw new RuntimeException("Test failed." + + " Shift-Click Text Selection does not work!"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (jFrame != null) { + jFrame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + jFrame = new JFrame("Shift-Click Text Selection"); + ta = new JTextArea(); + ta.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + String selText = ta.getSelectedText(); + passed = !(selText == null || (selText.length() == 0)); + } + }); + ta.setText("12345\n12345\n12345\n12345\n12345\n12345\n12345"); + ta.setCaretPosition(ta.getDocument().getLength()); + jFrame.getContentPane().add(ta); + jFrame.pack(); + jFrame.setLocationRelativeTo(null); + jFrame.setAlwaysOnTop(true); + jFrame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/text/DefaultCaret/bug4203175.java b/test/jdk/javax/swing/text/DefaultCaret/bug4203175.java new file mode 100644 index 00000000000..8a15644bf91 --- /dev/null +++ b/test/jdk/javax/swing/text/DefaultCaret/bug4203175.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2000, 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. + */ + +import java.awt.Container; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4203175 + * @key headful + * @summary Tests that double-click on disabled JTextField doesn't + * cause other text-field to select content. + */ + +public class bug4203175 { + private static JFrame jFrame; + private static JTextField tf1, tf2; + private static JButton b; + private static volatile Point point; + private static volatile boolean passed = true; + private static int clicks = 0; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.setAutoWaitForIdle(true); + + SwingUtilities.invokeAndWait(bug4203175::createAndShowUI); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> point = tf1.getLocationOnScreen()); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(200); + + SwingUtilities.invokeAndWait(() -> point = b.getLocationOnScreen()); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(200); + + SwingUtilities.invokeAndWait(() -> point = tf2.getLocationOnScreen()); + robot.mouseMove(point.x, point.y); + 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.delay(200); + + if (!passed) { + throw new RuntimeException("Test failed!! Text selection on disabled" + + " TextField does not work as expected!"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (jFrame != null) { + jFrame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + jFrame = new JFrame("JTextField Text Selection"); + Container cont = jFrame.getContentPane(); + cont.setLayout(new BoxLayout(cont, BoxLayout.Y_AXIS)); + + tf1 = new JTextField(20); + tf1.setText("sometext"); + tf1.setName("Field 1"); + tf1.setCaretPosition(tf1.getDocument().getLength()); + cont.add(tf1); + + tf2 = new JTextField(20); + tf2.setName("Field 2"); + tf2.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + clicks++; + if (clicks == 2) { + String selText = tf1.getSelectedText(); + passed = (selText == null || (selText.length() == 0)); + } + } + }); + cont.add(tf2); + + b = new JButton("Toggle Enabled"); + cont.add(b); + b.addActionListener(e -> { + if (e.getSource() == b) { + boolean b = tf1.isEnabled(); + tf1.setEnabled(!b); + tf2.setEnabled(!b); + } + }); + + jFrame.pack(); + jFrame.setLocationRelativeTo(null); + jFrame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/text/DefaultEditorKit/bug4265242.java b/test/jdk/javax/swing/text/DefaultEditorKit/bug4265242.java new file mode 100644 index 00000000000..d797b587858 --- /dev/null +++ b/test/jdk/javax/swing/text/DefaultEditorKit/bug4265242.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1999, 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. + */ + +import java.awt.event.ActionEvent; +import javax.swing.Action; +import javax.swing.JTextPane; +import javax.swing.text.DefaultEditorKit; + +/* + * @test + * @bug 4265242 + * @summary Tests endParagraphAction in JTextPane + */ + +public class bug4265242 { + public static void main(String[] args) { + JTextPane jTextPane = new JTextPane(); + jTextPane.setText("Merry sparrow"); + + Action[] actions = jTextPane.getActions(); + Action endPara = null; + for (Action action : actions) { + String name = (String) action.getValue(Action.NAME); + if (name.equals(DefaultEditorKit.endParagraphAction)) { + endPara = action; + } + } + endPara.actionPerformed(new ActionEvent(jTextPane, + ActionEvent.ACTION_PERFORMED, + DefaultEditorKit.endParagraphAction)); + } +} diff --git a/test/jdk/javax/swing/text/DefaultStyledDocument/bug4472852.java b/test/jdk/javax/swing/text/DefaultStyledDocument/bug4472852.java new file mode 100644 index 00000000000..cb9b4e654b3 --- /dev/null +++ b/test/jdk/javax/swing/text/DefaultStyledDocument/bug4472852.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001, 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. + */ + +import java.awt.Color; +import javax.swing.text.DefaultStyledDocument; +import javax.swing.text.Element; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; + +/* + * @test + * @bug 4472852 + * @summary Tests DefaultStyledDocument.split(int, int) + */ + +public class bug4472852 { + + public static void main(String[] args) throws Exception { + // create a Document and insert some text there + StyledDocument doc = new DefaultStyledDocument(); + doc.insertString(0, "this", null); + + // add style to the last word + Element root = doc.getDefaultRootElement(); + int end = root.getEndOffset(); + MutableAttributeSet as = new SimpleAttributeSet(); + StyleConstants.setBackground(as, Color.BLUE); + doc.setCharacterAttributes(end-5, 5, as, true); + + // inspect Elements of the only Paragraph -- + // there should be no empty Elements + Element para = root.getElement(0); + for (int i = 0; i < para.getElementCount(); i++) { + Element el = para.getElement(i); + if (el.getStartOffset() == el.getEndOffset()) { + throw new RuntimeException("Failed: empty Element found"); + } + } + } +} diff --git a/test/jdk/javax/swing/text/html/TableView/bug4813831.java b/test/jdk/javax/swing/text/html/TableView/bug4813831.java new file mode 100644 index 00000000000..4d7f286f8aa --- /dev/null +++ b/test/jdk/javax/swing/text/html/TableView/bug4813831.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2003, 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 4813831 + * @summary Verifies contents of table cells in HTML in JEditorPane wraps correctly + * @key headful + * @run main bug4813831 +*/ + +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.View; +import javax.swing.text.ParagraphView; +import javax.swing.text.html.HTMLEditorKit; + +import java.awt.Robot; +import java.awt.Shape; + +public class bug4813831 { + + private static boolean passed = false; + private boolean finished = false; + + private static JEditorPane jep; + private static JFrame f; + + public void init() { + + String text = + "" + + "" + + "" + + "
XXXXXXXXXXXXXX
X
X
" + + ""; + + f = new JFrame(); + jep = new JEditorPane(); + jep.setEditorKit(new HTMLEditorKit()); + jep.setEditable(false); + + jep.setText(text); + + f.getContentPane().add(jep); + f.setSize(20,500); + f.setLocationRelativeTo(null); + f.setVisible(true); + } + + + public static void main(String args[]) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + bug4813831 test = new bug4813831(); + try { + SwingUtilities.invokeAndWait(() -> test.init()); + robot.waitForIdle(); + robot.delay(1000); + Shape r = jep.getBounds(); + View v = jep.getUI().getRootView(jep); + do { + int n = v.getViewCount(); + Shape sh = v.getChildAllocation(n - 1, r); + if (sh != null) { + r = sh; + } + v = v.getView(n - 1); + } while (!(v instanceof ParagraphView)); + + int n = v.getViewCount(); + // there should be 3 lines or more (if the first long line was wrapped) in a cell + passed = n >= 3; + + if (passed) { + Shape sh = v.getChildAllocation(n - 2, r); + int x1 = sh.getBounds().x; + sh = v.getChildAllocation(n - 1, r); + int x2 = sh.getBounds().x; + System.out.println("x1: " + x1 + " x2: " + x2); + // lines should be equally aligned + passed = (x1 == x2); + } + if (!passed) { + throw new RuntimeException("Test failed."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/tree/DefaultTreeCellEditor/bug4480602.java b/test/jdk/javax/swing/tree/DefaultTreeCellEditor/bug4480602.java new file mode 100644 index 00000000000..d9073297a52 --- /dev/null +++ b/test/jdk/javax/swing/tree/DefaultTreeCellEditor/bug4480602.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2003, 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 4480602 + * @summary Verifies if DefaultTreeCellEditor.inHitRegion() incorrectly + * handles row bounds + * @key headful + * @run main bug4480602 +*/ + +import java.awt.ComponentOrientation; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.MouseEvent; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellEditor; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.SwingUtilities; + +import java.util.Date; + +public class bug4480602 { + + static JTree tree; + static JFrame fr; + static MyTreeCellEditor editor; + + static Robot robot; + boolean passed = false; + boolean do_test = false; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + try { + SwingUtilities.invokeAndWait(() -> { + fr = new JFrame("Test"); + + String s = "0\u05D01\u05D02\u05D03\u05D04\u05D05"; + DefaultMutableTreeNode root = new DefaultMutableTreeNode(s); + root.add(new DefaultMutableTreeNode(s)); + root.add(new DefaultMutableTreeNode(s)); + + tree = new JTree(root); + editor = new MyTreeCellEditor(tree, new DefaultTreeCellRenderer()); + tree.setCellEditor(editor); + tree.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + tree.setEditable(true); + JScrollPane sp = new JScrollPane(tree); + fr.getContentPane().add(sp); + + fr.setSize(250,200); + fr.setLocationRelativeTo(null); + fr.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + Rectangle rect = tree.getRowBounds(1); + editor.testTreeCellEditor(rect); + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (fr != null) { + fr.dispose(); + } + }); + } + } + + static class MyTreeCellEditor extends DefaultTreeCellEditor { + + public MyTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) { + super(tree, renderer); + } + + public void testTreeCellEditor(Rectangle rect) { + int x = rect.x + 10; + int y = rect.y + rect.height / 2; + MouseEvent me = new MouseEvent(tree, + MouseEvent.MOUSE_PRESSED, + (new Date()).getTime(), + MouseEvent.BUTTON1_DOWN_MASK, + rect.x + 10, rect.y + 10, + 1, true); + isCellEditable(me); + + if (tree == null) { + throw new RuntimeException("isCellEditable() should set the tree"); + } + if (lastRow != 1) { + throw new RuntimeException("isCellEditable() should set the lastRow"); + } + if (offset == 0) { + throw new RuntimeException("isCellEditable() should determine offset"); + } + + if (!inHitRegion(x,y)) { + throw new RuntimeException("Hit region should contain point ("+x+", "+y+")"); + } + x = rect.x + rect.width - 10; + if (inHitRegion(x,y)) { + throw new RuntimeException("Hit region shouldn't contain point ("+x+", "+y+")"); + } + } + } + +} diff --git a/test/jdk/javax/swing/tree/DefaultTreeCellRenderer/bug4180224.java b/test/jdk/javax/swing/tree/DefaultTreeCellRenderer/bug4180224.java new file mode 100644 index 00000000000..f9d88f29acf --- /dev/null +++ b/test/jdk/javax/swing/tree/DefaultTreeCellRenderer/bug4180224.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1999, 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 4180224 + * @summary DefaultTreeCellRenderer.hasFocus protected (not private) now. + * @key headful + * @run main bug4180224 +*/ + +import javax.swing.tree.DefaultTreeCellRenderer; + +public class bug4180224 { + + static class MyDTCR extends DefaultTreeCellRenderer { + void test() { + hasFocus = false; + } + } + + public static void main(String[] argv) { + MyDTCR m = new MyDTCR(); + m.test(); + } +} diff --git a/test/jdk/javax/swing/tree/FixedHeightLayoutCache/bug4745001.java b/test/jdk/javax/swing/tree/FixedHeightLayoutCache/bug4745001.java new file mode 100644 index 00000000000..d2beface3c2 --- /dev/null +++ b/test/jdk/javax/swing/tree/FixedHeightLayoutCache/bug4745001.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2002, 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 4745001 + * @summary JTree with setLargeModel(true) not display correctly + * when we expand/collapse nodes + * @key headful + * @run main bug4745001 +*/ + +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Robot; + +import javax.swing.JFrame; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.SwingUtilities; + +public class bug4745001 { + + static JTree tree; + static JFrame fr; + boolean stateChanged; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + bug4745001 test = new bug4745001(); + try { + SwingUtilities.invokeAndWait(() -> test.init()); + robot.waitForIdle(); + robot.delay(1000); + test.start(); + robot.delay(1000); + test.destroy(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (fr != null) { + fr.dispose(); + } + }); + } + } + + public void init() { + fr = new JFrame("Test"); + fr.getContentPane().setLayout(new FlowLayout()); + + tree = new JTree(); + tree.setRowHeight(20); + tree.setLargeModel(true); + tree.setPreferredSize(new Dimension(100, 400)); + tree.setRootVisible(false); + tree.setShowsRootHandles(true); + + DefaultMutableTreeNode root = new DefaultMutableTreeNode(""); + DefaultMutableTreeNode a = new DefaultMutableTreeNode("a"); + DefaultMutableTreeNode b = new DefaultMutableTreeNode("b"); + DefaultMutableTreeNode c = new DefaultMutableTreeNode("c"); + root.add(a); + root.add(b); + root.add(c); + b.add(new DefaultMutableTreeNode("b1")); + c.add(new DefaultMutableTreeNode("c2")); + tree.setModel(new DefaultTreeModel(root)); + + fr.getContentPane().add(tree); + + tree.addTreeExpansionListener(new TreeExpansionListener() { + public void treeExpanded(TreeExpansionEvent e) { + TreePath path = e.getPath(); + if (path != null) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode)path.getLastPathComponent(); + node.removeAllChildren(); + String s = (String)node.getUserObject(); + node.add(new DefaultMutableTreeNode(s + "1")); + node.add(new DefaultMutableTreeNode(s + "2")); + node.add(new DefaultMutableTreeNode(s + "3")); + DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); + model.nodeStructureChanged(node); + synchronized (bug4745001.this) { + stateChanged = true; + bug4745001.this.notifyAll(); + } + } + } + + public void treeCollapsed(TreeExpansionEvent e) { + synchronized (bug4745001.this) { + stateChanged = true; + bug4745001.this.notifyAll(); + } + } + }); + + fr.pack(); + fr.setVisible(true); + } + + void changeNodeStateForRow(final int row, final boolean expand) throws Exception { + try { + stateChanged = false; + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + if (expand) { + tree.expandRow(row); + } else { + tree.collapseRow(row); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }); + synchronized (this) { + while (!stateChanged) { + bug4745001.this.wait(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public void start() throws Exception { + // expand node "c" + changeNodeStateForRow(2, true); + // expand node "b" + changeNodeStateForRow(1, true); + // collapse node "c" + changeNodeStateForRow(1, false); + } + + String[] expected = new String[] {"a", "b", "c", "c1", "c2", "c3"}; + + public void destroy() { + for (int i = 0; i < expected.length; i++) { + Object obj = tree.getPathForRow(i).getLastPathComponent(); + if (!obj.toString().equals(expected[i])) { + throw new RuntimeException("Unexpected node at row "+i); + } + } + } + +} diff --git a/test/jdk/sun/security/tools/keytool/ExportPrivateKeyNoPwd.java b/test/jdk/sun/security/tools/keytool/ExportPrivateKeyNoPwd.java deleted file mode 100644 index 799bf455b23..00000000000 --- a/test/jdk/sun/security/tools/keytool/ExportPrivateKeyNoPwd.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.security.*; - -/* - * Export a private key from the named keychain entry without supplying a - * password. See JDK-8062264. - * - * NOTE: Keychain access controls must already have been lowered to permit - * the target entry to be accessed. - */ -public class ExportPrivateKeyNoPwd { - - public static final void main(String[] args) throws Exception { - - if (args.length != 1) { - throw new Exception( - "ExportPrivateKeyNoPwd: must supply name of a keystore entry"); - } - String alias = args[0]; - - KeyStore ks = KeyStore.getInstance("KeychainStore"); - System.out.println("ExportPrivateKeyNoPwd: loading keychains..."); - ks.load(null, null); - - System.out.println("ExportPrivateKeyNoPwd: exporting key..."); - Key key = ks.getKey(alias, null); - if (key instanceof PrivateKey) { - System.out.println("ExportPrivateKeyNoPwd: exported " + - key.getAlgorithm() + " private key from '" + alias + "'"); - } else { - throw new Exception("Error exporting private key from keychain"); - } - } -} - diff --git a/test/jdk/sun/security/tools/keytool/ListKeyChainStore.java b/test/jdk/sun/security/tools/keytool/ListKeyChainStore.java new file mode 100644 index 00000000000..39626b8dfc5 --- /dev/null +++ b/test/jdk/sun/security/tools/keytool/ListKeyChainStore.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2012, 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 7133495 8062264 8046777 8153005 + * @summary KeyChain KeyStore implementation retrieves only one private key entry + * @requires (os.family == "mac") + * @library /test/lib + * @run main/othervm/manual ListKeyChainStore + */ + +import jdk.test.lib.SecurityTools; +import jdk.test.lib.process.ProcessTools; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.Key; +import java.security.KeyStore; +import java.security.PrivateKey; + +public class ListKeyChainStore { + private static final String PWD = "xxxxxx"; + private static final String DEFAULT_KEYTOOL = "-list -storetype KeychainStore " + + "-keystore NONE -storepass " + PWD; + private static final String USER_DIR = System.getProperty("user.dir", "."); + private static final String FS = System.getProperty("file.separator"); + private static final String PKCS12_KEYSTORE = USER_DIR + FS + "7133495.p12"; + private static final String KEYCHAIN_FILE = USER_DIR + FS + "7133495.keychain"; + private static final String TEMPORARY_FILE = USER_DIR + FS + "7133495.tmp"; + private static final String USER_KEYCHAIN_LIST = USER_DIR + FS + "user.keychain.list"; + private static final String PRIVATE_KEY_ENTRY = "PrivateKeyEntry"; + + public static void main(String[] args) throws Throwable { + LOG_MSG("WARNING: This test doesn't work on macOS virtualized environment. " + + "`security list-keychains -s` doesn't update the search order."); + + deleteTestTempFilesIfExists(); + + // Get the old security keychain list to restore later + try (PrintStream printStream = new PrintStream(USER_KEYCHAIN_LIST)) { + ProcessTools.executeCommand("sh", "-c", "security list-keychains") + .shouldHaveExitValue(0).outputTo(printStream); + } + + try { + try (PrintStream printStream = new PrintStream(TEMPORARY_FILE)) { + SecurityTools.keytool(DEFAULT_KEYTOOL).shouldHaveExitValue(0) + .outputTo(printStream); + } + int oldPrivateKeyCount = countOccurrences(TEMPORARY_FILE, PRIVATE_KEY_ENTRY); + LOG_MSG("Found " + oldPrivateKeyCount + " private key entries in the " + + "Keychain keystore"); + + // Create the PKCS12 keystore containing 3 public/private key pairs + LOG_MSG("Creating PKCS12 keystore: " + PKCS12_KEYSTORE); + for (int i = 0; i < 3; i++) { + // Use legacy encryption and MAC algorithms, refer macOS open radar FB8988319 + // macOS security framework doesn't work with the latest algorithms + SecurityTools.keytool(String.format("-J-Dkeystore.pkcs12.legacy -genkeypair" + + " -storetype PKCS12 -keystore %s -storepass %s -keyalg rsa -dname " + + "CN=CN%d,OU=OU%d,O=O%d,ST=ST%d,C=US -alias 7133495-%d", + PKCS12_KEYSTORE, PWD, i, i, i, i, i)).shouldHaveExitValue(0); + } + + // Create the keychain + LOG_MSG("Creating keychain: " + KEYCHAIN_FILE); + ProcessTools.executeCommand("sh", "-c", String.format("security create-keychain" + + " -p %s %s", PWD, KEYCHAIN_FILE)).shouldHaveExitValue(0); + + // Unlock the keychain + LOG_MSG("Unlock keychain: " + KEYCHAIN_FILE); + ProcessTools.executeCommand("sh", "-c", String.format("security unlock-keychain" + + " -p %s %s", PWD, KEYCHAIN_FILE)).shouldHaveExitValue(0); + + // Import the key pairs from the PKCS12 keystore into the keychain + // The '-A' option is used to lower the keychain's access controls + LOG_MSG("Importing the key pairs from " + PKCS12_KEYSTORE + + " to " + KEYCHAIN_FILE); + ProcessTools.executeCommand("sh", "-c", String.format("security import %s -k %s" + + " -f pkcs12 -P %s -A", PKCS12_KEYSTORE, KEYCHAIN_FILE, PWD)).shouldHaveExitValue(0); + + // Generate a 2048-bit RSA keypair and import into the keychain + // Its private key is configured with non-default key usage settings + ProcessTools.executeCommand("sh", "-c", String.format("certtool ca k=%s " + + "< " + msg); + } +} diff --git a/test/jdk/sun/security/tools/keytool/ListKeychainStore.sh b/test/jdk/sun/security/tools/keytool/ListKeychainStore.sh deleted file mode 100644 index 6ab1be90065..00000000000 --- a/test/jdk/sun/security/tools/keytool/ListKeychainStore.sh +++ /dev/null @@ -1,188 +0,0 @@ -# -# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 7133495 8041740 8062264 8046777 -# @summary [macosx] KeyChain KeyStore implementation retrieves only one private key entry - -if [ "${TESTJAVA}" = "" ] ; then - JAVAC_CMD=`which javac` - TESTJAVA=`dirname $JAVAC_CMD`/.. -fi - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi -if [ "${TESTCLASSES}" = "" ] ; then - TESTCLASSES=`pwd` -fi - -# Only run on MacOS -OS=`uname -s` -case "$OS" in - Darwin ) - ;; - * ) - echo "Will not run test on: ${OS}" - exit 0; - ;; -esac - -PWD="xxxxxx" -KEYTOOL="${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -storetype KeychainStore -keystore NONE -storepass $PWD" -TEMPORARY_P12="$TESTCLASSES/7133495.p12" -TEMPORARY_KC="$TESTCLASSES/7133495.keychain" -TEMPORARY_LIST="$TESTCLASSES/7133495.tmp" -CLEANUP_P12="rm -f $TEMPORARY_P12" -CLEANUP_KC="security delete-keychain $TEMPORARY_KC" -CLEANUP_LIST="rm -f $TEMPORARY_LIST" - -# Count the number of private key entries in the Keychain keystores - -COUNT=`$KEYTOOL -list | grep PrivateKeyEntry | wc -l` -echo "Found $COUNT private key entries in the Keychain keystores" - -# Create a temporary PKCS12 keystore containing 3 public/private keypairs - -RESULT=`$CLEANUP_P12` - -for i in X Y Z -do - ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -genkeypair \ - -storetype PKCS12 \ - -keystore $TEMPORARY_P12 \ - -storepass $PWD \ - -keyalg rsa \ - -dname "CN=$i,OU=$i,O=$i,ST=$i,C=US" \ - -alias 7133495-$i - - if [ $? -ne 0 ]; then - echo "Error: cannot create keypair $i in the temporary PKCS12 keystore" - RESULT=`$CLEANUP_P12` - exit 1 - fi -done -echo "Created a temporary PKCS12 keystore: $TEMPORARY_P12" - -# Create a temporary keychain - -security create-keychain -p $PWD $TEMPORARY_KC -if [ $? -ne 0 ]; then - echo "Error: cannot create the temporary keychain" - RESULT=`$CLEANUP_P12` - exit 2 -fi -echo "Created a temporary keychain: $TEMPORARY_KC" - -# Unlock the temporary keychain - -security unlock-keychain -p $PWD $TEMPORARY_KC -if [ $? -ne 0 ]; then - echo "Error: cannot unlock the temporary keychain" - RESULT=`$CLEANUP_P12` - RESULT=`$CLEANUP_KC` - exit 3 -fi -echo "Unlocked the temporary keychain" - -# Import the keypairs from the PKCS12 keystore into the keychain -# (The '-A' option is used to lower the temporary keychain's access controls) - -security import $TEMPORARY_P12 -k $TEMPORARY_KC -f pkcs12 -P $PWD -A -if [ $? -ne 0 ]; then - echo "Error: cannot import keypairs from PKCS12 keystore into the keychain" - RESULT=`$CLEANUP_P12` - RESULT=`$CLEANUP_KC` - exit 4 -fi -echo "Imported keypairs from PKCS12 keystore into the keychain" - -# Generate a 2048-bit RSA keypair and import into the temporary keychain -# (its private key is configured with non-default key usage settings) - -certtool c k=$TEMPORARY_KC < $TEMPORARY_LIST -security list-keychains >> $TEMPORARY_LIST -security list-keychains -s `xargs < ${TEMPORARY_LIST}` -`$CLEANUP_LIST` -echo "Temporary keychain search order:" -security list-keychains - -# Recount the number of private key entries in the Keychain keystores -# (3 private keys imported from PKCS12, 1 private key generated by 'certtool') - -RECOUNT=`$KEYTOOL -list | grep PrivateKeyEntry | wc -l` -echo "Found $RECOUNT private key entries in the Keychain keystore" -if [ $RECOUNT -lt `expr $COUNT + 4` ]; then - echo "Error: expected >$COUNT private key entries in the Keychain keystores" - RESULT=`$CLEANUP_P12` - RESULT=`$CLEANUP_KC` - exit 5 -fi - -# Export a private key from the keychain (without supplying a password) -# Access controls have already been lowered (see 'security import ... -A' above) - -${TESTJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . ${TESTSRC}/ExportPrivateKeyNoPwd.java || exit 6 -${TESTJAVA}/bin/java ${TESTVMOPTS} ExportPrivateKeyNoPwd x -if [ $? -ne 0 ]; then - echo "Error exporting private key from the temporary keychain" - RESULT=`$CLEANUP_P12` - RESULT=`$CLEANUP_KC` - exit 6 -fi -echo "Exported a private key from the temporary keychain" - -RESULT=`$CLEANUP_P12` -if [ $? -ne 0 ]; then - echo "Error: cannot remove the temporary PKCS12 keystore" - exit 7 -fi -echo "Removed the temporary PKCS12 keystore" - -RESULT=`$CLEANUP_KC` -if [ $? -ne 0 ]; then - echo "Error: cannot remove the temporary keychain" - exit 8 -fi -echo "Removed the temporary keychain" - -exit 0 diff --git a/test/lib/jdk/test/lib/process/OutputAnalyzer.java b/test/lib/jdk/test/lib/process/OutputAnalyzer.java index 34e1fafe83f..1e2cd22bcbe 100644 --- a/test/lib/jdk/test/lib/process/OutputAnalyzer.java +++ b/test/lib/jdk/test/lib/process/OutputAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -607,15 +607,15 @@ public OutputAnalyzer stdoutShouldMatchByLine(String pattern) { /** * @see #shouldMatchByLine(String, String, String) */ - public OutputAnalyzer shouldMatchByLineFrom(String from, String pattern) { - return shouldMatchByLine(from, null, pattern); + public OutputAnalyzer shouldMatchByLineFrom(String fromPattern, String pattern) { + return shouldMatchByLine(fromPattern, null, pattern); } /** * @see #shouldMatchByLine(String, String, String) */ - public OutputAnalyzer shouldMatchByLineTo(String to, String pattern) { - return shouldMatchByLine(null, to, pattern); + public OutputAnalyzer shouldMatchByLineTo(String toPattern, String pattern) { + return shouldMatchByLine(null, toPattern, pattern); } /** @@ -623,17 +623,17 @@ public OutputAnalyzer shouldMatchByLineTo(String to, String pattern) { * {@code pattern} line by line. The whole output could be matched or * just a subset of it. * - * @param from - * The line (excluded) from where output will be matched. - * Set {@code from} to null for matching from the first line. - * @param to - * The line (excluded) until where output will be matched. - * Set {@code to} to null for matching until the last line. + * @param fromPattern + * The pattern of line (excluded) from where output will be matched. + * Set {@code fromPattern} to null for matching from the first line. + * @param toPattern + * The pattern of line (excluded) until where output will be matched. + * Set {@code toPattern} to null for matching until the last line. * @param pattern * Matching pattern */ - public OutputAnalyzer shouldMatchByLine(String from, String to, String pattern) { - return shouldMatchByLine(getOutput(), from, to, pattern); + public OutputAnalyzer shouldMatchByLine(String fromPattern, String toPattern, String pattern) { + return shouldMatchByLine(getOutput(), fromPattern, toPattern, pattern); } /** @@ -641,34 +641,34 @@ public OutputAnalyzer shouldMatchByLine(String from, String to, String pattern) * {@code pattern} line by line. The whole stdout could be matched or * just a subset of it. * - * @param from - * The line (excluded) from where stdout will be matched. - * Set {@code from} to null for matching from the first line. - * @param to - * The line (excluded) until where stdout will be matched. - * Set {@code to} to null for matching until the last line. + * @param fromPattern + * The pattern of line (excluded) from where stdout will be matched. + * Set {@code fromPattern} to null for matching from the first line. + * @param toPattern + * The pattern of line (excluded) until where stdout will be matched. + * Set {@code toPattern} to null for matching until the last line. * @param pattern * Matching pattern */ - public OutputAnalyzer stdoutShouldMatchByLine(String from, String to, String pattern) { - return shouldMatchByLine(getStdout(), from, to, pattern); + public OutputAnalyzer stdoutShouldMatchByLine(String fromPattern, String toPattern, String pattern) { + return shouldMatchByLine(getStdout(), fromPattern, toPattern, pattern); } - private OutputAnalyzer shouldMatchByLine(String buffer, String from, String to, String pattern) { + private OutputAnalyzer shouldMatchByLine(String buffer, String fromPattern, String toPattern, String pattern) { List lines = asLines(buffer); int fromIndex = 0; - if (from != null) { - fromIndex = indexOf(lines, from, 0) + 1; // + 1 -> apply 'pattern' to lines after 'from' match + if (fromPattern != null) { + fromIndex = indexOf(lines, fromPattern, 0) + 1; // + 1 -> apply 'pattern' to lines after 'from' match Asserts.assertGreaterThan(fromIndex, 0, - "The line/pattern '" + from + "' from where the output should match can not be found"); + "The line matched with pattern '" + fromPattern + "' from where the output should match can not be found"); } int toIndex = lines.size(); - if (to != null) { - toIndex = indexOf(lines, to, fromIndex); + if (toPattern != null) { + toIndex = indexOf(lines, toPattern, fromIndex); Asserts.assertGreaterThan(toIndex, fromIndex, - "The line/pattern '" + to + "' until where the output should match can not be found"); + "The line matched with pattern '" + toPattern + "' until where the output should match can not be found"); } List subList = lines.subList(fromIndex, toIndex);