Skip to content

Commit dd74487

Browse files
committed
Add tests on shake restart merging
1 parent c53e059 commit dd74487

4 files changed

Lines changed: 75 additions & 10 deletions

File tree

ghcide-test/exe/Main.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import ReferenceTests
6363
import ResolveTests
6464
import RootUriTests
6565
import SafeTests
66+
import ShakeRestartTests
6667
import SymlinkTests
6768
import THTests
6869
import UnitTests
@@ -105,4 +106,5 @@ main = do
105106
, GarbageCollectionTests.tests
106107
, HieDbRetry.tests
107108
, ExceptionTests.tests
109+
, ShakeRestartTests.tests
108110
]
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
{-# OPTIONS_GHC -Wno-orphans #-}
3+
4+
module ShakeRestartTests (tests) where
5+
6+
import Control.Concurrent.STM
7+
import Data.IORef
8+
import Data.IORef.Extra (atomicModifyIORef'_)
9+
import Development.IDE.Core.Shake
10+
import Development.IDE.Graph (newKey)
11+
import Language.LSP.VFS
12+
import Test.Tasty
13+
import Test.Tasty.HUnit
14+
15+
tests :: TestTree
16+
tests = testGroup "shake restart merging"
17+
[ testCase "newestVFSModified" $ do
18+
let vfs1 = VFSModified (VFS mempty)
19+
newestVFSModified VFSUnmodified VFSUnmodified @?= VFSUnmodified
20+
newestVFSModified vfs1 VFSUnmodified @?= vfs1
21+
newestVFSModified VFSUnmodified vfs1 @?= vfs1
22+
23+
, testCase "mergePendingRestart Nothing" $ do
24+
let p = PendingRestart VFSUnmodified (pure []) ["reason"] [] []
25+
if mergePendingRestart p Nothing == p
26+
then pure ()
27+
else assertFailure "merging with nothing should get new"
28+
29+
, testCase "mergePendingRestart Just" $ do
30+
done1 <- newEmptyTMVarIO
31+
done2 <- newEmptyTMVarIO
32+
let key1 = newKey ("1" :: String)
33+
key2 = newKey ("2" :: String)
34+
p1 = PendingRestart VFSUnmodified (pure [key1]) ["r1"] [] [done1]
35+
p2 = PendingRestart VFSUnmodified (pure [key2]) ["r2"] [] [done2]
36+
merged = mergePendingRestart p1 (Just p2)
37+
38+
pendingRestartReasons merged @?= ["r1", "r2"]
39+
keys <- pendingRestartActionBetweenSessions merged
40+
keys @?= [key2, key1]
41+
42+
, testCase "RestartSlot coalescing" $ do
43+
slot <- newRestartSlot
44+
let p1 = PendingRestart VFSUnmodified (pure []) ["r1"] [] []
45+
p2 = PendingRestart VFSUnmodified (pure []) ["r2"] [] []
46+
47+
atomicModifyIORef'_ (queuedRestart slot) $ Just . mergePendingRestart p1
48+
atomicModifyIORef'_ (queuedRestart slot) $ Just . mergePendingRestart p2
49+
50+
res <- atomicModifyIORef' (queuedRestart slot) (Nothing,)
51+
case res of
52+
Nothing -> assertFailure "Should have a pending restart"
53+
Just p -> pendingRestartReasons p @?= ["r2", "r1"]
54+
]
55+
56+
instance Eq VFSModified where
57+
VFSUnmodified == VFSUnmodified = True
58+
VFSModified (VFS _) == VFSModified (VFS _) = True
59+
_ == _ = False
60+
61+
instance Eq PendingRestart where
62+
p1 == p2 = pendingRestartVFS p1 == pendingRestartVFS p2 &&
63+
pendingRestartReasons p1 == pendingRestartReasons p2

ghcide/src/Development/IDE/Core/Shake.hs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ module Development.IDE.Core.Shake(
7272
IndexQueue,
7373
HieDb,
7474
HieDbWriter(..),
75+
PendingRestart(..),
76+
RestartSlot(..),
7577
addPersistentRule,
78+
newestVFSModified,
79+
mergePendingRestart,
7680
garbageCollectDirtyKeys,
7781
garbageCollectDirtyKeysOlderThan,
7882
Log(..),
@@ -133,10 +137,8 @@ import Development.IDE.Core.WorkerThread
133137
import Development.IDE.Types.Options as Options
134138
import qualified Language.LSP.Protocol.Message as LSP
135139
import qualified Language.LSP.Server as LSP
136-
import qualified Language.LSP.VFS as VFS
137140

138141
import Development.IDE.Core.Tracing
139-
import Development.IDE.Core.WorkerThread
140142
#if MIN_VERSION_ghc(9,13,0)
141143
import Development.IDE.GHC.Compat (NameCache,
142144
NameCacheUpdater,
@@ -830,15 +832,10 @@ mergePendingRestart :: PendingRestart -> Maybe PendingRestart -> PendingRestart
830832
mergePendingRestart new Nothing = new
831833
mergePendingRestart new (Just old) = PendingRestart
832834
{ pendingRestartVFS = newestVFSModified (pendingRestartVFS new) (pendingRestartVFS old)
833-
, pendingRestartActions = do
834-
old' <- pendingRestartActions old
835-
new' <- pendingRestartActions new
836-
pure $ new' <> old'
837835
, pendingRestartReasons = pendingRestartReasons new <> pendingRestartReasons old
838-
, pendingRestartActionBetweenSessions = do
839-
old' <- pendingRestartActionBetweenSessions old
840-
new' <- pendingRestartActionBetweenSessions new
841-
pure $ new' <> old'
836+
-- TODO: Contains a quadratic list append on the number of accumulated shake restarts.
837+
, pendingRestartActions = pendingRestartActions old <> pendingRestartActions new
838+
, pendingRestartActionBetweenSessions = pendingRestartActionBetweenSessions old <> pendingRestartActionBetweenSessions new
842839
, pendingRestartDoneSignals = pendingRestartDoneSignals new <> pendingRestartDoneSignals old }
843840

844841
data RestartSlot = RestartSlot
@@ -931,6 +928,7 @@ shakeEnqueue ShakeExtras{actionQueue, shakeRecorder} act = do
931928
return (wait' b >>= either throwIO return)
932929

933930
data VFSModified = VFSUnmodified | VFSModified !VFS
931+
deriving Show
934932

935933
-- | Set up a new 'ShakeSession' with a set of initial actions
936934
-- Will crash if there is an existing 'ShakeSession' running.

haskell-language-server.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,6 +2107,7 @@ test-suite ghcide-tests
21072107
, extra
21082108
, filepath
21092109
, ghcide
2110+
, hls-graph
21102111
, hls-plugin-api
21112112
, lens
21122113
, list-t
@@ -2174,6 +2175,7 @@ test-suite ghcide-tests
21742175
ResolveTests
21752176
RootUriTests
21762177
SafeTests
2178+
ShakeRestartTests
21772179
SymlinkTests
21782180
THTests
21792181
UnitTests

0 commit comments

Comments
 (0)