From d968a8cc634f7309305cfdbf58a1e6f91c4cc4a5 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Tue, 25 Jul 2023 17:10:15 +0200 Subject: [PATCH] Improve error messages in CompletionTest #906 Provide more meaningful error message in case any of the test cases in CompletionTest fails. Particularly also explicitly validate whether the proposal list widget has been disposed concurrently. Contributes to https://github.com/eclipse-platform/eclipse.platform.ui/issues/906 --- .../genericeditor/tests/CompletionTest.java | 86 ++++++++++--------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/tests/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java b/tests/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java index 1ce6cdee752a..1c2944595ce2 100644 --- a/tests/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java +++ b/tests/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java @@ -13,18 +13,24 @@ *******************************************************************************/ package org.eclipse.ui.genericeditor.tests; +import static org.hamcrest.CoreMatchers.endsWith; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Hashtable; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; import java.util.Set; +import java.util.function.BooleanSupplier; import java.util.stream.Collectors; import org.junit.After; @@ -119,14 +125,20 @@ public void testCompletionUsingViewerSelection() throws Exception { editor.selectAndReveal(0, 3); this.completionShell= openConentAssist(); final Table completionProposalList = findCompletionSelectionControl(completionShell); - assertTrue(new DisplayHelper() { + waitForProposalRelatedCondition("Proposal list did not contain expected item: ABC", completionProposalList, + () -> Arrays.stream(completionProposalList.getItems()).map(TableItem::getText).anyMatch("ABC"::equals), 5_000); + } + + private static void waitForProposalRelatedCondition(String errorMessage, Table completionProposalList, BooleanSupplier condition, int timeoutInMsec) { + assertTrue(errorMessage, new DisplayHelper() { @Override protected boolean condition() { - return Arrays.stream(completionProposalList.getItems()).map(TableItem::getText).anyMatch("ABC"::equals); + assertFalse("Completion proposal list was unexpectedly disposed", completionProposalList.isDisposed()); + return condition.getAsBoolean(); } - }.waitForCondition(completionProposalList.getDisplay(), 200)); + }.waitForCondition(completionProposalList.getDisplay(), timeoutInMsec)); } - + @Test public void testEnabledWhenCompletion() throws Exception { // Confirm that when disabled, a completion shell is present @@ -165,29 +177,27 @@ private Shell openConentAssist(boolean expectShell) { */ private void checkCompletionContent(final Table completionProposalList) { // should be instantaneous, but happens to go asynchronous on CI so let's allow a wait - assertTrue(new DisplayHelper() { - @Override - protected boolean condition() { - return completionProposalList.getItemCount() == 2; - } - }.waitForCondition(completionProposalList.getDisplay(), 200)); + waitForProposalRelatedCondition("Proposal list did not show two initial items", completionProposalList, + () -> completionProposalList.getItemCount() == 2, 200); assertTrue("Missing computing info entry", isComputingInfoEntry(completionProposalList.getItem(0))); - TableItem completionProposalItem = completionProposalList.getItem(1); - final ICompletionProposal selectedProposal = (ICompletionProposal)completionProposalItem.getData(); - assertTrue("Incorrect proposal content", BarContentAssistProcessor.PROPOSAL.endsWith(selectedProposal .getDisplayString())); - completionProposalList.setSelection(completionProposalItem); + assertTrue("Missing computing info entry in proposal list", isComputingInfoEntry(completionProposalList.getItem(0))); + final TableItem initialProposalItem = completionProposalList.getItem(1); + final String initialProposalString = ((ICompletionProposal)initialProposalItem.getData()).getDisplayString(); + assertThat("Unexpected initial proposal item", + BarContentAssistProcessor.PROPOSAL, endsWith(initialProposalString)); + completionProposalList.setSelection(initialProposalItem); // asynchronous - new DisplayHelper() { - @Override - protected boolean condition() { - return !isComputingInfoEntry(completionProposalList.getItem(0)) && completionProposalList.getItemCount() == 2; - } - }.waitForCondition(completionProposalList.getDisplay(), LongRunningBarContentAssistProcessor.DELAY + 200); - completionProposalItem = completionProposalList.getItem(0); - assertTrue("Proposal content seems incorrect", BarContentAssistProcessor.PROPOSAL.endsWith(((ICompletionProposal)completionProposalItem.getData()).getDisplayString())); - TableItem otherProposalItem = completionProposalList.getItem(1); - assertTrue("Proposal content seems incorrect", LongRunningBarContentAssistProcessor.PROPOSAL.endsWith(((ICompletionProposal)otherProposalItem.getData()).getDisplayString())); - assertEquals("Addition of completion proposal should keep selection", selectedProposal, completionProposalList.getSelection()[0].getData()); + waitForProposalRelatedCondition("Proposal list did not show two items after finishing computing", completionProposalList, + () -> !isComputingInfoEntry(completionProposalList.getItem(0)) && completionProposalList.getItemCount() == 2, + LongRunningBarContentAssistProcessor.DELAY + 200); + final TableItem firstCompletionProposalItem = completionProposalList.getItem(0); + final TableItem secondCompletionProposalItem = completionProposalList.getItem(1); + String firstCompletionProposalText = ((ICompletionProposal)firstCompletionProposalItem.getData()).getDisplayString(); + String secondCOmpletionProposalText = ((ICompletionProposal)secondCompletionProposalItem.getData()).getDisplayString(); + assertThat("Unexpected first proposal item", BarContentAssistProcessor.PROPOSAL, endsWith(firstCompletionProposalText)); + assertThat("Unexpected second proposal item", LongRunningBarContentAssistProcessor.PROPOSAL, endsWith(secondCOmpletionProposalText)); + String selectedProposalString = ((ICompletionProposal)completionProposalList.getSelection()[0].getData()).getDisplayString(); + assertEquals("Addition of completion proposal should keep selection", initialProposalString, selectedProposalString); } private static boolean isComputingInfoEntry(TableItem item) { @@ -211,13 +221,8 @@ public void testCompletionFreeze_bug521484() throws Exception { this.completionShell=openConentAssist(); final Table completionProposalList = findCompletionSelectionControl(this.completionShell); // should be instantaneous, but happens to go asynchronous on CI so let's allow a wait - new DisplayHelper() { - @Override - protected boolean condition() { - return completionProposalList.getItemCount() == 2; - } - }.waitForCondition(completionShell.getDisplay(), 200); - assertEquals(2, completionProposalList.getItemCount()); + waitForProposalRelatedCondition("Proposal list did not show two items", completionProposalList, + () -> completionProposalList.getItemCount() == 2, 200); assertTrue("Missing computing info entry", isComputingInfoEntry(completionProposalList.getItem(0))); // Some processors are long running, moving cursor can cause freeze (bug 521484) // asynchronous @@ -251,16 +256,17 @@ private void emulatePressLeftArrowKey() { } public static Table findCompletionSelectionControl(Widget control) { - if (control instanceof Table) { - return (Table)control; - } else if (control instanceof Composite) { - for (Widget child : ((Composite)control).getChildren()) { - Table res = findCompletionSelectionControl(child); - if (res != null) { - return res; - } + Queue widgetsToProcess = new LinkedList<>(); + widgetsToProcess.add(control); + while (!widgetsToProcess.isEmpty()) { + Widget child = widgetsToProcess.poll(); + if (child instanceof Table table) { + return table; + } else if (child instanceof Composite composite) { + widgetsToProcess.addAll(Arrays.asList(composite.getChildren())); } } + fail("No completion selection control found in widget: " + control); return null; }