1111module Main (main ) where
1212
1313import Control.Applicative.Combinators
14- import Control.Exception (catch )
14+ import Control.Exception (bracket_ , catch )
1515import qualified Control.Lens as Lens
1616import Control.Monad
1717import Control.Monad.IO.Class (liftIO )
@@ -41,7 +41,7 @@ import Language.Haskell.LSP.Types.Capabilities
4141import qualified Language.Haskell.LSP.Types.Lens as Lsp (diagnostics , params , message )
4242import Language.Haskell.LSP.VFS (applyChange )
4343import Network.URI
44- import System.Environment.Blank (getEnv , setEnv )
44+ import System.Environment.Blank (unsetEnv , getEnv , setEnv )
4545import System.FilePath
4646import System.IO.Extra hiding (withTempDir )
4747import qualified System.IO.Extra
@@ -58,8 +58,10 @@ import Test.Tasty.HUnit
5858import Test.Tasty.QuickCheck
5959import System.Time.Extra
6060import Development.IDE.Plugin.CodeAction (typeSignatureCommandId , blockCommandId , matchRegExMultipleImports )
61- import Development.IDE.Plugin.Test (WaitForIdeRuleResult (.. ), TestRequest (WaitForIdeRule , BlockSeconds ,GetInterfaceFilesDir ))
61+ import Development.IDE.Plugin.Test (WaitForIdeRuleResult (.. ), TestRequest (BlockSeconds ,GetInterfaceFilesDir ))
6262import Control.Monad.Extra (whenJust )
63+ import qualified Language.Haskell.LSP.Types.Lens as L
64+ import Control.Lens ((^.) )
6365
6466main :: IO ()
6567main = do
@@ -630,11 +632,6 @@ cancellationTemplate (edit, undoEdit) mbKey = testCase (maybe "-" fst mbKey) $ r
630632 -- similar to run except it disables kick
631633 runTestNoKick s = withTempDir $ \ dir -> runInDir' dir " ." " ." [" --test-no-kick" ] s
632634
633- waitForAction key TextDocumentIdentifier {_uri} = do
634- waitId <- sendRequest (CustomClientMethod " test" ) (WaitForIdeRule key _uri)
635- ResponseMessage {_result} <- skipManyTill anyMessage $ responseForId waitId
636- return _result
637-
638635 typeCheck doc = do
639636 Right WaitForIdeRuleResult {.. } <- waitForAction " TypeCheck" doc
640637 liftIO $ assertBool " The file should typecheck" ideResultSuccess
@@ -3388,7 +3385,7 @@ cradleTests :: TestTree
33883385cradleTests = testGroup " cradle"
33893386 [testGroup " dependencies" [sessionDepsArePickedUp]
33903387 ,testGroup " ignore-fatal" [ignoreFatalWarning]
3391- ,testGroup " loading" [loadCradleOnlyonce]
3388+ ,testGroup " loading" [loadCradleOnlyonce, retryFailedCradle ]
33923389 ,testGroup " multi" [simpleMultiTest, simpleMultiTest2]
33933390 ,testGroup " sub-directory" [simpleSubDirectoryTest]
33943391 ]
@@ -3415,6 +3412,43 @@ loadCradleOnlyonce = testGroup "load cradle only once"
34153412 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @ PublishDiagnosticsNotification ))
34163413 liftIO $ length msgs @?= 0
34173414
3415+ retryFailedCradle :: TestTree
3416+ retryFailedCradle = testSession' " retry failed" $ \ dir -> do
3417+ -- The false cradle always fails
3418+ let hieContents = " cradle: {bios: {shell: \" false\" }}"
3419+ hiePath = dir </> " hie.yaml"
3420+ liftIO $ writeFile hiePath hieContents
3421+ hieDoc <- createDoc hiePath " yaml" $ T. pack hieContents
3422+ let aPath = dir </> " A.hs"
3423+ doc <- createDoc aPath " haskell" " main = return ()"
3424+ Right WaitForIdeRuleResult {.. } <- waitForAction " TypeCheck" doc
3425+ liftIO $ " Test assumption failed: cradle should error out" `assertBool` not ideResultSuccess
3426+
3427+ -- Fix the cradle and typecheck again
3428+ let validCradle = " cradle: {bios: {shell: \" echo A.hs\" }}"
3429+ liftIO $ writeFileUTF8 hiePath $ T. unpack validCradle
3430+ changeDoc
3431+ hieDoc
3432+ [ TextDocumentContentChangeEvent
3433+ { _range = Nothing ,
3434+ _rangeLength = Nothing ,
3435+ _text = validCradle
3436+ }
3437+ ]
3438+
3439+ -- Force a session restart by making an edit, just to dirty the typecheck node
3440+ changeDoc
3441+ doc
3442+ [ TextDocumentContentChangeEvent
3443+ { _range = Just Range {_start = Position 0 0 , _end = Position 0 0 },
3444+ _rangeLength = Nothing ,
3445+ _text = " \n "
3446+ }
3447+ ]
3448+
3449+ Right WaitForIdeRuleResult {.. } <- waitForAction " TypeCheck" doc
3450+ liftIO $ " No joy after fixing the cradle" `assertBool` ideResultSuccess
3451+
34183452
34193453dependentFileTest :: TestTree
34203454dependentFileTest = testGroup " addDependentFile"
@@ -3479,17 +3513,19 @@ simpleSubDirectoryTest =
34793513 expectNoMoreDiagnostics 0.5
34803514
34813515simpleMultiTest :: TestTree
3482- simpleMultiTest = testCase " simple-multi-test" $ runWithExtraFiles " multi" $ \ dir -> do
3516+ simpleMultiTest = testCase " simple-multi-test" $ withLongTimeout $ runWithExtraFiles " multi" $ \ dir -> do
34833517 let aPath = dir </> " a/A.hs"
34843518 bPath = dir </> " b/B.hs"
34853519 aSource <- liftIO $ readFileUtf8 aPath
3486- (TextDocumentIdentifier adoc) <- createDoc aPath " haskell" aSource
3487- expectNoMoreDiagnostics 0.5
3520+ adoc <- createDoc aPath " haskell" aSource
3521+ Right WaitForIdeRuleResult {.. } <- waitForAction " TypeCheck" adoc
3522+ liftIO $ assertBool " A should typecheck" ideResultSuccess
34883523 bSource <- liftIO $ readFileUtf8 bPath
34893524 bdoc <- createDoc bPath " haskell" bSource
3490- expectNoMoreDiagnostics 0.5
3525+ Right WaitForIdeRuleResult {.. } <- waitForAction " TypeCheck" bdoc
3526+ liftIO $ assertBool " B should typecheck" ideResultSuccess
34913527 locs <- getDefinitions bdoc (Position 2 7 )
3492- let fooL = mkL adoc 2 0 2 3
3528+ let fooL = mkL ( adoc ^. L. uri) 2 0 2 3
34933529 checkDefs locs (pure [fooL])
34943530 expectNoMoreDiagnostics 0.5
34953531
@@ -3855,6 +3891,9 @@ run' s = withTempDir $ \dir -> runInDir dir (s dir)
38553891runInDir :: FilePath -> Session a -> IO a
38563892runInDir dir = runInDir' dir " ." " ." []
38573893
3894+ withLongTimeout :: IO a -> IO a
3895+ withLongTimeout = bracket_ (setEnv " LSP_TIMEOUT" " 120" True ) (unsetEnv " LSP_TIMEOUT" )
3896+
38583897-- | Takes a directory as well as relative paths to where we should launch the executable as well as the session root.
38593898runInDir' :: FilePath -> FilePath -> FilePath -> [String ] -> Session a -> IO a
38603899runInDir' dir startExeIn startSessionIn extraOptions s = do
@@ -3875,19 +3914,19 @@ runInDir' dir startExeIn startSessionIn extraOptions s = do
38753914 setEnv " HOME" " /homeless-shelter" False
38763915 let lspTestCaps = fullCaps { _window = Just $ WindowClientCapabilities $ Just True }
38773916 logColor <- fromMaybe True <$> checkEnv " LSP_TEST_LOG_COLOR"
3917+ timeoutOverride <- fmap read <$> getEnv " LSP_TIMEOUT"
3918+ let conf = defaultConfig{messageTimeout = fromMaybe (messageTimeout defaultConfig) timeoutOverride}
3919+ -- uncomment this or set LSP_TEST_LOG_STDERR=1 to see all logging
3920+ -- { logStdErr = True }
3921+ -- uncomment this or set LSP_TEST_LOG_MESSAGES=1 to see all messages
3922+ -- { logMessages = True }
38783923 runSessionWithConfig conf{logColor} cmd lspTestCaps projDir s
38793924 where
38803925 checkEnv :: String -> IO (Maybe Bool )
38813926 checkEnv s = fmap convertVal <$> getEnv s
38823927 convertVal " 0" = False
38833928 convertVal _ = True
38843929
3885- conf = defaultConfig
3886- -- uncomment this or set LSP_TEST_LOG_STDERR=1 to see all logging
3887- -- { logStdErr = True }
3888- -- uncomment this or set LSP_TEST_LOG_MESSAGES=1 to see all messages
3889- -- { logMessages = True }
3890-
38913930openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
38923931openTestDataDoc path = do
38933932 source <- liftIO $ readFileUtf8 $ " test/data" </> path
0 commit comments