Revision b009f682

b/src/Ganeti/Utils.hs
46 46
  , rStripSpace
47 47
  , newUUID
48 48
  , clockTimeToString
49
  , chompPrefix
49 50
  ) where
50 51

  
51 52
import Data.Char (toUpper, isAlphaNum, isDigit, isSpace)
......
292 293
-- | Convert a ClockTime into a (seconds-only) timestamp.
293 294
clockTimeToString :: ClockTime -> String
294 295
clockTimeToString (TOD t _) = show t
296

  
297
{-| Strip a prefix from a string, allowing the last character of the prefix
298
(which is assumed to be a separator) to be absent from the string if the string
299
terminates there.
300

  
301
>>> chompPrefix "foo:bar:" "a:b:c"
302
Nothing
303

  
304
>>> chompPrefix "foo:bar:" "foo:bar:baz"
305
Just "baz"
306

  
307
>>> chompPrefix "foo:bar:" "foo:bar:"
308
Just ""
309

  
310
>>> chompPrefix "foo:bar:" "foo:bar"
311
Just ""
312

  
313
>>> chompPrefix "foo:bar:" "foo:barbaz"
314
Nothing
315
-}
316
chompPrefix :: String -> String -> Maybe String
317
chompPrefix pfx str =
318
  if pfx `isPrefixOf` str || str == init pfx
319
    then Just $ drop (length pfx) str
320
    else Nothing
b/test/hs/Test/Ganeti/Utils.hs
238 238
prop_clockTimeToString ts pico =
239 239
  clockTimeToString (TOD ts pico) ==? show ts
240 240

  
241
-- | Test normal operation for 'chompPrefix'.
242
--
243
-- Any random prefix of a string must be stripped correctly, including the empty
244
-- prefix, and the whole string.
245
prop_chompPrefix_normal :: String -> Property
246
prop_chompPrefix_normal str =
247
  forAll (choose (0, length str)) $ \size ->
248
  chompPrefix (take size str) str ==? (Just $ drop size str)
249

  
250
-- | Test that 'chompPrefix' correctly allows the last char (the separator) to
251
-- be absent if the string terminates there.
252
prop_chompPrefix_last :: Property
253
prop_chompPrefix_last =
254
  forAll (choose (1, 20)) $ \len ->
255
  forAll (vectorOf len arbitrary) $ \pfx ->
256
  chompPrefix pfx pfx ==? Just "" .&&.
257
  chompPrefix pfx (init pfx) ==? Just ""
258

  
259
-- | Test that chompPrefix on the empty string always returns Nothing for
260
-- prefixes of length 2 or more.
261
prop_chompPrefix_empty_string :: Property
262
prop_chompPrefix_empty_string =
263
  forAll (choose (2, 20)) $ \len ->
264
  forAll (vectorOf len arbitrary) $ \pfx ->
265
  chompPrefix pfx "" ==? Nothing
266

  
267
-- | Test 'chompPrefix' returns Nothing when the prefix doesn't match.
268
prop_chompPrefix_nothing :: Property
269
prop_chompPrefix_nothing =
270
  forAll (choose (1, 20)) $ \len ->
271
  forAll (vectorOf len arbitrary) $ \pfx ->
272
  forAll (arbitrary `suchThat`
273
          (\s -> not (pfx `isPrefixOf` s) && s /= init pfx)) $ \str ->
274
  chompPrefix pfx str ==? Nothing
275

  
276

  
241 277
-- | Test list for the Utils module.
242 278
testSuite "Utils"
243 279
            [ 'prop_commaJoinSplit
......
258 294
            , 'case_new_uuid
259 295
#endif
260 296
            , 'prop_clockTimeToString
297
            , 'prop_chompPrefix_normal
298
            , 'prop_chompPrefix_last
299
            , 'prop_chompPrefix_empty_string
300
            , 'prop_chompPrefix_nothing
261 301
            ]

Also available in: Unified diff