3
3
4
4
module ActionSpec where
5
5
6
+ import Control.Concurrent (MVar , readMVar )
6
7
import qualified Control.Concurrent as C
7
8
import Control.Concurrent.STM
9
+ import Control.Monad.IO.Class (MonadIO (.. ))
8
10
import Development.IDE.Graph (shakeOptions )
9
11
import Development.IDE.Graph.Database (shakeNewDatabase ,
10
- shakeRunDatabase )
12
+ shakeRunDatabase ,
13
+ shakeRunDatabaseForKeys )
11
14
import Development.IDE.Graph.Internal.Database (build , incDatabase )
12
15
import Development.IDE.Graph.Internal.Key
13
16
import Development.IDE.Graph.Internal.Types
@@ -16,15 +19,50 @@ import Example
16
19
import qualified StmContainers.Map as STM
17
20
import Test.Hspec
18
21
22
+
23
+
19
24
spec :: Spec
20
25
spec = do
26
+ describe " apply1" $ it " Test build update, Buggy dirty mechanism in hls-graph #4237" $ do
27
+ let ruleStep1 :: MVar Int -> Rules ()
28
+ ruleStep1 m = addRule $ \ CountRule _old mode -> do
29
+ -- depends on ruleSubBranch, it always changed if dirty
30
+ _ :: Int <- apply1 SubBranchRule
31
+ let r = 1
32
+ case mode of
33
+ -- it update the built step
34
+ RunDependenciesChanged -> do
35
+ _ <- liftIO $ C. modifyMVar m $ \ x -> return (x+ 1 , x)
36
+ return $ RunResult ChangedRecomputeSame " " r (return () )
37
+ -- this won't update the built step
38
+ RunDependenciesSame ->
39
+ return $ RunResult ChangedNothing " " r (return () )
40
+ count <- C. newMVar 0
41
+ count1 <- C. newMVar 0
42
+ db <- shakeNewDatabase shakeOptions $ do
43
+ ruleSubBranch count
44
+ ruleStep1 count1
45
+ -- bootstrapping the database
46
+ _ <- shakeRunDatabase db $ pure $ apply1 CountRule -- count = 1
47
+ let child = newKey SubBranchRule
48
+ let parent = newKey CountRule
49
+ -- instruct to RunDependenciesChanged then CountRule should be recomputed
50
+ -- result should be changed 0, build 1
51
+ _res1 <- shakeRunDatabaseForKeys (Just [child]) db [apply1 CountRule ] -- count = 2
52
+ -- since child changed = parent build
53
+ -- instruct to RunDependenciesSame then CountRule should not be recomputed
54
+ -- result should be changed 0, build 1
55
+ _res3 <- shakeRunDatabaseForKeys (Just [parent]) db [apply1 CountRule ] -- count = 2
56
+ -- invariant child changed = parent build should remains after RunDependenciesSame
57
+ -- this used to be a bug, with additional computation, see https://github.com/haskell/haskell-language-server/pull/4238
58
+ _res3 <- shakeRunDatabaseForKeys (Just [parent]) db [apply1 CountRule ] -- count = 2
59
+ c1 <- readMVar count1
60
+ c1 `shouldBe` 2
21
61
describe " apply1" $ do
22
62
it " computes a rule with no dependencies" $ do
23
- db <- shakeNewDatabase shakeOptions $ do
24
- ruleUnit
63
+ db <- shakeNewDatabase shakeOptions ruleUnit
25
64
res <- shakeRunDatabase db $
26
- pure $ do
27
- apply1 (Rule @ () )
65
+ pure $ apply1 (Rule @ () )
28
66
res `shouldBe` [() ]
29
67
it " computes a rule with one dependency" $ do
30
68
db <- shakeNewDatabase shakeOptions $ do
@@ -38,8 +76,7 @@ spec = do
38
76
ruleBool
39
77
let theKey = Rule @ Bool
40
78
res <- shakeRunDatabase db $
41
- pure $ do
42
- apply1 theKey
79
+ pure $ apply1 theKey
43
80
res `shouldBe` [True ]
44
81
Just (Clean res) <- lookup (newKey theKey) <$> getDatabaseValues theDb
45
82
resultDeps res `shouldBe` ResultDeps [singletonKeySet $ newKey (Rule @ () )]
@@ -49,14 +86,12 @@ spec = do
49
86
ruleBool
50
87
let theKey = Rule @ Bool
51
88
res <- shakeRunDatabase db $
52
- pure $ do
53
- apply1 theKey
89
+ pure $ apply1 theKey
54
90
res `shouldBe` [True ]
55
91
Just KeyDetails {.. } <- atomically $ STM. lookup (newKey (Rule @ () )) databaseValues
56
- keyReverseDeps `shouldBe` ( singletonKeySet $ newKey theKey)
92
+ keyReverseDeps `shouldBe` singletonKeySet ( newKey theKey)
57
93
it " rethrows exceptions" $ do
58
- db <- shakeNewDatabase shakeOptions $ do
59
- addRule $ \ (Rule :: Rule () ) _old _mode -> error " boom"
94
+ db <- shakeNewDatabase shakeOptions $ addRule $ \ (Rule :: Rule () ) _old _mode -> error " boom"
60
95
let res = shakeRunDatabase db $ pure $ apply1 (Rule @ () )
61
96
res `shouldThrow` anyErrorCall
62
97
it " computes a rule with branching dependencies does not invoke phantom dependencies #3423" $ do
@@ -81,18 +116,16 @@ spec = do
81
116
countRes <- build theDb emptyStack [SubBranchRule ]
82
117
snd countRes `shouldBe` [1 :: Int ]
83
118
84
- describe " applyWithoutDependency" $ do
85
- it " does not track dependencies" $ do
86
- db@ (ShakeDatabase _ _ theDb) <- shakeNewDatabase shakeOptions $ do
87
- ruleUnit
88
- addRule $ \ Rule _old _mode -> do
89
- [() ] <- applyWithoutDependency [Rule ]
90
- return $ RunResult ChangedRecomputeDiff " " True $ return ()
119
+ describe " applyWithoutDependency" $ it " does not track dependencies" $ do
120
+ db@ (ShakeDatabase _ _ theDb) <- shakeNewDatabase shakeOptions $ do
121
+ ruleUnit
122
+ addRule $ \ Rule _old _mode -> do
123
+ [() ] <- applyWithoutDependency [Rule ]
124
+ return $ RunResult ChangedRecomputeDiff " " True $ return ()
91
125
92
- let theKey = Rule @ Bool
93
- res <- shakeRunDatabase db $
94
- pure $ do
95
- applyWithoutDependency [theKey]
96
- res `shouldBe` [[True ]]
97
- Just (Clean res) <- lookup (newKey theKey) <$> getDatabaseValues theDb
98
- resultDeps res `shouldBe` UnknownDeps
126
+ let theKey = Rule @ Bool
127
+ res <- shakeRunDatabase db $
128
+ pure $ applyWithoutDependency [theKey]
129
+ res `shouldBe` [[True ]]
130
+ Just (Clean res) <- lookup (newKey theKey) <$> getDatabaseValues theDb
131
+ resultDeps res `shouldBe` UnknownDeps
0 commit comments