Skip to content

8341984: Use PassFailJFrame for TimeChangeButtonClickTest.java #21476

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 72 additions & 164 deletions test/jdk/javax/swing/JButton/TimeChangeButtonClickTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
Expand All @@ -26,195 +26,103 @@
* @bug 7096375
* @summary Test that Swing does not ignore first click on a JButton after
* decreasing system's time
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual TimeChangeButtonClickTest
*/

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.concurrent.CountDownLatch;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.TimeUnit;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class TimeChangeButtonClickTest {

public static void main(String args[]) throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
TestUI test = new TestUI(latch);

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
test.createUI();
} catch (Exception ex) {
throw new RuntimeException("Exception while creating test UI");
}
}
});

boolean status = latch.await(5, TimeUnit.MINUTES);

if (!status) {
System.out.println("Test timed out.");
}

SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
try {
test.disposeUI();
} catch (Exception ex) {
throw new RuntimeException("Exception while disposing test UI");
}
}
});

if (test.testResult == false) {
throw new RuntimeException("Test Failed.");
}
}
}

class TestUI {

private static JFrame mainFrame;
private static JPanel mainControlPanel;

private static JTextArea instructionTextArea;

private static JPanel resultButtonPanel;
private static JButton passButton;
private static JButton failButton;

private static JPanel testPanel;
private static JButton testButton;
private static JLabel buttonPressCountLabel;

private static GridBagLayout layout;
private final CountDownLatch latch;
public boolean testResult = false;
private int buttonPressCount = 0;

public TestUI(CountDownLatch latch) throws Exception {
this.latch = latch;
private static final String INSTRUCTIONS = """
<html><body>
<ol>
<li>
<strong>Test 1:</strong>
<ol style="margin-top: 0px">
<li>Click <b>Test Button</b> with left mouse button</li>
<li>Observe: Button Press count change to 1</li>
</ol>
</li>
<li>
<strong>Test 2:</strong>
<ol style="margin-top: 0px">
<li>Change the system time to one hour less than current time</li>
<li>Click <b>Test Button</b> with left mouse button</li>
<li>Observe: Button Press count change to 2</li>
</ol>
</li>
<li>
<strong>Test 3:</strong>
<ol style="margin-top: 0px">
<li>Change the system time by adding two hours</li>
<li>Click <b>Test Button</b> with left mouse button</li>
<li>Observe: Button Press count changes to 3</li>
</ol>
</li>

<li style="margin-top: 8px; padding-top: 8px; border-top: 1px solid">
Restore the system time.</li>
<li style="margin-top: 8px; padding-top: 8px; border-top: 1px solid">
Press <b>Pass</b> if Button Press count is 3,
and <b>Fail</b> otherwise.</li>
</ol>
</body></html>
""";

public static void main(String[] args) throws Exception {
PassFailJFrame.builder()
.instructions(INSTRUCTIONS)
.rows(20)
.columns(40)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.columns(40)
.columns(40)
.testTimeOut(10)

We do have a pause timer option but I think a timeout of 8-10 mins is better than the default of 5 mins since it allows more time for the user to change the time settings.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think what is happening is that when the time is set forward an hour (+2 hours forward from 1 hour behind as in instructions) the test will automatically time out because it thinks an hour has passed. I thought initially it was me being slow on changing the time settings but even if you do everything quickly the test always fails exactly when you set the time forward.

So I think with the way the timeout is implemented the test is broken with PassFailJFrame.

Copy link
Contributor

@prrace prrace Oct 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What an .. interesting .. test. No idea what this does to the jtreg test harness too.
FWIW I think this test should be deleted rather than trying to make it nicer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think what is happening is that when the time is set forward an hour (+2 hours forward from 1 hour behind as in instructions) the test will automatically time out because it thinks an hour has passed. I thought initially it was me being slow on changing the time settings but even if you do everything quickly the test always fails exactly when you set the time forward.

Good catch. I hadn't noticed PFJ timeout.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, the test does not play nicely with timeout in PassFailJFrame.

The workaround could be to pause the timeout. In addition to that, we could set the timeout to 15 minutes. If the user changes time not -1 / +2 hours but rather -5 / +10 minutes, it should be enough.

What an .. interesting .. test. No idea what this does to the jtreg test harness too.

The jtreg test harness turns off its timeout for manual tests, as far as I understand. By the time, the test finishes, the time on the system should be correct again.

FWIW I think this test should be deleted rather than trying to make it nicer.

Another option could be to mark the test with @ignore so that it's not run regularly. The test could still be useful; even though changing time isn't common…

I wonder if going to/from DST reproduces the problem in JDK-7096375 for which the test was written.

Copy link
Contributor

@honkar-jdk honkar-jdk Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workaround could be to pause the timeout. In addition to that, we could set the timeout to 15 minutes. If the user changes time not -1 / +2 hours but rather -5 / +10 minutes, it should be enough.

The workaround sounds good and may be also include pause timer in the test instructions as below.

Pause the timer and reduce the system time to 10 mins less than current time.
......
.....
Pause the timer and increase the system time by adding 10 mins to the current time.

Yes I agree, retaining the test might be a good idea since it was created for -
JDK-7096375.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good for a workaround.

.splitUI(TimeChangeButtonClickTest::createTestPanel)
.build()
.awaitAndCheck();
}

public final void createUI() throws Exception {

mainFrame = new JFrame("TimeChangeButtonClickTest");

layout = new GridBagLayout();
mainControlPanel = new JPanel(layout);
resultButtonPanel = new JPanel(layout);
testPanel = new JPanel(layout);

GridBagConstraints gbc = new GridBagConstraints();

// Create Test instructions
String instructions
= "Test 1 : --------------------\n"
+ "1. Click 'Test Button' with left mouse button\n"
+ "Observe : Button Press count change to 1\n"
+ "Test 2 : --------------------\n"
+ "1. Change the system time to one hour less than current time\n"
+ "2. Click 'Test Button' with left mouse button\n"
+ "Observe : Button Press count change to 2\n"
+ "Test 3 : --------------------\n"
+ "1. Change the system time by adding two hours\n"
+ "2. Click 'Test Button' with left mouse button\n"
+ "Observe : Button Press count change to 3\n"
+ "--------------------\n"
+ "Restore the system time.\n"
+ "--------------------\n"
+ "Press 'Pass' if Button Press count is 3, 'Fail' otherwise";

instructionTextArea = new JTextArea();
instructionTextArea.setText(instructions);
instructionTextArea.setEditable(false);
instructionTextArea.setBorder(BorderFactory.
createTitledBorder("Test Instructions"));

gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainControlPanel.add(instructionTextArea, gbc);
private static JComponent createTestPanel() {
final JLabel buttonPressCountLabel = new JLabel(
"Button Press Count: 0");

// Create Test Button and label
testButton = new JButton("Test Button");
JButton testButton = new JButton("Test Button");
testButton.addActionListener(new ActionListener() {
private int buttonPressCount;

@Override
public void actionPerformed(ActionEvent e) {
buttonPressCount++;
buttonPressCountLabel.setText(
"Button Press Count : " + buttonPressCount);
}
});

gbc.gridx = 0;
gbc.gridy = 0;
testPanel.add(testButton, gbc);

gbc.gridx = 0;
gbc.gridy = 1;
testPanel.add(Box.createVerticalStrut(50));

gbc.gridx = 0;
gbc.gridy = 2;
buttonPressCountLabel = new JLabel(
"Button Press Count : " + buttonPressCount);
testPanel.add(buttonPressCountLabel, gbc);

mainControlPanel.add(testPanel);

// Create resultButtonPanel with Pass, Fail buttons
passButton = new JButton("Pass");
passButton.setActionCommand("Pass");
passButton.addActionListener((ActionEvent e) -> {
System.out.println("Pass Button pressed!");
testResult = true;
latch.countDown();

});

failButton = new JButton("Fail");
failButton.setActionCommand("Fail");
failButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Fail Button pressed!");
testResult = false;
latch.countDown();
"Button Press Count: " + buttonPressCount);
}
});

JPanel buttonPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
resultButtonPanel.add(passButton, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
resultButtonPanel.add(failButton, gbc);

gbc.gridx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
buttonPanel.add(testButton, gbc);
gbc.gridy = 1;
mainControlPanel.add(resultButtonPanel, gbc);
gbc.ipady = 16;
buttonPanel.add(buttonPressCountLabel, gbc);

mainFrame.add(mainControlPanel);
Box testPanel = Box.createVerticalBox();
testPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));

mainFrame.pack();
mainFrame.setVisible(true);
}
testPanel.add(Box.createVerticalGlue());
testPanel.add(buttonPanel);
testPanel.add(Box.createVerticalGlue());

public void disposeUI() {
mainFrame.setVisible(false);
mainFrame.dispose();
return testPanel;
}
}