提交 a184020e 编写于 作者: Z zgu

8221263: [TEST_BUG] RemotePrinterStatusRefresh test is hard to use

Reviewed-by: serb, prr
上级 a56d7aa6
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
* questions. * questions.
*/ */
/** /*
* @test * @test
* @bug 8153732 8212202 8221263 8221412 * @bug 8153732 8212202 8221263 8221412
* @requires (os.family == "Windows") * @requires (os.family == "Windows")
...@@ -29,235 +29,472 @@ ...@@ -29,235 +29,472 @@
* @run main/manual RemotePrinterStatusRefresh * @run main/manual RemotePrinterStatusRefresh
*/ */
import java.awt.GridBagConstraints; import java.awt.BorderLayout;
import java.awt.GridBagLayout; import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.print.PageFormat; import java.awt.event.WindowAdapter;
import java.awt.print.Paper; import java.awt.event.WindowEvent;
import java.awt.print.PrinterException; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.swing.AbstractListModel;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.Box; import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListCellRenderer;
import javax.swing.GroupLayout;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea; import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import java.awt.print.PrinterJob; import javax.swing.Timer;
import javax.print.PrintService;
public class RemotePrinterStatusRefresh import static javax.swing.BorderFactory.createTitledBorder;
{
private static TestUI test = null; public class RemotePrinterStatusRefresh extends WindowAdapter {
public static void main(String args[]) throws Exception {
final CountDownLatch latch = new CountDownLatch(1); private static final long refreshTime = getRefreshTime();
// Test UI creation private static final long TIMEOUT = refreshTime * 4 + 60;
test = new TestUI(latch);
SwingUtilities.invokeAndWait(new Runnable() { private static final CountDownLatch latch = new CountDownLatch(1);
@Override private static volatile RemotePrinterStatusRefresh test;
public void run() {
try { private volatile boolean testResult;
test.createUI(); private volatile boolean testTimedOut;
} catch (Exception e) {
throw new RuntimeException(e); private final JFrame frame;
}
} private JButton refreshButton;
}); private JButton passButton;
private JButton failButton;
// RemotePrinterStatusRefresh creation
RemotePrinterStatusRefresh RemotePrinterStatusRefresh = new RemotePrinterStatusRefresh(); private final ServiceItemListModel beforeList;
SwingUtilities.invokeAndWait(() -> { private final ServiceItemListModel afterList;
collectPrintersList(test.resultsTextArea, true);
}); private JTextField nextRefresh;
private JTextField timeLeft;
// 8 min = 480000 msec
if(waitForFlag(480000)) { private final Timer timer;
SwingUtilities.invokeAndWait(() -> { private final long startTime;
collectPrintersList(test.resultsTextArea, false);
});
} else { private static class ServiceItem {
dispose(); private enum State {
throw new RuntimeException("No new network printer got added/removed!! Test timed out!!"); REMOVED, UNCHANGED, ADDED
} }
boolean status = latch.await(1, TimeUnit.MINUTES); final String name;
if (!status) { State state;
dispose();
throw new RuntimeException("Test timed out."); private ServiceItem(final String name) {
this.name = name;
state = State.UNCHANGED;
} }
if (test.testResult == false) { @Override
dispose(); public String toString() {
throw new RuntimeException("Test Failed."); return name;
} }
dispose(); @Override
} public boolean equals(Object obj) {
return (obj instanceof ServiceItem)
&& ((ServiceItem) obj).name.equals(name);
}
public static void dispose() throws Exception { @Override
SwingUtilities.invokeAndWait(() -> { public int hashCode() {
test.disposeUI(); return name.hashCode();
}); }
} }
public static boolean waitForFlag (long maxTimeoutInMsec) throws Exception { private static class ServiceItemListModel extends AbstractListModel<ServiceItem> {
while(!test.isAdded && maxTimeoutInMsec > 0) { private final List<ServiceItem> list;
maxTimeoutInMsec -= 100;
Thread.sleep(100); private ServiceItemListModel(List<ServiceItem> list) {
this.list = list;
}
@Override
public int getSize() {
return list.size();
}
@Override
public ServiceItem getElementAt(int index) {
return list.get(index);
}
private void refreshList(List<ServiceItem> newList) {
list.clear();
list.addAll(newList);
fireChanged();
} }
if(maxTimeoutInMsec <= 0) { private void fireChanged() {
return false; fireContentsChanged(this, 0, list.size() - 1);
} else {
return true;
} }
} }
private static void collectPrintersList(JTextArea textArea, boolean before) { private static class ServiceItemListRenderer extends DefaultListCellRenderer {
if(before) { @Override
System.out.println("List of printers(before): "); public Component getListCellRendererComponent(JList<?> list,
textArea.setText("List of printers(before): \n"); Object value,
for (PrintService printServiceBefore : PrinterJob.lookupPrintServices()) { int index,
System.out.println(printServiceBefore); boolean isSelected,
textArea.append(printServiceBefore.toString()); boolean cellHasFocus) {
textArea.append("\n"); Component component =
} super.getListCellRendererComponent(list, value, index,
} else { isSelected, cellHasFocus);
textArea.append("\n"); switch (((ServiceItem) value).state) {
System.out.println("List of printers(after): "); case REMOVED:
textArea.append("List of printers(after): \n"); component.setBackground(Color.RED);
for (PrintService printServiceAfter : PrinterJob.lookupPrintServices()) { component.setForeground(Color.WHITE);
System.out.println(printServiceAfter); break;
textArea.append(printServiceAfter.toString()); case ADDED:
textArea.append("\n"); component.setBackground(Color.GREEN);
component.setForeground(Color.BLACK);
break;
case UNCHANGED:
default:
break;
} }
return component;
} }
} }
}
class TestUI { private static final String INSTRUCTIONS_TEXT =
private static JFrame mainFrame; "Please follow the steps for this manual test:\n"
private static JPanel mainControlPanel; + "Step 0: \"Before\" list is populated with currently "
+ "configured printers.\n"
+ "Step 1: Add or Remove a network printer using "
+ "Windows Control Panel.\n"
+ "Step 2: Wait for 4 minutes after adding or removing.\n"
+ " \"Next printer refresh in\" gives you a "
+ "rough estimation on when update will happen.\n"
+ "Step 3: Click Refresh."
+ "\"After\" list is populated with updated list "
+ "of printers.\n"
+ "Step 4: Compare the list of printers in \"Before\" and "
+ "\"After\" lists.\n"
+ " Added printers are highlighted with "
+ "green color, removed ones \u2014 with "
+ "red color.\n"
+ "Step 5: Click Pass if the list of printers is correctly "
+ "updated.\n"
+ "Step 6: If the list is not updated, wait for another "
+ "4 minutes, and then click Refresh again.\n"
+ "Step 7: If the list does not update, click Fail.\n"
+ "\n"
+ "You have to click Refresh to enable Pass and Fail buttons. "
+ "If no button is pressed,\n"
+ "the test will time out. "
+ "Closing the window also fails the test.";
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(RemotePrinterStatusRefresh::createUI);
latch.await();
if (!test.testResult) {
throw new RuntimeException("Test failed"
+ (test.testTimedOut ? " because of time out" : ""));
}
}
private static long getRefreshTime() {
String refreshTime =
System.getProperty("sun.java2d.print.minRefreshTime", "240");
try {
long value = Long.parseLong(refreshTime);
return value < 240L ? 240L : value;
} catch (NumberFormatException e) {
return 240L;
}
}
private static void createUI() {
test = new RemotePrinterStatusRefresh();
}
private RemotePrinterStatusRefresh() {
frame = new JFrame("RemotePrinterStatusRefresh");
frame.addWindowListener(this);
private static JTextArea instructionTextArea; JPanel northPanel = new JPanel(new BorderLayout());
northPanel.add(createInfoPanel(), BorderLayout.NORTH);
northPanel.add(createInstructionsPanel(), BorderLayout.SOUTH);
private static JPanel resultButtonPanel;
private static JButton passButton;
private static JButton failButton;
private static JButton addedButton;
private static JPanel testPanel; beforeList = new ServiceItemListModel(
private static JButton testButton; Collections.unmodifiableList(collectPrinterList()));
private static JLabel buttonPressCountLabel; afterList = new ServiceItemListModel(new ArrayList<>());
logList("Before:", beforeList.list);
private static GridBagLayout layout; JPanel listPanel = new JPanel(new GridLayout(1, 2));
private final CountDownLatch latch; listPanel.setBorder(createTitledBorder("Print Services"));
public boolean testResult = false; listPanel.add(createListPanel(beforeList, "Before:", 'b'));
public volatile Boolean isAdded = false; listPanel.add(createListPanel(afterList, "After:", 'a'));
public static JTextArea resultsTextArea;
public TestUI(CountDownLatch latch) throws Exception {
this.latch = latch; JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(northPanel, BorderLayout.NORTH);
mainPanel.add(listPanel, BorderLayout.CENTER);
mainPanel.add(createButtonPanel(), BorderLayout.SOUTH);
frame.add(mainPanel);
frame.pack();
refreshButton.requestFocusInWindow();
frame.setVisible(true);
timer = new Timer(1000, this::updateTimeLeft);
timer.start();
startTime = System.currentTimeMillis();
updateTimeLeft(null);
} }
public final void createUI() { private JPanel createInfoPanel() {
mainFrame = new JFrame("RemotePrinterStatusRefresh"); JLabel javaLabel = new JLabel("Java version:");
layout = new GridBagLayout(); JTextField javaVersion =
mainControlPanel = new JPanel(layout); new JTextField(System.getProperty("java.runtime.version"));
resultButtonPanel = new JPanel(layout); javaVersion.setEditable(false);
testPanel = new JPanel(layout); javaLabel.setLabelFor(javaVersion);
GridBagConstraints gbc = new GridBagConstraints();
JLabel refreshTimeLabel = new JLabel("Refresh interval:");
// Create Test instructions long minutes = refreshTime / 60;
String instructions long seconds = refreshTime % 60;
= "This test displays the current list of printers(before) attached to \n" String interval = String.format("%1$d seconds%2$s",
+ "this computer in the results panel.\n\n" refreshTime,
+ "Please follow the below steps for this manual test\n" minutes > 0
+ "--------------------------------------------------------------------\n" ? String.format(" (%1$d %2$s%3$s)",
+ "Step 1: Add/Remove a new network printer and Wait for 4 minutes after adding/removing\n" minutes,
+ "Step 2: Then click on 'Printer Added/Removed' button\n" minutes > 1 ? "minutes" : "minute",
+ "Step 2: Once the new network printer is added/removed, see if it is \n" seconds > 0
+ " the same as displayed/not displayed in the results panel.\n" ? String.format(" %1$d %2$s",
+ "Step 3: If displayed/not displayed, then click 'Pass' else click on 'Fail' button"; seconds,
seconds > 1 ? "seconds" : "second")
instructionTextArea = new JTextArea(); : "")
instructionTextArea.setText(instructions); : ""
instructionTextArea.setEditable(false); );
instructionTextArea.setBorder(BorderFactory. JTextField refreshInterval = new JTextField(interval);
createTitledBorder("Test Instructions")); refreshInterval.setEditable(false);
refreshTimeLabel.setLabelFor(refreshInterval);
gbc.gridx = 0;
gbc.gridy = 0; JLabel nextRefreshLabel = new JLabel("Next printer refresh in:");
gbc.fill = GridBagConstraints.HORIZONTAL; nextRefresh = new JTextField();
mainControlPanel.add(instructionTextArea, gbc); nextRefresh.setEditable(false);
nextRefreshLabel.setLabelFor(nextRefresh);
gbc.gridx = 0;
gbc.gridy = 1; JLabel timeoutLabel = new JLabel("Time left:");
testPanel.add(Box.createVerticalStrut(50)); timeLeft = new JTextField();
mainControlPanel.add(testPanel); timeLeft.setEditable(false);
timeoutLabel.setLabelFor(timeLeft);
addedButton = new JButton("Printer Added/Removed");
addedButton.setActionCommand("Added"); JPanel infoPanel = new JPanel();
addedButton.addActionListener((ActionEvent e) -> { GroupLayout layout = new GroupLayout(infoPanel);
System.out.println("Added Button pressed!"); infoPanel.setLayout(layout);
isAdded = true; infoPanel.setBorder(BorderFactory.createTitledBorder("Info"));
}); layout.setAutoCreateGaps(true);
layout.setHorizontalGroup(
// Create resultButtonPanel with Pass, Fail buttons layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(javaLabel)
.addComponent(refreshTimeLabel)
.addComponent(nextRefreshLabel)
.addComponent(timeoutLabel)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, true)
.addComponent(javaVersion)
.addComponent(refreshInterval)
.addComponent(nextRefresh)
.addComponent(timeLeft)
)
);
layout.setVerticalGroup(
layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(javaLabel)
.addComponent(javaVersion)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(refreshTimeLabel)
.addComponent(refreshInterval))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(nextRefreshLabel)
.addComponent(nextRefresh))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(timeoutLabel)
.addComponent(timeLeft))
);
return infoPanel;
}
private JPanel createInstructionsPanel() {
JPanel instructionsPanel = new JPanel(new BorderLayout());
JTextArea instructionText = new JTextArea(INSTRUCTIONS_TEXT);
instructionText.setEditable(false);
instructionsPanel.setBorder(createTitledBorder("Test Instructions"));
instructionsPanel.add(new JScrollPane(instructionText));
return instructionsPanel;
}
private JPanel createListPanel(final ServiceItemListModel model,
final String title,
final char mnemonic) {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JList<ServiceItem> list = new JList<>(model);
list.setCellRenderer(new ServiceItemListRenderer());
JLabel label = new JLabel(title);
label.setLabelFor(list);
label.setDisplayedMnemonic(mnemonic);
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.X_AXIS));
labelPanel.add(label, BorderLayout.EAST);
labelPanel.add(Box.createHorizontalGlue());
panel.add(labelPanel);
panel.add(new JScrollPane(list));
return panel;
}
private JPanel createButtonPanel() {
refreshButton = new JButton("Refresh");
refreshButton.addActionListener(this::refresh);
passButton = new JButton("Pass"); passButton = new JButton("Pass");
passButton.setActionCommand("Pass"); passButton.addActionListener(this::pass);
passButton.addActionListener((ActionEvent e) -> { passButton.setEnabled(false);
System.out.println("Pass Button pressed!");
testResult = true;
latch.countDown();
disposeUI();
});
failButton = new JButton("Fail"); failButton = new JButton("Fail");
failButton.setActionCommand("Fail"); failButton.addActionListener(this::fail);
failButton.addActionListener((ActionEvent e) -> { failButton.setEnabled(false);
System.out.println("Fail Button pressed!");
testResult = false; JPanel buttonPanel = new JPanel();
latch.countDown(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
disposeUI(); buttonPanel.add(Box.createHorizontalGlue());
}); buttonPanel.add(refreshButton);
buttonPanel.add(passButton);
buttonPanel.add(failButton);
buttonPanel.add(Box.createHorizontalGlue());
return buttonPanel;
}
private static List<ServiceItem> collectPrinterList() {
PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
List<ServiceItem> list = new ArrayList<>(printServices.length);
for (PrintService service : printServices) {
list.add(new ServiceItem(service.getName()));
}
return list;
}
private static void logList(final String title, final List<ServiceItem> list) {
System.out.println(title);
for (ServiceItem item : list) {
System.out.println(item.name);
}
System.out.println();
}
gbc.gridx = 0; private static void compareLists(final ServiceItemListModel before, final ServiceItemListModel after) {
gbc.gridy = 0; boolean beforeUpdated = false;
resultButtonPanel.add(addedButton, gbc); boolean afterUpdated = false;
for (ServiceItem item : before.list) {
if (!after.list.contains(item)) {
item.state = ServiceItem.State.REMOVED;
beforeUpdated = true;
} else if (item.state != ServiceItem.State.UNCHANGED) {
item.state = ServiceItem.State.UNCHANGED;
beforeUpdated = true;
}
}
gbc.gridx = 1; for (ServiceItem item : after.list) {
gbc.gridy = 0; if (!before.list.contains(item)) {
resultButtonPanel.add(passButton, gbc); item.state = ServiceItem.State.ADDED;
afterUpdated = true;
} else if (item.state != ServiceItem.State.UNCHANGED) {
item.state = ServiceItem.State.UNCHANGED;
afterUpdated = true;
}
}
gbc.gridx = 2; if (beforeUpdated) {
gbc.gridy = 0; before.fireChanged();
resultButtonPanel.add(failButton, gbc); }
if (afterUpdated) {
after.fireChanged();
}
}
resultsTextArea = new JTextArea(); @Override
resultsTextArea.setEditable(false); public void windowClosing(WindowEvent e) {
resultsTextArea.setBorder(BorderFactory. System.out.println("The window closed");
createTitledBorder("Results")); disposeUI();
}
gbc.gridx = 0; private void disposeUI() {
gbc.gridy = 1; timer.stop();
gbc.fill = GridBagConstraints.HORIZONTAL; latch.countDown();
mainControlPanel.add(resultsTextArea, gbc); frame.dispose();
}
gbc.gridx = 0; @SuppressWarnings("unused")
gbc.gridy = 2; private void refresh(ActionEvent e) {
mainControlPanel.add(resultButtonPanel, gbc); System.out.println("Refresh button pressed");
afterList.refreshList(collectPrinterList());
compareLists(beforeList, afterList);
passButton.setEnabled(true);
failButton.setEnabled(true);
logList("After:", afterList.list);
}
mainFrame.add(mainControlPanel); @SuppressWarnings("unused")
mainFrame.pack(); private void pass(ActionEvent e) {
mainFrame.setVisible(true); System.out.println("Pass button pressed");
testResult = true;
disposeUI();
} }
public void disposeUI() { @SuppressWarnings("unused")
mainFrame.dispose(); private void fail(ActionEvent e) {
System.out.println("Fail button pressed");
testResult = false;
disposeUI();
} }
@SuppressWarnings("unused")
private void updateTimeLeft(ActionEvent e) {
long elapsed = (System.currentTimeMillis() - startTime) / 1000;
long left = TIMEOUT - elapsed;
if (left < 0) {
testTimedOut = true;
disposeUI();
}
timeLeft.setText(formatTime(left));
nextRefresh.setText(formatTime(refreshTime - (elapsed % refreshTime)));
}
private static String formatTime(final long seconds) {
long minutes = seconds / 60;
return String.format("%d:%02d", minutes, seconds - minutes * 60);
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册