Changeset 18804 in josm for trunk/test/unit


Ignore:
Timestamp:
2023-08-13T00:20:18+02:00 (14 months ago)
Author:
taylor.smock
Message:

Fix #23116: Adding a member to a newly created relation will cause an NPE

This was caused by returning a null relation for a new relation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditorTest.java

    r18799 r18804  
    22package org.openstreetmap.josm.gui.dialogs.relation;
    33
     4import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    45import static org.junit.jupiter.api.Assertions.assertEquals;
     6import static org.junit.jupiter.api.Assertions.assertFalse;
     7import static org.junit.jupiter.api.Assertions.assertInstanceOf;
    58import static org.junit.jupiter.api.Assertions.assertNotNull;
    69import static org.junit.jupiter.api.Assertions.assertNull;
    710import static org.junit.jupiter.api.Assertions.assertSame;
    8 
     11import static org.openstreetmap.josm.tools.I18n.tr;
     12
     13import java.awt.Container;
     14import java.awt.event.WindowEvent;
    915import java.util.Collection;
    1016import java.util.Collections;
    11 
     17import java.util.concurrent.atomic.AtomicReference;
     18
     19import javax.swing.Action;
     20import javax.swing.JButton;
    1221import javax.swing.JOptionPane;
    1322import javax.swing.JPanel;
    1423
     24import mockit.Invocation;
    1525import mockit.Mock;
    1626import mockit.MockUp;
     27
     28import org.junit.jupiter.api.BeforeEach;
    1729import org.junit.jupiter.api.Test;
    1830import org.junit.platform.commons.support.ReflectionSupport;
     
    2234import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2335import org.openstreetmap.josm.data.osm.Relation;
     36import org.openstreetmap.josm.data.osm.RelationMember;
    2437import org.openstreetmap.josm.data.osm.Way;
     38import org.openstreetmap.josm.gui.MainApplication;
     39import org.openstreetmap.josm.gui.SideButton;
     40import org.openstreetmap.josm.gui.dialogs.RelationListDialog;
     41import org.openstreetmap.josm.gui.dialogs.relation.actions.AddSelectedAtStartAction;
    2542import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionAccess;
    2643import org.openstreetmap.josm.gui.dialogs.relation.actions.PasteMembersAction;
     
    3148import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    3249import org.openstreetmap.josm.testutils.annotations.Main;
     50import org.openstreetmap.josm.testutils.annotations.Projection;
    3351import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
    3452import org.openstreetmap.josm.testutils.mockers.WindowMocker;
     
    3957@BasicPreferences
    4058@Main
     59@Projection
    4160public class GenericRelationEditorTest {
    4261    /**
     
    8099            }
    81100        };
     101    }
     102
     103    @BeforeEach
     104    void setup() {
     105        new PasteMembersActionMock();
     106        new WindowMocker();
    82107    }
    83108
     
    137162    @Test
    138163    void testNonRegression23091() throws Exception {
    139         new MockUp<PasteMembersAction>() {
    140             @Mock
    141             protected void updateEnabledState() {
    142                 // Do nothing
    143             }
    144         };
    145         new WindowMocker();
    146 
    147164        DataSet ds = new DataSet();
    148165        Relation relation = new Relation(1);
     
    161178        assertSame(relation, selection.iterator().next(), "The selection should be the same");
    162179    }
     180
     181    /**
     182     * Ensure that users can create new relations and modify them.
     183     */
     184    @Test
     185    void testNonRegression23116() {
     186        // Setup the mocks
     187        final AtomicReference<RelationEditor> editorReference = new AtomicReference<>();
     188        new MockUp<RelationEditor>() {
     189            @Mock public RelationEditor getEditor(Invocation invocation, OsmDataLayer layer, Relation r,
     190                    Collection<RelationMember> selectedMembers) {
     191                editorReference.set(invocation.proceed(layer, r, selectedMembers));
     192                return editorReference.get();
     193            }
     194        };
     195        // We want to go through the `setVisible` code, just in case. So we have to mock the window location
     196        new MockUp<GenericRelationEditor>() {
     197            @Mock public void setVisible(boolean visible) {
     198                // Do nothing. Ideally, we would just mock the awt methods called, but that would take a lot of mocking.
     199            }
     200        };
     201        // Set up the data
     202        final DataSet dataSet = new DataSet();
     203        MainApplication.getLayerManager().addLayer(new OsmDataLayer(dataSet, "GenericRelationEditorTest.testNonRegression23116", null));
     204        dataSet.addPrimitive(TestUtils.newNode(""));
     205        dataSet.setSelected(dataSet.allPrimitives());
     206        final RelationListDialog relationListDialog = new RelationListDialog();
     207        try {
     208            final Action newAction = ((SideButton) getComponent(relationListDialog, 2, 0, 0)).getAction();
     209            assertEquals("class org.openstreetmap.josm.gui.dialogs.RelationListDialog$NewAction",
     210                    newAction.getClass().toString());
     211            // Now get the buttons we want to push
     212            newAction.actionPerformed(null);
     213            final GenericRelationEditor editor = assertInstanceOf(GenericRelationEditor.class, editorReference.get());
     214            final JButton okAction = getComponent(editor, 0, 1, 0, 2, 0);
     215            assertEquals(tr("Delete"), okAction.getText(), "OK is Delete until the relation actually has data");
     216            assertNotNull(editor);
     217            final TagEditorPanel tagEditorPanel = getComponent(editor, 0, 1, 0, 1, 0, 0, 1, 1);
     218            // We need at least one tag for the action to not be "Delete".
     219            tagEditorPanel.getModel().add("type", "someUnknownTypeHere");
     220            final Action addAtStartAction = assertInstanceOf(AddSelectedAtStartAction.class,
     221                    ((JButton) getComponent(editor, 0, 1, 0, 1, 0, 0, 2, 0, 2, 1, 2, 0, 0)).getAction());
     222            // Perform the actual test.
     223            assertDoesNotThrow(() -> addAtStartAction.actionPerformed(null));
     224            assertDoesNotThrow(() -> okAction.getAction().actionPerformed(null));
     225            assertFalse(dataSet.getRelations().isEmpty());
     226            assertSame(dataSet.getNodes().iterator().next(),
     227                    dataSet.getRelations().iterator().next().getMember(0).getNode());
     228        } finally {
     229            // This avoids an issue with the cleanup code and the mocks for this test
     230            if (editorReference.get() != null) {
     231                RelationDialogManager.getRelationDialogManager().windowClosed(new WindowEvent(editorReference.get(), 0));
     232            }
     233        }
     234    }
     235
     236    @SuppressWarnings("unchecked")
     237    private static <T extends Container> T getComponent(Container parent, int... tree) {
     238        Container current = parent;
     239        for (int i : tree) {
     240            current = (Container) current.getComponent(i);
     241        }
     242        return (T) current;
     243    }
     244
     245    private static class PasteMembersActionMock extends MockUp<PasteMembersAction> {
     246        @Mock
     247        protected void updateEnabledState() {
     248            // Do nothing
     249        }
     250    }
    163251}
Note: See TracChangeset for help on using the changeset viewer.