提交 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;
import static javax.swing.BorderFactory.createTitledBorder;
public class RemotePrinterStatusRefresh extends WindowAdapter {
private static final long refreshTime = getRefreshTime();
private static final long TIMEOUT = refreshTime * 4 + 60;
private static final CountDownLatch latch = new CountDownLatch(1);
private static volatile RemotePrinterStatusRefresh test;
private volatile boolean testResult;
private volatile boolean testTimedOut;
private final JFrame frame;
private JButton refreshButton;
private JButton passButton;
private JButton failButton;
public class RemotePrinterStatusRefresh private final ServiceItemListModel beforeList;
{ private final ServiceItemListModel afterList;
private static TestUI test = null;
public static void main(String args[]) throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
// Test UI creation private JTextField nextRefresh;
test = new TestUI(latch); private JTextField timeLeft;
private final Timer timer;
private final long startTime;
private static class ServiceItem {
private enum State {
REMOVED, UNCHANGED, ADDED
}
final String name;
State state;
private ServiceItem(final String name) {
this.name = name;
state = State.UNCHANGED;
}
SwingUtilities.invokeAndWait(new Runnable() {
@Override @Override
public void run() { public String toString() {
try { return name;
test.createUI(); }
} catch (Exception e) {
throw new RuntimeException(e); @Override
public boolean equals(Object obj) {
return (obj instanceof ServiceItem)
&& ((ServiceItem) obj).name.equals(name);
}
@Override
public int hashCode() {
return name.hashCode();
} }
} }
});
// RemotePrinterStatusRefresh creation private static class ServiceItemListModel extends AbstractListModel<ServiceItem> {
RemotePrinterStatusRefresh RemotePrinterStatusRefresh = new RemotePrinterStatusRefresh(); private final List<ServiceItem> list;
SwingUtilities.invokeAndWait(() -> {
collectPrintersList(test.resultsTextArea, true);
});
// 8 min = 480000 msec private ServiceItemListModel(List<ServiceItem> list) {
if(waitForFlag(480000)) { this.list = list;
SwingUtilities.invokeAndWait(() -> {
collectPrintersList(test.resultsTextArea, false);
});
} else {
dispose();
throw new RuntimeException("No new network printer got added/removed!! Test timed out!!");
} }
boolean status = latch.await(1, TimeUnit.MINUTES); @Override
if (!status) { public int getSize() {
dispose(); return list.size();
throw new RuntimeException("Test timed out.");
} }
if (test.testResult == false) { @Override
dispose(); public ServiceItem getElementAt(int index) {
throw new RuntimeException("Test Failed."); return list.get(index);
} }
dispose(); private void refreshList(List<ServiceItem> newList) {
list.clear();
list.addAll(newList);
fireChanged();
} }
public static void dispose() throws Exception { private void fireChanged() {
SwingUtilities.invokeAndWait(() -> { fireContentsChanged(this, 0, list.size() - 1);
test.disposeUI(); }
});
} }
public static boolean waitForFlag (long maxTimeoutInMsec) throws Exception { private static class ServiceItemListRenderer extends DefaultListCellRenderer {
while(!test.isAdded && maxTimeoutInMsec > 0) { @Override
maxTimeoutInMsec -= 100; public Component getListCellRendererComponent(JList<?> list,
Thread.sleep(100); Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
Component component =
super.getListCellRendererComponent(list, value, index,
isSelected, cellHasFocus);
switch (((ServiceItem) value).state) {
case REMOVED:
component.setBackground(Color.RED);
component.setForeground(Color.WHITE);
break;
case ADDED:
component.setBackground(Color.GREEN);
component.setForeground(Color.BLACK);
break;
case UNCHANGED:
default:
break;
}
return component;
}
} }
if(maxTimeoutInMsec <= 0) { private static final String INSTRUCTIONS_TEXT =
return false; "Please follow the steps for this manual test:\n"
} else { + "Step 0: \"Before\" list is populated with currently "
return true; + "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 void collectPrintersList(JTextArea textArea, boolean before) { private static long getRefreshTime() {
if(before) { String refreshTime =
System.out.println("List of printers(before): "); System.getProperty("sun.java2d.print.minRefreshTime", "240");
textArea.setText("List of printers(before): \n"); try {
for (PrintService printServiceBefore : PrinterJob.lookupPrintServices()) { long value = Long.parseLong(refreshTime);
System.out.println(printServiceBefore); return value < 240L ? 240L : value;
textArea.append(printServiceBefore.toString()); } catch (NumberFormatException e) {
textArea.append("\n"); return 240L;
} }
} else {
textArea.append("\n");
System.out.println("List of printers(after): ");
textArea.append("List of printers(after): \n");
for (PrintService printServiceAfter : PrinterJob.lookupPrintServices()) {
System.out.println(printServiceAfter);
textArea.append(printServiceAfter.toString());
textArea.append("\n");
} }
private static void createUI() {
test = new RemotePrinterStatusRefresh();
} }
private RemotePrinterStatusRefresh() {
frame = new JFrame("RemotePrinterStatusRefresh");
frame.addWindowListener(this);
JPanel northPanel = new JPanel(new BorderLayout());
northPanel.add(createInfoPanel(), BorderLayout.NORTH);
northPanel.add(createInstructionsPanel(), BorderLayout.SOUTH);
beforeList = new ServiceItemListModel(
Collections.unmodifiableList(collectPrinterList()));
afterList = new ServiceItemListModel(new ArrayList<>());
logList("Before:", beforeList.list);
JPanel listPanel = new JPanel(new GridLayout(1, 2));
listPanel.setBorder(createTitledBorder("Print Services"));
listPanel.add(createListPanel(beforeList, "Before:", 'b'));
listPanel.add(createListPanel(afterList, "After:", 'a'));
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);
} }
}
class TestUI { private JPanel createInfoPanel() {
private static JFrame mainFrame; JLabel javaLabel = new JLabel("Java version:");
private static JPanel mainControlPanel; JTextField javaVersion =
new JTextField(System.getProperty("java.runtime.version"));
private static JTextArea instructionTextArea; javaVersion.setEditable(false);
javaLabel.setLabelFor(javaVersion);
private static JPanel resultButtonPanel;
private static JButton passButton; JLabel refreshTimeLabel = new JLabel("Refresh interval:");
private static JButton failButton; long minutes = refreshTime / 60;
private static JButton addedButton; long seconds = refreshTime % 60;
String interval = String.format("%1$d seconds%2$s",
private static JPanel testPanel; refreshTime,
private static JButton testButton; minutes > 0
private static JLabel buttonPressCountLabel; ? String.format(" (%1$d %2$s%3$s)",
minutes,
private static GridBagLayout layout; minutes > 1 ? "minutes" : "minute",
private final CountDownLatch latch; seconds > 0
public boolean testResult = false; ? String.format(" %1$d %2$s",
public volatile Boolean isAdded = false; seconds,
public static JTextArea resultsTextArea; seconds > 1 ? "seconds" : "second")
: "")
public TestUI(CountDownLatch latch) throws Exception { : ""
this.latch = latch; );
} JTextField refreshInterval = new JTextField(interval);
refreshInterval.setEditable(false);
public final void createUI() { refreshTimeLabel.setLabelFor(refreshInterval);
mainFrame = new JFrame("RemotePrinterStatusRefresh");
layout = new GridBagLayout(); JLabel nextRefreshLabel = new JLabel("Next printer refresh in:");
mainControlPanel = new JPanel(layout); nextRefresh = new JTextField();
resultButtonPanel = new JPanel(layout); nextRefresh.setEditable(false);
testPanel = new JPanel(layout); nextRefreshLabel.setLabelFor(nextRefresh);
GridBagConstraints gbc = new GridBagConstraints();
JLabel timeoutLabel = new JLabel("Time left:");
// Create Test instructions timeLeft = new JTextField();
String instructions timeLeft.setEditable(false);
= "This test displays the current list of printers(before) attached to \n" timeoutLabel.setLabelFor(timeLeft);
+ "this computer in the results panel.\n\n"
+ "Please follow the below steps for this manual test\n" JPanel infoPanel = new JPanel();
+ "--------------------------------------------------------------------\n" GroupLayout layout = new GroupLayout(infoPanel);
+ "Step 1: Add/Remove a new network printer and Wait for 4 minutes after adding/removing\n" infoPanel.setLayout(layout);
+ "Step 2: Then click on 'Printer Added/Removed' button\n" infoPanel.setBorder(BorderFactory.createTitledBorder("Info"));
+ "Step 2: Once the new network printer is added/removed, see if it is \n" layout.setAutoCreateGaps(true);
+ " the same as displayed/not displayed in the results panel.\n" layout.setHorizontalGroup(
+ "Step 3: If displayed/not displayed, then click 'Pass' else click on 'Fail' button"; layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
instructionTextArea = new JTextArea(); .addComponent(javaLabel)
instructionTextArea.setText(instructions); .addComponent(refreshTimeLabel)
instructionTextArea.setEditable(false); .addComponent(nextRefreshLabel)
instructionTextArea.setBorder(BorderFactory. .addComponent(timeoutLabel)
createTitledBorder("Test Instructions")); )
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, true)
gbc.gridx = 0; .addComponent(javaVersion)
gbc.gridy = 0; .addComponent(refreshInterval)
gbc.fill = GridBagConstraints.HORIZONTAL; .addComponent(nextRefresh)
mainControlPanel.add(instructionTextArea, gbc); .addComponent(timeLeft)
)
gbc.gridx = 0; );
gbc.gridy = 1; layout.setVerticalGroup(
testPanel.add(Box.createVerticalStrut(50)); layout.createSequentialGroup()
mainControlPanel.add(testPanel); .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(javaLabel)
addedButton = new JButton("Printer Added/Removed"); .addComponent(javaVersion)
addedButton.setActionCommand("Added"); )
addedButton.addActionListener((ActionEvent e) -> { .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
System.out.println("Added Button pressed!"); .addComponent(refreshTimeLabel)
isAdded = true; .addComponent(refreshInterval))
}); .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(nextRefreshLabel)
// Create resultButtonPanel with Pass, Fail buttons .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;
}
gbc.gridx = 0; private static List<ServiceItem> collectPrinterList() {
gbc.gridy = 0; PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
resultButtonPanel.add(addedButton, gbc); List<ServiceItem> list = new ArrayList<>(printServices.length);
for (PrintService service : printServices) {
list.add(new ServiceItem(service.getName()));
}
return list;
}
gbc.gridx = 1; private static void logList(final String title, final List<ServiceItem> list) {
gbc.gridy = 0; System.out.println(title);
resultButtonPanel.add(passButton, gbc); for (ServiceItem item : list) {
System.out.println(item.name);
}
System.out.println();
}
gbc.gridx = 2; private static void compareLists(final ServiceItemListModel before, final ServiceItemListModel after) {
gbc.gridy = 0; boolean beforeUpdated = false;
resultButtonPanel.add(failButton, 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;
}
}
resultsTextArea = new JTextArea(); for (ServiceItem item : after.list) {
resultsTextArea.setEditable(false); if (!before.list.contains(item)) {
resultsTextArea.setBorder(BorderFactory. item.state = ServiceItem.State.ADDED;
createTitledBorder("Results")); afterUpdated = true;
} else if (item.state != ServiceItem.State.UNCHANGED) {
item.state = ServiceItem.State.UNCHANGED;
afterUpdated = true;
}
}
gbc.gridx = 0; if (beforeUpdated) {
gbc.gridy = 1; before.fireChanged();
gbc.fill = GridBagConstraints.HORIZONTAL; }
mainControlPanel.add(resultsTextArea, gbc); if (afterUpdated) {
after.fireChanged();
}
}
@Override
public void windowClosing(WindowEvent e) {
System.out.println("The window closed");
disposeUI();
}
private void disposeUI() {
timer.stop();
latch.countDown();
frame.dispose();
}
@SuppressWarnings("unused")
private void refresh(ActionEvent e) {
System.out.println("Refresh button pressed");
afterList.refreshList(collectPrinterList());
compareLists(beforeList, afterList);
passButton.setEnabled(true);
failButton.setEnabled(true);
logList("After:", afterList.list);
}
gbc.gridx = 0; @SuppressWarnings("unused")
gbc.gridy = 2; private void pass(ActionEvent e) {
mainControlPanel.add(resultButtonPanel, gbc); System.out.println("Pass button pressed");
testResult = true;
disposeUI();
}
mainFrame.add(mainControlPanel); @SuppressWarnings("unused")
mainFrame.pack(); private void fail(ActionEvent e) {
mainFrame.setVisible(true); System.out.println("Fail button pressed");
testResult = false;
disposeUI();
} }
public void disposeUI() { @SuppressWarnings("unused")
mainFrame.dispose(); 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.
先完成此消息的编辑!
想要评论请 注册