Skip to content

Commit 6176093

Browse files
hsenaggaryverhaegen-da
authored andcommitted
ghcide: make tests fail on unexpected diagnostic messages (#2813) (#2823)
This has the downside of relying on a timeout, experimentally tuned to be 0.5s, as we have no other way of knowing when the server has finished sending us messages.
1 parent 5da86c3 commit 6176093

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

test/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ da_haskell_library(
1212
srcs = glob(["src/**/*.hs"]),
1313
hackage_deps = [
1414
"base",
15+
"extra",
1516
"containers",
1617
"haskell-lsp-types",
1718
"lens",

test/exe/Main.hs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,15 @@ diagnosticTests = testGroup "diagnostics"
147147

148148

149149
testSession :: String -> Session () -> TestTree
150-
testSession name = testCase name . run
150+
testSession name =
151+
testCase name . run .
152+
-- Check that any diagnostics produced were already consumed by the test case.
153+
--
154+
-- If in future we add test cases where we don't care about checking the diagnostics,
155+
-- this could move elsewhere.
156+
--
157+
-- Experimentally, 0.5s seems to be long enough to wait for any final diagnostics to appear.
158+
( >> expectNoMoreDiagnostics 0.5)
151159

152160

153161
run :: Session a -> IO a

test/src/Development/IDE/Test.hs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Development.IDE.Test
66
, cursorPosition
77
, requireDiagnostic
88
, expectDiagnostics
9+
, expectNoMoreDiagnostics
910
) where
1011

1112
import Control.Applicative.Combinators
@@ -18,6 +19,7 @@ import Language.Haskell.LSP.Test hiding (message, openDoc')
1819
import qualified Language.Haskell.LSP.Test as LspTest
1920
import Language.Haskell.LSP.Types
2021
import Language.Haskell.LSP.Types.Lens as Lsp
22+
import System.Time.Extra
2123
import Test.Tasty.HUnit
2224

2325

@@ -41,6 +43,32 @@ requireDiagnostic actuals expected@(severity, cursor, expectedMsg) = do
4143
&& standardizeQuotes (T.toLower expectedMsg) `T.isInfixOf`
4244
standardizeQuotes (T.toLower $ d ^. message)
4345

46+
-- |wait for @timeout@ seconds and report an assertion failure
47+
-- if any diagnostic messages arrive in that period
48+
expectNoMoreDiagnostics :: Seconds -> Session ()
49+
expectNoMoreDiagnostics timeout = do
50+
-- Give any further diagnostic messages time to arrive.
51+
liftIO $ sleep timeout
52+
-- Send a dummy message to provoke a response from the server.
53+
-- This guarantees that we have at least one message to
54+
-- process, so message won't block or timeout.
55+
void $ sendRequest (CustomClientMethod "non-existent-method") ()
56+
handleMessages
57+
where
58+
handleMessages = handleDiagnostic <|> handleCustomMethodResponse <|> ignoreOthers
59+
handleDiagnostic = do
60+
diagsNot <- LspTest.message :: Session PublishDiagnosticsNotification
61+
let fileUri = diagsNot ^. params . uri
62+
actual = diagsNot ^. params . diagnostics
63+
liftIO $ assertFailure $
64+
"Got unexpected diagnostics for " <> show fileUri <>
65+
" got " <> show actual
66+
handleCustomMethodResponse =
67+
-- the CustomClientMethod triggers a log message about ignoring it
68+
-- handle that and then exit
69+
void (LspTest.message :: Session LogMessageNotification)
70+
ignoreOthers = void anyMessage >> handleMessages
71+
4472
expectDiagnostics :: [(FilePath, [(DiagnosticSeverity, Cursor, T.Text)])] -> Session ()
4573
expectDiagnostics expected = do
4674
expected' <- Map.fromListWith (<>) <$> traverseOf (traverse . _1) (fmap toNormalizedUri . getDocUri) expected

0 commit comments

Comments
 (0)