From 311e9ea018ce1721cd79341243b79afdda85e2f1 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Sat, 19 May 2018 00:22:19 -0400 Subject: [PATCH] Start work on matching expected results --- example/Recorded.hs | 4 +- src/Language/Haskell/LSP/Test/Recorded.hs | 46 ++++++++++++++--------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/example/Recorded.hs b/example/Recorded.hs index dc4aa69..e267ff8 100644 --- a/example/Recorded.hs +++ b/example/Recorded.hs @@ -3,5 +3,5 @@ import System.Directory import System.Environment main = do - file <- (head <$> getArgs) >>= canonicalizePath - replay file + [client, server] <- ((take 2) <$> getArgs) >>= mapM canonicalizePath + replay client server diff --git a/src/Language/Haskell/LSP/Test/Recorded.hs b/src/Language/Haskell/LSP/Test/Recorded.hs index 10aebe3..6bf2319 100644 --- a/src/Language/Haskell/LSP/Test/Recorded.hs +++ b/src/Language/Haskell/LSP/Test/Recorded.hs @@ -15,8 +15,12 @@ import Data.Aeson import System.IO import System.Process -replay :: FilePath -> IO Int -replay fp = do +-- | Replays a recorded client output and +-- makes sure it matches up with an expected response. +replay :: FilePath -- ^ The client output to replay to the server. + -> FilePath -- ^ The expected response from the server. + -> IO Int +replay cfp sfp = do (Just serverIn, Just serverOut, _, _) <- createProcess (proc "hie" ["--lsp", "-l", "/tmp/hie.log", "-d"]) { std_in = CreatePipe @@ -29,21 +33,24 @@ replay fp = do -- whether to send the next request semaphore <- newEmptyMVar + -- the recorded client input to the server + clientRecIn <- openFile cfp ReadMode + serverRecIn <- openFile sfp ReadMode + null <- openFile "/dev/null" WriteMode + -- listen to server forkIO $ forever $ do - headers <- getHeaders serverOut - case read . init <$> lookup "Content-Length" headers of - Nothing -> error "Couldn't read Content-Length header" - Just size -> do - message <- B.hGet serverOut size - case decode message :: Maybe (LSP.ResponseMessage Value) of + msg <- getNextMessage serverOut + expectedMsg <- getNextMessage serverRecIn + putStrLn $ "received: " ++ (show msg) + putStrLn $ "next expected: " ++ (show expectedMsg) + case decode msg :: Maybe (LSP.RequestMessage Value Value Value) of + Just _ -> putStrLn "ignoring request" >> return () + Nothing -> when (msg /= expectedMsg) $ error ("Expected " ++ show expectedMsg ++ " but got " ++ show msg) + case decode msg :: Maybe (LSP.ResponseMessage Value) of Just _ -> putMVar semaphore () Nothing -> return () -- might be a notification or something, that's ok - -- the recorded client input to the server - clientRecIn <- openFile fp ReadMode - null <- openFile "/dev/null" WriteMode - -- send inialize request ourselves since haskell-lsp consumes it -- rest are handled via `handlers` sendInitialize clientRecIn serverIn @@ -57,15 +64,20 @@ replay fp = do Nothing where sendInitialize recH serverH = do - headers <- getHeaders recH - case read . init <$> lookup "Content-Length" headers of - Nothing -> error "Failed to read the read the initialize request" - Just size -> do - message <- B.hGet recH size + message <- getNextMessage recH B.hPut serverH (addHeader message) -- bring the file back to the start for haskell-lsp hSeek recH AbsoluteSeek 0 +-- | Fetches the next message bytes based on +-- the Content-Length header +getNextMessage :: Handle -> IO B.ByteString +getNextMessage h = do + headers <- getHeaders h + case read . init <$> lookup "Content-Length" headers of + Nothing -> error "Couldn't read Content-Length header" + Just size -> B.hGet h size + handlers :: Handle -> MVar () -> Handlers handlers serverH flag = def -- 2.30.2