11
22module ExceptionTests (tests ) where
33
4- import Control.Concurrent.Async
54import Control.Exception (ArithException (DivideByZero ),
6- finally , throwIO )
5+ throwIO )
76import Control.Lens
87import Control.Monad.Error.Class (MonadError (throwError ))
98import Control.Monad.IO.Class (liftIO )
@@ -12,6 +11,7 @@ import Data.Text as T
1211import Development.IDE.Core.Shake (IdeState (.. ))
1312import qualified Development.IDE.LSP.Notifications as Notifications
1413import qualified Development.IDE.Main as IDE
14+ import Development.IDE.Plugin.HLS (toResponseError )
1515import Development.IDE.Plugin.Test as Test
1616import Development.IDE.Types.Options
1717import GHC.Base (coerce )
@@ -30,8 +30,6 @@ import Language.LSP.Protocol.Types hiding
3030 mkRange )
3131import Language.LSP.Test
3232import LogType (Log (.. ))
33- import System.Directory
34- import System.Process.Extra (createPipe )
3533import Test.Tasty
3634import Test.Tasty.HUnit
3735import TestUtils
@@ -50,7 +48,6 @@ tests recorder logger = do
5048 pure (InL [] )
5149 ]
5250 }]
53-
5451 testIde recorder (testingLite recorder logger plugins) $ do
5552 doc <- createDoc " A.hs" " haskell" " module A where"
5653 waitForProgressDone
@@ -60,6 +57,7 @@ tests recorder logger = do
6057 liftIO $ assertBool " We caught an error, but it wasn't ours!"
6158 (T. isInfixOf " divide by zero" _message && T. isInfixOf (coerce pluginId) _message)
6259 _ -> liftIO $ assertFailure $ show lens
60+
6361 , testCase " Commands" $ do
6462 let pluginId = " command-exception"
6563 commandId = CommandId " exception"
@@ -71,7 +69,6 @@ tests recorder logger = do
7169 pure (InR Null )
7270 ]
7371 }]
74-
7572 testIde recorder (testingLite recorder logger plugins) $ do
7673 _ <- createDoc " A.hs" " haskell" " module A where"
7774 waitForProgressDone
@@ -83,6 +80,7 @@ tests recorder logger = do
8380 liftIO $ assertBool " We caught an error, but it wasn't ours!"
8481 (T. isInfixOf " divide by zero" _message && T. isInfixOf (coerce pluginId) _message)
8582 _ -> liftIO $ assertFailure $ show res
83+
8684 , testCase " Notification Handlers" $ do
8785 let pluginId = " notification-exception"
8886 plugins = pluginDescToIdePlugins $
@@ -95,101 +93,24 @@ tests recorder logger = do
9593 [ mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
9694 pure (InL [] )
9795 ]
98- }
99- , Notifications. descriptor (cmapWithPrio LogNotifications recorder) " ghcide-core" ]
100-
96+ }]
10197 testIde recorder (testingLite recorder logger plugins) $ do
10298 doc <- createDoc " A.hs" " haskell" " module A where"
10399 waitForProgressDone
104100 (view L. result -> lens) <- request SMethod_TextDocumentCodeLens (CodeLensParams Nothing Nothing doc)
105101 case lens of
106102 Right (InL [] ) ->
103+ -- We don't get error responses from notification handlers, so
104+ -- we can only make sure that the server is still responding
107105 pure ()
108106 _ -> liftIO $ assertFailure $ " We should have had an empty list" <> show lens]
109107
110108 , testGroup " Testing PluginError order..."
111- [ testCase " InternalError over InvalidParams" $ do
112- let pluginId = " internal-error-order"
113- plugins = pluginDescToIdePlugins $
114- [ (defaultPluginDescriptor pluginId)
115- { pluginHandlers = mconcat
116- [ mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
117- throwError $ PluginInternalError " error test"
118- ,mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
119- throwError $ PluginInvalidParams " error test"
120- ]
121- }
122- , Notifications. descriptor (cmapWithPrio LogNotifications recorder) " ghcide-core" ]
123-
124- testIde recorder (testingLite recorder logger plugins) $ do
125- doc <- createDoc " A.hs" " haskell" " module A where"
126- waitForProgressDone
127- (view L. result -> lens) <- request SMethod_TextDocumentCodeLens (CodeLensParams Nothing Nothing doc)
128- case lens of
129- Left (ResponseError {_code = InR ErrorCodes_InternalError , _message}) ->
130- liftIO $ assertBool " We caught an error, but it wasn't ours!"
131- (T. isInfixOf " error test" _message && T. isInfixOf (coerce pluginId) _message)
132- _ -> liftIO $ assertFailure $ show lens
133- , testCase " InvalidParams over InvalidUserState" $ do
134- let pluginId = " invalid-params-order"
135- plugins = pluginDescToIdePlugins $
136- [ (defaultPluginDescriptor pluginId)
137- { pluginHandlers = mconcat
138- [ mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
139- throwError $ PluginInvalidParams " error test"
140- ,mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
141- throwError $ PluginInvalidUserState " error test"
142- ]
143- }
144- , Notifications. descriptor (cmapWithPrio LogNotifications recorder) " ghcide-core" ]
145-
146- testIde recorder (testingLite recorder logger plugins) $ do
147- doc <- createDoc " A.hs" " haskell" " module A where"
148- waitForProgressDone
149- (view L. result -> lens) <- request SMethod_TextDocumentCodeLens (CodeLensParams Nothing Nothing doc)
150- case lens of
151- Left (ResponseError {_code = InR ErrorCodes_InvalidParams , _message}) ->
152- liftIO $ assertBool " We caught an error, but it wasn't ours!"
153- (T. isInfixOf " error test" _message && T. isInfixOf (coerce pluginId) _message)
154- _ -> liftIO $ assertFailure $ show lens
155- , testCase " InvalidUserState over RequestRefused" $ do
156- let pluginId = " invalid-user-state-order"
157- plugins = pluginDescToIdePlugins $
158- [ (defaultPluginDescriptor pluginId)
159- { pluginHandlers = mconcat
160- [ mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
161- throwError $ PluginInvalidUserState " error test"
162- ,mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
163- throwError $ PluginRequestRefused " error test"
164- ]
165- }
166- , Notifications. descriptor (cmapWithPrio LogNotifications recorder) " ghcide-core" ]
167-
168- testIde recorder (testingLite recorder logger plugins) $ do
169- doc <- createDoc " A.hs" " haskell" " module A where"
170- waitForProgressDone
171- (view L. result -> lens) <- request SMethod_TextDocumentCodeLens (CodeLensParams Nothing Nothing doc)
172- case lens of
173- Left (ResponseError {_code = InL LSPErrorCodes_RequestFailed , _message}) ->
174- liftIO $ assertBool " We caught an error, but it wasn't ours!"
175- (T. isInfixOf " error test" _message && T. isInfixOf (coerce pluginId) _message)
176- _ -> liftIO $ assertFailure $ show lens
177- ]]
178-
179- testIde :: Recorder (WithPriority Log ) -> IDE. Arguments -> Session () -> IO ()
180- testIde recorder arguments session = do
181- config <- getConfigFromEnv
182- cwd <- getCurrentDirectory
183- (hInRead, hInWrite) <- createPipe
184- (hOutRead, hOutWrite) <- createPipe
185- let projDir = " ."
186- let server = IDE. defaultMain (cmapWithPrio LogIDEMain recorder) arguments
187- { IDE. argsHandleIn = pure hInRead
188- , IDE. argsHandleOut = pure hOutWrite
189- }
190-
191- flip finally (setCurrentDirectory cwd) $ withAsync server $ \ _ ->
192- runSessionWithHandles hInWrite hOutRead config lspTestCaps projDir session
109+ [ pluginOrderTestCase recorder logger " InternalError over InvalidParams" PluginInternalError PluginInvalidParams
110+ , pluginOrderTestCase recorder logger " InvalidParams over InvalidUserState" PluginInvalidParams PluginInvalidUserState
111+ , pluginOrderTestCase recorder logger " InvalidUserState over RequestRefused" PluginInvalidUserState PluginRequestRefused
112+ ]
113+ ]
193114
194115testingLite :: Recorder (WithPriority Log ) -> Logger -> IdePlugins IdeState -> IDE. Arguments
195116testingLite recorder logger plugins =
@@ -210,3 +131,25 @@ testingLite recorder logger plugins =
210131 { IDE. argsHlsPlugins = hlsPlugins
211132 , IDE. argsIdeOptions = ideOptions
212133 }
134+
135+ pluginOrderTestCase :: Recorder (WithPriority Log ) -> Logger -> TestName -> (T. Text -> PluginError ) -> (T. Text -> PluginError ) -> TestTree
136+ pluginOrderTestCase recorder logger msg err1 err2 =
137+ testCase msg $ do
138+ let pluginId = " error-order-test"
139+ plugins = pluginDescToIdePlugins $
140+ [ (defaultPluginDescriptor pluginId)
141+ { pluginHandlers = mconcat
142+ [ mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
143+ throwError $ err1 " error test"
144+ ,mkPluginHandler SMethod_TextDocumentCodeLens $ \ _ _ _-> do
145+ throwError $ err2 " error test"
146+ ]
147+ }]
148+ testIde recorder (testingLite recorder logger plugins) $ do
149+ doc <- createDoc " A.hs" " haskell" " module A where"
150+ waitForProgressDone
151+ (view L. result -> lens) <- request SMethod_TextDocumentCodeLens (CodeLensParams Nothing Nothing doc)
152+ case lens of
153+ Left re | toResponseError (pluginId, err1 " error test" ) == re -> pure ()
154+ | otherwise -> liftIO $ assertFailure " We caught an error, but it wasn't ours!"
155+ _ -> liftIO $ assertFailure $ show lens
0 commit comments