# HG changeset patch # User Alex Macdonald # Date 1467226908 14400 # Node ID 59385cdc7d0dc35269bf0a7689be82a77af11737 # Parent 8a65bb11a6f975cf347c31b84246286d5dc32285 Add SwingVmProfileViewTest Backport of 6b9d935a750c from HEAD. PR3046 Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-June/019927.html diff -r 8a65bb11a6f9 -r 59385cdc7d0d vm-profiler/client-swing/src/main/java/com/redhat/thermostat/vm/profiler/client/swing/internal/SwingVmProfileView.java --- a/vm-profiler/client-swing/src/main/java/com/redhat/thermostat/vm/profiler/client/swing/internal/SwingVmProfileView.java Thu Jun 30 11:36:54 2016 -0400 +++ b/vm-profiler/client-swing/src/main/java/com/redhat/thermostat/vm/profiler/client/swing/internal/SwingVmProfileView.java Wed Jun 29 15:01:48 2016 -0400 @@ -128,10 +128,8 @@ boolean cellHasFocus) { if (value instanceof Profile) { Profile profile = (Profile) value; - value = translator - .localize(LocaleResources.PROFILER_LIST_ITEM, - profile.name, new Date(profile.timeStamp).toString()) - .getContents(); + value = translator.localize(LocaleResources.PROFILER_LIST_ITEM, + profile.name, new Date(profile.timeStamp).toString()).getContents(); } return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } @@ -141,7 +139,9 @@ listModel = new DefaultListModel<>(); tabPane = new JTabbedPane(); - toggleButton = new ActionToggleButton(START_ICON, STOP_ICON, translator.localize(LocaleResources.START_PROFILING)); + toggleButton = new ActionToggleButton(START_ICON, STOP_ICON, translator.localize( + LocaleResources.START_PROFILING)); + toggleButton.setName("TOGGLE_PROFILING_BUTTON"); toggleButton.toggleText(false); toggleButton.addActionListener(new java.awt.event.ActionListener() { @Override @@ -190,16 +190,14 @@ constraints.gridx = 0; constraints.gridwidth = 1; currentStatusLabel = new JLabel("Current Status: {0}"); + currentStatusLabel.setName("CURRENT_STATUS_LABEL"); statusPanel.add(currentStatusLabel, constraints); return statusPanel; } private JComponent createInformationPanel() { - if (!SwingUtilities.isEventDispatchThread()) { - throw new AssertionError("Not in the EDT!"); - } - profileList = new JList<>(listModel); + profileList.setName("PROFILE_LIST"); profileList.setCellRenderer(new ProfileItemRenderer()); profileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); profileList.addListSelectionListener(new ListSelectionListener() { @@ -262,6 +260,7 @@ return super.getCellRenderer(row, column); } }; + profileTable.setName("METHOD_TABLE"); tabPane.addTab(translator.localize(LocaleResources.PROFILER_RESULTS_TABLE).getContents(), profileTable.wrap()); @@ -284,10 +283,6 @@ } private void fireProfileAction(final ProfileAction action) { - if (!SwingUtilities.isEventDispatchThread()) { - throw new AssertionError("Not in the EDT!"); - } - new SwingWorker() { @Override protected Void doInBackground() throws Exception { @@ -402,9 +397,8 @@ tableModel.setRowCount(0); if (results.getMethodInfo().size() == 0) { - String noResultsMessage = translator - .localize(LocaleResources.PROFILER_NO_RESULTS) - .getContents(); + String noResultsMessage = translator.localize( + LocaleResources.PROFILER_NO_RESULTS).getContents(); tableModel.addRow(new Object[] { noResultsMessage, null, null }); return; } @@ -468,6 +462,10 @@ static class SyntaxHighlightedMethodDeclarationRenderer extends ThermostatTableRenderer { + static final Color METHOD_COLOR = Palette.PALE_RED.getColor(); + static final Color PARAMETER_COLOR = Palette.VIOLET.getColor(); + static final Color RETURN_TYPE_COLOR = Palette.GRANITA_ORANGE.getColor(); + @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { @@ -481,10 +479,6 @@ } private String syntaxHighlightMethod(MethodDeclaration decl) { - final Color METHOD_COLOR = Palette.PALE_RED.getColor(); - final Color PARAMETER_COLOR = Palette.VIOLET.getColor(); - final Color RETURN_TYPE_COLOR = Palette.GRANITA_ORANGE.getColor(); - String highlightedName = htmlColorText(decl.getName(), METHOD_COLOR); String highlightedReturnType = htmlColorText(decl.getReturnType(), RETURN_TYPE_COLOR); @@ -513,7 +507,10 @@ } - private String htmlColorText(String unescapedText, Color color) { + /** + * Package-private for testing purposes. + */ + static String htmlColorText(String unescapedText, Color color) { String hexColorString = "#" + Integer.toHexString(color.getRGB() & 0x00ffffff); return "" + StringUtils.htmlEscape(unescapedText) + ""; diff -r 8a65bb11a6f9 -r 59385cdc7d0d vm-profiler/client-swing/src/test/java/com/redhat/thermostat/vm/profiler/client/swing/internal/SwingVmProfileViewTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-profiler/client-swing/src/test/java/com/redhat/thermostat/vm/profiler/client/swing/internal/SwingVmProfileViewTest.java Wed Jun 29 15:01:48 2016 -0400 @@ -0,0 +1,419 @@ +/* + * Copyright 2012-2016 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.profiler.client.swing.internal; + +import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import javax.swing.JList; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.TableModel; + +import org.fest.swing.annotation.GUITest; +import org.fest.swing.edt.FailOnThreadViolationRepaintManager; +import org.fest.swing.edt.GuiActionRunner; +import org.fest.swing.edt.GuiTask; +import org.fest.swing.fixture.Containers; +import org.fest.swing.fixture.FrameFixture; +import org.fest.swing.fixture.JLabelFixture; +import org.fest.swing.fixture.JListFixture; +import org.fest.swing.fixture.JTableFixture; +import org.fest.swing.fixture.JToggleButtonFixture; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +import com.redhat.thermostat.annotations.internal.CacioTest; +import com.redhat.thermostat.client.swing.components.ActionToggleButton; +import com.redhat.thermostat.client.swing.components.Icon; +import com.redhat.thermostat.client.swing.components.ThermostatTableRenderer; +import com.redhat.thermostat.common.utils.MethodDescriptorConverter; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.vm.profiler.client.core.ProfilingResult; + +@Category(CacioTest.class) +@RunWith(CacioFESTRunner.class) +public class SwingVmProfileViewTest { + + private static final Translate translator = LocaleResources.createLocalizer(); + + private PrintStream stderr; + + private SwingVmProfileView view; + private FrameFixture frame; + + @BeforeClass + public static void setUpOnce() { + FailOnThreadViolationRepaintManager.install(); + } + + @Before + public void setUp() { + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + view = new SwingVmProfileView(); + } + }); + + frame = Containers.frameFixtureFor((Container) view.getUiComponent()); + stderr = System.err; + } + + @After + public void tearDown() { + System.setErr(stderr); + frame.cleanUp(); + frame = null; + view = null; + } + + @GUITest + @Test + public void testSetProfilingState() throws InvocationTargetException, InterruptedException { + frame.show(); + + JLabelFixture currentStatusLabelFixture = frame.label("CURRENT_STATUS_LABEL"); + JToggleButtonFixture toggleButtonFixture = frame.toggleButton("TOGGLE_PROFILING_BUTTON"); + final ActionToggleButton toggleButton = (ActionToggleButton) toggleButtonFixture.component(); + + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + toggleButton.toggleText(true); + view.setViewControlsEnabled(false); + view.setProfilingState(VmProfileView.ProfilingState.STARTED); + } + }); + + checkButtonState(VmProfileView.ProfilingState.DISABLED, toggleButton); + assertEquals(translator.localize(LocaleResources.PROFILER_CURRENT_STATUS_DEAD).getContents(), + currentStatusLabelFixture.text()); + assertEquals(translator.localize(LocaleResources.START_PROFILING).getContents(), + toggleButtonFixture.text()); + + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + view.setViewControlsEnabled(true); + view.setProfilingState(VmProfileView.ProfilingState.STOPPING); + } + }); + checkButtonState(VmProfileView.ProfilingState.STOPPING, toggleButton); + verifyActive(currentStatusLabelFixture, toggleButtonFixture); + + setProfilingStateInEDT(VmProfileView.ProfilingState.STARTED); + checkButtonState(VmProfileView.ProfilingState.STARTED, toggleButton); + verifyActive(currentStatusLabelFixture, toggleButtonFixture); + + setProfilingStateInEDT(VmProfileView.ProfilingState.STOPPED); + checkButtonState(VmProfileView.ProfilingState.STOPPED, toggleButton); + verifyInactive(currentStatusLabelFixture, toggleButtonFixture); + + setProfilingStateInEDT(VmProfileView.ProfilingState.DISABLED); + checkButtonState(VmProfileView.ProfilingState.DISABLED, toggleButton); + verifyInactive(currentStatusLabelFixture, toggleButtonFixture); + + setProfilingStateInEDT(VmProfileView.ProfilingState.STARTING); + checkButtonState(VmProfileView.ProfilingState.STARTING, toggleButton); + verifyInactive(currentStatusLabelFixture, toggleButtonFixture); + } + + private void setProfilingStateInEDT(final VmProfileView.ProfilingState state) { + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + view.setProfilingState(state); + } + }); + } + + private void checkButtonState(final VmProfileView.ProfilingState profilingState, + final ActionToggleButton toggleButton) + throws InterruptedException, InvocationTargetException { + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + ActionToggleButton reference = new ActionToggleButton(new Icon()); + reference.setToggleActionState(profilingState); + assertEquals(reference.isEnabled(), toggleButton.isEnabled()); + assertEquals(reference.isSelected(), toggleButton.isSelected()); + } + }); + } + + private void verifyActive(JLabelFixture currentStatusLabelFixture, + JToggleButtonFixture toggleButtonFixture) { + assertEquals(translator.localize(LocaleResources.PROFILER_CURRENT_STATUS_ACTIVE).getContents(), + currentStatusLabelFixture.text()); + assertEquals(translator.localize(LocaleResources.STOP_PROFILING).getContents(), + toggleButtonFixture.text()); + } + + private void verifyInactive(JLabelFixture currentStatusLabelFixture, + JToggleButtonFixture toggleButtonFixture) { + assertEquals(translator.localize(LocaleResources.PROFILER_CURRENT_STATUS_INACTIVE).getContents(), + currentStatusLabelFixture.text()); + assertEquals(translator.localize(LocaleResources.START_PROFILING).getContents(), + toggleButtonFixture.text()); + } + + @GUITest + @Test + public void testGetSelectedProfileWithoutSelection() throws InvocationTargetException, + InterruptedException { + + frame.show(); + + JListFixture profileJList = frame.list("PROFILE_LIST"); + profileJList.clearSelection(); + + ByteArrayOutputStream divertedErr = new ByteArrayOutputStream(); + System.setErr(new PrintStream(divertedErr)); + + view.getSelectedProfile(); + + assertTrue(divertedErr.toString().contains(InvocationTargetException.class.getSimpleName())); + } + + @GUITest + @Test + public void testGetSelectedProfileWithSelection() throws InvocationTargetException, + InterruptedException { + + frame.show(); + + final JListFixture profileJList = frame.list("PROFILE_LIST"); + final List availableRuns = new ArrayList<>(); + availableRuns.add(new VmProfileView.Profile("profile1", 1000)); + view.setAvailableProfilingRuns(availableRuns); + + profileJList.clickItem(0); + assertEquals(availableRuns.get(0), view.getSelectedProfile()); + } + + @GUITest + @Test + public void testSetProfilingDetailDataWithNoResults() throws InvocationTargetException, + InterruptedException { + + frame.show(); + + final JTableFixture profileTable = frame.table("METHOD_TABLE"); + + view.setProfilingDetailData(new ProfilingResult(new ArrayList())); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + TableModel model = profileTable.component().getModel(); + assertEquals(1, model.getRowCount()); + assertEquals(translator.localize(LocaleResources.PROFILER_NO_RESULTS).getContents(), + model.getValueAt(0, 0)); + } + }); + } + + @GUITest + @Test + public void testSetProfilingDetailDataWithResults() throws InvocationTargetException, + InterruptedException { + + frame.show(); + + final JTableFixture profileTable = frame.table("METHOD_TABLE"); + + List data = new ArrayList<>(); + data.add(new ProfilingResult.MethodInfo(new MethodDescriptorConverter.MethodDeclaration( + "foo", Arrays.asList("int"), "int"), 700, 70)); + data.add(new ProfilingResult.MethodInfo(new MethodDescriptorConverter.MethodDeclaration( + "bar", Arrays.asList("double"), "double"), 300, 30)); + final ProfilingResult result = new ProfilingResult(data); + + view.setProfilingDetailData(result); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + TableModel model = profileTable.component().getModel(); + assertEquals(2, model.getRowCount()); + + ArrayList methodNames = new ArrayList<>(); + methodNames.add(model.getValueAt(0, 0).toString()); + methodNames.add(model.getValueAt(1, 0).toString()); + assertTrue(methodNames.contains("int foo(int)")); + assertTrue(methodNames.contains("double bar(double)")); + } + }); + } + + @Test + public void testProfileItemRendererFailsWithNonProfileValue() { + SwingVmProfileView.ProfileItemRenderer renderer = new SwingVmProfileView.ProfileItemRenderer(); + + String value = "value"; + Component result = renderer.getListCellRendererComponent( + mock(JList.class), value, 0, true, true); + + SwingVmProfileView.ProfileItemRenderer resultRenderer = + (SwingVmProfileView.ProfileItemRenderer) result; + + assertEquals(value, resultRenderer.getText()); + } + + @Test + public void testProfileItemRendererWithProfileValue() { + SwingVmProfileView.ProfileItemRenderer renderer = new SwingVmProfileView.ProfileItemRenderer(); + + VmProfileView.Profile value = new VmProfileView.Profile("profile", 1000); + Component result = renderer.getListCellRendererComponent( + mock(JList.class), value, 0, true, true); + + SwingVmProfileView.ProfileItemRenderer resultRenderer = + (SwingVmProfileView.ProfileItemRenderer) result; + + String expectedValue = translator.localize(LocaleResources.PROFILER_LIST_ITEM, + value.name, new Date(value.timeStamp).toString()).getContents(); + assertEquals(expectedValue, resultRenderer.getText()); + } + + @Test + public void testSimpleTextRendererFailsWithInvalidValue() { + SwingVmProfileView.SimpleTextRenderer renderer = new SwingVmProfileView.SimpleTextRenderer(); + + testRendererWithNullValue(renderer); + testRendererWithPlainObjectAsValue(renderer); + } + + @Test + public void testPlainTextMethodDeclarationRendererFailsWithInvalidValue() { + SwingVmProfileView.PlainTextMethodDeclarationRenderer renderer = + new SwingVmProfileView.PlainTextMethodDeclarationRenderer(); + + testRendererWithNullValue(renderer); + testRendererWithPlainObjectAsValue(renderer); + } + + @Test + public void testSyntaxHighlightedMethodDeclarationRendererFailsWithInvalidValue() { + SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer renderer = + new SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer(); + + testRendererWithNullValue(renderer); + testRendererWithPlainObjectAsValue(renderer); + } + + private void testRendererWithNullValue(ThermostatTableRenderer renderer) { + try { + renderer.getTableCellRendererComponent(mock(JTable.class), null, true, true, 0, 0); + fail("Error expected"); + } catch (AssertionError e) { + assertEquals("Unexpected value", e.getMessage()); + } + } + + private void testRendererWithPlainObjectAsValue(ThermostatTableRenderer renderer) { + try { + renderer.getTableCellRendererComponent(mock(JTable.class), new Object(), true, true, 0, 0); + fail("Error expected"); + } catch (AssertionError e) { + assertEquals("Unexpected value", e.getMessage()); + } + } + + @Test + public void testSyntaxHighlightedMethodDeclarationRendererWithValidValue() { + final Color METHOD_COLOR = + SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer.METHOD_COLOR; + final Color PARAMETER_COLOR = + SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer.PARAMETER_COLOR; + final Color RETURN_TYPE_COLOR = + SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer.RETURN_TYPE_COLOR; + + SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer renderer = + new SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer(); + + String methodName = "foo"; + List parameters = Arrays.asList("double", "String"); + String returnType = "int"; + MethodDescriptorConverter.MethodDeclaration decl = + new MethodDescriptorConverter.MethodDeclaration( + methodName, parameters, returnType); + + Component result = renderer.getTableCellRendererComponent(mock(JTable.class), decl, + true, true, 0, 0); + + SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer resultRenderer = + (SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer) result; + + String highlightedReturnType = SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer + .htmlColorText(returnType, RETURN_TYPE_COLOR); + String highlightedName = SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer + .htmlColorText(methodName, METHOD_COLOR); + String highlightedFirstParam = SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer + .htmlColorText(parameters.get(0), PARAMETER_COLOR); + String highlightedSecondParam = SwingVmProfileView.SyntaxHighlightedMethodDeclarationRenderer + .htmlColorText(parameters.get(1), PARAMETER_COLOR); + + String expectedResult = "
" + highlightedReturnType + " " +
+                highlightedName +"(" + highlightedFirstParam + "," + highlightedSecondParam +
+                ")
"; + + assertEquals(expectedResult, resultRenderer.getText()); + } + +}