Also add 'genSublist' which picks a random sublist from a given list.

Signed-off-by: Petr Pudlak <[email protected]>
---
 test/hs/Test/Ganeti/TestCommon.hs | 17 +++++++++++++++++
 test/hs/Test/Ganeti/Utils.hs      | 18 ++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/test/hs/Test/Ganeti/TestCommon.hs 
b/test/hs/Test/Ganeti/TestCommon.hs
index 38a1ab6..bfb1849 100644
--- a/test/hs/Test/Ganeti/TestCommon.hs
+++ b/test/hs/Test/Ganeti/TestCommon.hs
@@ -44,6 +44,7 @@ module Test.Ganeti.TestCommon
   , genFQDN
   , genUUID
   , genMaybe
+  , genSublist
   , genTags
   , genFields
   , genUniquesList
@@ -227,6 +228,22 @@ genUUID = do
 genMaybe :: Gen a -> Gen (Maybe a)
 genMaybe subgen = frequency [ (1, pure Nothing), (3, Just <$> subgen) ]
 
+-- | Generates a sublist of a given list, keeping the ordering.
+-- The generated elements are always a subset of the list.
+--
+-- In order to better support corner cases, the size of the sublist is
+-- chosen to have the uniform distribution.
+genSublist :: [a] -> Gen [a]
+genSublist xs = choose (0, l) >>= g xs l
+  where
+    l = length xs
+    g _      _ 0 = return []
+    g []     _ _ = return []
+    g ys     n k | k == n = return ys
+    g (y:ys) n k = frequency [ (k,     liftM (y :) (g ys (n - 1) (k - 1)))
+                             , (n - k, g ys (n - 1) k)
+                             ]
+
 -- | Defines a tag type.
 newtype TagChar = TagChar { tagGetChar :: Char }
 
diff --git a/test/hs/Test/Ganeti/Utils.hs b/test/hs/Test/Ganeti/Utils.hs
index 5275d5b..b39d3b1 100644
--- a/test/hs/Test/Ganeti/Utils.hs
+++ b/test/hs/Test/Ganeti/Utils.hs
@@ -34,6 +34,8 @@ import Test.HUnit
 import Data.Char (isSpace)
 import qualified Data.Either as Either
 import Data.List
+import Data.Maybe (listToMaybe)
+import qualified Data.Set as S
 import System.Time
 import qualified Text.JSON as J
 #ifndef NO_REGEX_PCRE
@@ -67,6 +69,21 @@ prop_commaSplitJoin :: String -> Property
 prop_commaSplitJoin s =
   commaJoin (sepSplit ',' s) ==? s
 
+-- | Test 'findFirst' on several possible inputs.
+prop_findFirst :: Property
+prop_findFirst =
+  forAll (genSublist [0..5 :: Int]) $ \xs ->
+  forAll (choose (-2, 7)) $ \base ->
+  printTestCase "findFirst utility function" $
+  let r = findFirst base (S.fromList xs)
+      (ss, es) = partition (< r) $ dropWhile (< base) xs
+      -- the prefix must be a range of numbers
+      -- and the suffix must not start with 'r'
+   in conjoin [ and $ zipWith ((==) . (+ 1)) ss (drop 1 ss)
+              , maybe True (> r) (listToMaybe es)
+              ]
+
+
 -- | fromObjWithDefault, we test using the Maybe monad and an integer
 -- value.
 prop_fromObjWithDefault :: Integer -> String -> Bool
@@ -328,6 +345,7 @@ prop_splitRecombineEithers es =
 testSuite "Utils"
             [ 'prop_commaJoinSplit
             , 'prop_commaSplitJoin
+            , 'prop_findFirst
             , 'prop_fromObjWithDefault
             , 'prop_if'if
             , 'prop_select
-- 
1.9.1.423.g4596e3a

Reply via email to