changeset 2000:59385cdc7d0d

Add SwingVmProfileViewTest Backport of 6b9d935a750c from HEAD. PR3046 Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-June/019927.html
author Alex Macdonald <almacdon@redhat.com>
date Wed, 29 Jun 2016 15:01:48 -0400
parents 8a65bb11a6f9
children 1f5dc3abcf16
files vm-profiler/client-swing/src/main/java/com/redhat/thermostat/vm/profiler/client/swing/internal/SwingVmProfileView.java vm-profiler/client-swing/src/test/java/com/redhat/thermostat/vm/profiler/client/swing/internal/SwingVmProfileViewTest.java
diffstat 2 files changed, 437 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- 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<Void, Void>() {
             @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 "<font color='" + hexColorString + "'>"
                     + StringUtils.htmlEscape(unescapedText) + "</font>";
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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<LocaleResources> 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<VmProfileView.Profile> 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<ProfilingResult.MethodInfo>()));
+
+        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<ProfilingResult.MethodInfo> 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<String> 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<String> 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 = "<html><pre>" + highlightedReturnType + " <b>" +
+                highlightedName +"</b>(" + highlightedFirstParam + "," + highlightedSecondParam +
+                ")</pre><html>";
+
+        assertEquals(expectedResult, resultRenderer.getText());
+    }
+
+}