11{-# LANGUAGE DerivingStrategies #-}
2+ {-# LANGUAGE TypeApplications #-}
23{-# LANGUAGE ScopedTypeVariables #-}
34{-# LANGUAGE NumericUnderscores #-}
45{-# LANGUAGE ImportQualifiedPost #-}
@@ -68,6 +69,24 @@ prop_topsort_sound g =
6869 go [] = True
6970 go (n : ns) = all (\ n' -> not $ dependsOn n n' g) ns && go ns
7071
72+ prop_find_cycle_sound :: Property
73+ prop_find_cycle_sound =
74+ forAllShrink (mkGraph @ Node <$> arbitrary) shrink $ \ g ->
75+ and [ all (\ (x, y) -> dependsOn x y g) (zip c (drop 1 c))
76+ | n <- Set. toList $ nodes g
77+ , let c = findCycle g n
78+ ]
79+
80+ prop_find_cycle_loops :: Property
81+ prop_find_cycle_loops =
82+ forAllShrink (mkGraph @ Node <$> arbitrary) shrink $ \ g ->
83+ conjoin
84+ [ case findCycle g n of
85+ [] -> discard
86+ c@ (x: _) -> counterexample (show c) $ dependsOn (last c) x g
87+ | n <- Set. toList $ nodes g
88+ ]
89+
7190tests :: Bool -> Spec
7291tests _nightly =
7392 describe " Graph tests" $ do
@@ -80,3 +99,5 @@ tests _nightly =
8099 prop " prop_depends_grows" $ withMaxSuccess 10000 prop_depends_grows
81100 prop " prop_topsort_all_nodes" $ withMaxSuccess 10000 prop_topsort_all_nodes
82101 prop " prop_topsort_sound" $ withMaxSuccess 10000 prop_topsort_sound
102+ prop " prop_find_cycle_sound" $ withMaxSuccess 10000 prop_find_cycle_sound
103+ prop " prop_find_cycle_loops" $ withMaxSuccess 10000 prop_find_cycle_loops
0 commit comments