List.hs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. {-# LANGUAGE TemplateHaskell #-}
  2. {-# LANGUAGE CPP #-}
  3. #if __GLASGOW_HASKELL__ > 800
  4. {-# OPTIONS_GHC -Wno-error=missing-signatures #-}
  5. #endif
  6. {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
  7. module Internal.Utils.List ( tests ) where
  8. import Agda.Utils.List
  9. import Data.Either (partitionEithers)
  10. import Data.Function
  11. import Data.List ( (\\), elemIndex, intercalate, isPrefixOf, isSuffixOf, nub, nubBy, sort, sortBy )
  12. import Internal.Helpers
  13. ------------------------------------------------------------------------------
  14. prop_last2 a b as = last2 (a:b:as) == toPair (drop (length as) $ a:b:as)
  15. where
  16. toPair [x,y] = Just (x,y)
  17. toPair _ = Nothing
  18. prop_dropEnd n as = dropEnd n as == reverse (drop n (reverse as))
  19. -- Trivial:
  20. -- prop_initLast_nil = initLast [] == Nothing
  21. prop_initLast_cons a as = initLast xs == Just (init xs, last xs)
  22. where xs = a:as
  23. spec_updateHead f as = let (bs, cs) = splitAt 1 as in map f bs ++ cs
  24. prop_updateHead f as = updateHead f as == spec_updateHead f as
  25. spec_updateLast f as = let (bs, cs) = splitAt (length as - 1) as in bs ++ map f cs
  26. prop_updateLast f as = updateLast f as == spec_updateLast f as
  27. spec_updateAt n f as = let (bs, cs) = splitAt n as in bs ++ updateHead f cs
  28. prop_updateAt (NonNegative n) f as = updateAt n f as == spec_updateAt n f as
  29. prop_spanEnd_split p xs = let (ys, zs) = spanEnd p xs in xs == ys ++ zs
  30. prop_spanEnd_holds p xs = let (ys, zs) = spanEnd p xs in all p zs
  31. prop_spanEnd_maximal p xs = let (ys, zs) = spanEnd p xs in maybe True (not . p) (lastMaybe ys)
  32. prop_partitionMaybe :: (Int -> Maybe Bool) -> [Int] -> Bool
  33. prop_partitionMaybe f as = partitionMaybe f as == partitionEithers (map f' as)
  34. where f' a = maybe (Left a) Right $ f a
  35. prop_mapMaybeAndRest_Nothing as = mapMaybeAndRest (const Nothing) as == ([] :: [Int],as)
  36. prop_mapMaybeAndRest_Just as = mapMaybeAndRest Just as == (as,[])
  37. prop_stripSuffix_sound suf xs = maybe True (\ pre -> xs == pre ++ suf) $ stripSuffix suf xs
  38. prop_stripSuffix_complete pre suf = stripSuffix suf (pre ++ suf) == Just pre
  39. prop_stripReversedSuffix_sound rsuf xs = maybe True (\ pre -> xs == pre ++ reverse rsuf) $ stripReversedSuffix rsuf xs
  40. prop_stripReversedSuffix_complete pre rsuf = stripReversedSuffix rsuf (pre ++ reverse rsuf) == Just pre
  41. prop_chop_intercalate :: Property
  42. prop_chop_intercalate =
  43. forAllShrink (choose (0, 4 :: Int)) shrink $ \ d ->
  44. forAllShrink (listOf (choose (0, 4 :: Int))) shrink $ \ xs ->
  45. xs === intercalate [d] (chopWhen (== d) xs)
  46. prop_distinct_fastDistinct :: [Integer] -> Bool
  47. prop_distinct_fastDistinct xs = distinct xs == fastDistinct xs
  48. -- To test duplicates, we distinguish them with a decoration by some small natural number.
  49. data Decorate a = Decorate (Positive (Small Int)) a
  50. deriving (Show)
  51. instance Eq a => Eq (Decorate a) where
  52. (==) = (==) `on` (\ (Decorate _ a) -> a)
  53. instance Ord a => Ord (Decorate a) where
  54. compare = compare `on` (\ (Decorate _ a) -> a)
  55. instance Arbitrary a => Arbitrary (Decorate a) where
  56. arbitrary = Decorate <$> arbitrary <*> arbitrary
  57. prop_allDuplicates :: [Decorate (Positive Int)] -> Bool
  58. prop_allDuplicates xs = allDuplicates xs `sameList` sort (xs \\ nub xs)
  59. where
  60. sameList xs ys = and $ zipWith same xs ys
  61. same (Decorate i a) (Decorate j b) = i == j && a == b
  62. prop_groupBy' :: (Bool -> Bool -> Bool) -> [Bool] -> Property
  63. prop_groupBy' p xs =
  64. classify (length xs - length gs >= 3) "interesting" $
  65. concat gs == xs
  66. &&
  67. and [not (null zs) | zs <- gs]
  68. &&
  69. and [and (pairInitTail zs zs) | zs <- gs]
  70. &&
  71. (null gs || not (or (pairInitTail (map last gs) (map head gs))))
  72. where gs = groupBy' p xs
  73. pairInitTail xs ys = zipWith p (init xs) (tail ys)
  74. prop_genericElemIndex :: Integer -> [Integer] -> Property
  75. prop_genericElemIndex x xs =
  76. classify (x `elem` xs) "members" $
  77. genericElemIndex x xs == elemIndex x xs
  78. prop_zipWith' :: (Integer -> Integer -> Integer) -> Property
  79. prop_zipWith' f =
  80. forAll natural $ \n ->
  81. forAll (two $ vector n) $ \(xs, ys) ->
  82. zipWith' f xs ys == Just (zipWith f xs ys)
  83. -- | Defining property of zipWithKeepRest
  84. prop_zipWithKeepRest f as bs =
  85. zipWithKeepRest f as bs == zipWith f as bs ++ drop (length as) bs
  86. -- Redundant properties of zipWithKeepRest:
  87. -- | The second list does not get shorter.
  88. prop_zipWithKeepRest_length f as bs =
  89. length (zipWithKeepRest f as bs) == length bs
  90. -- | If the first list is at least as long as the second,
  91. -- 'zipWithKeepRest' behaves like 'zipWith'.
  92. prop_zipWithKeepRest_first_longer f as bs =
  93. let cs = as ++ bs in
  94. zipWithKeepRest f cs bs == zipWith f cs bs
  95. -- | The rest of the second list is unchanged.
  96. prop_zipWithKeepRest_rest_unchanged f as bs =
  97. drop (length as) (zipWithKeepRest f as bs) == drop (length as) bs
  98. -- | The initial part is like in zipWith.
  99. prop_zipWithKeepRest_init_zipWith f as bs =
  100. take (length as) (zipWithKeepRest f as bs) ==
  101. take (length as) (zipWith f as bs)
  102. prop_nubOn :: (Integer -> Integer) -> [Integer] -> Bool
  103. prop_nubOn f xs = nubOn f xs == nubBy ((==) `on` f) xs
  104. prop_nubAndDuplicatesOn :: (Integer -> Integer) -> [Integer] -> Bool
  105. prop_nubAndDuplicatesOn f xs = nubAndDuplicatesOn f xs == (ys, xs \\ ys)
  106. where ys = nubBy ((==) `on` f) xs
  107. prop_uniqOn1 :: (Integer -> Integer) -> [Integer] -> Bool
  108. prop_uniqOn1 f xs = uniqOn f xs == sortBy (compare `on` f) (nubBy ((==) `on` f) xs)
  109. prop_commonPrefix :: [Integer] -> [Integer] -> [Integer] -> Bool
  110. prop_commonPrefix xs ys zs =
  111. and [ isPrefixOf zs zs'
  112. , isPrefixOf zs' (zs ++ xs)
  113. , isPrefixOf zs' (zs ++ ys) ]
  114. where
  115. zs' = commonPrefix (zs ++ xs) (zs ++ ys)
  116. prop_commonSuffix :: [Integer] -> [Integer] -> [Integer] -> Bool
  117. prop_commonSuffix xs ys zs =
  118. and [ isSuffixOf zs zs'
  119. , isSuffixOf zs' (xs ++ zs)
  120. , isSuffixOf zs' (ys ++ zs) ]
  121. where
  122. zs' = commonSuffix (xs ++ zs) (ys ++ zs)
  123. prop_editDistance :: Property
  124. prop_editDistance =
  125. forAllShrink (choose (0, 10)) shrink $ \ n ->
  126. forAllShrink (choose (0, 10)) shrink $ \ m ->
  127. forAllShrink (vector n) shrink $ \ xs ->
  128. forAllShrink (vector m) shrink $ \ ys ->
  129. editDistanceSpec xs ys == editDistance xs (ys :: [Integer])
  130. ------------------------------------------------------------------------
  131. -- * All tests
  132. ------------------------------------------------------------------------
  133. -- Template Haskell hack to make the following $allProperties work
  134. -- under ghc-7.8.
  135. return [] -- KEEP!
  136. -- | All tests as collected by 'allProperties'.
  137. --
  138. -- Using 'allProperties' is convenient and superior to the manual
  139. -- enumeration of tests, since the name of the property is added
  140. -- automatically.
  141. tests :: TestTree
  142. tests = testProperties "Internal.Utils.List" $allProperties