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