blob: 4ecaa2f5aaed7645d522f7d215ba3bc015ad053c [file] [log] [blame]
{-# LANGUAGE TemplateHaskell #-}
{-| Unittests for the DRBD Parser -}
{-
Copyright (C) 2012 Google Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
-}
module Test.Ganeti.Storage.Drbd.Parser (testBlock_Drbd_Parser) where
import Test.QuickCheck as QuickCheck hiding (Result)
import Test.HUnit
import Test.Ganeti.TestHelper
import Test.Ganeti.TestCommon
import qualified Data.Attoparsec.Text as A
import Data.List (intercalate)
import Data.Text (pack)
import Ganeti.Storage.Drbd.Parser (drbdStatusParser, commaIntParser)
import Ganeti.Storage.Drbd.Types
{-# ANN module "HLint: ignore Use camelCase" #-}
-- | Test a DRBD 8.0 file with an empty line inside.
case_drbd80_emptyline :: Assertion
case_drbd80_emptyline = testParser (drbdStatusParser [])
"proc_drbd80-emptyline.txt" $ DRBDStatus
( VersionInfo (Just "8.0.12") (Just "86") (Just "86") Nothing
(Just "5c9f89594553e32adb87d9638dce591782f947e3")
(Just "root@node1.example.com, 2009-05-22 12:47:52")
)
[ DeviceInfo 0 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate UpToDate) 'C' "r---"
(PerfIndicators 78728316 0 77675644 1277039 254 270 0 0 0 0
Nothing Nothing Nothing)
Nothing
(Just $ AdditionalInfo 0 61 65657 135 0 0 135)
(Just $ AdditionalInfo 0 257 11378843 254 0 0 254)
Nothing,
UnconfiguredDevice 1,
UnconfiguredDevice 2,
UnconfiguredDevice 5,
UnconfiguredDevice 6
]
-- | Test a DRBD 8.0 file with an empty version.
case_drbd80_emptyversion :: Assertion
case_drbd80_emptyversion = testParser (drbdStatusParser [])
"proc_drbd80-emptyversion.txt" $ DRBDStatus
( VersionInfo Nothing Nothing Nothing Nothing
(Just "5c9f89594553e32adb87d9638dce591782f947e3")
(Just "root@node1.example.com, 2009-05-22 12:47:52")
)
[ DeviceInfo 0 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate UpToDate) 'C' "r---"
(PerfIndicators 78728316 0 77675644 1277039 254 270 0 0 0 0
Nothing Nothing Nothing)
Nothing
(Just $ AdditionalInfo 0 61 65657 135 0 0 135)
(Just $ AdditionalInfo 0 257 11378843 254 0 0 254)
Nothing,
UnconfiguredDevice 1,
UnconfiguredDevice 2,
UnconfiguredDevice 5,
UnconfiguredDevice 6
]
-- | Test a DRBD 8.4 file with an ongoing synchronization.
case_drbd84_sync :: Assertion
case_drbd84_sync = testParser (drbdStatusParser []) "proc_drbd84_sync.txt" $
DRBDStatus
( VersionInfo (Just "8.4.2") (Just "1") (Just "86-101") Nothing
(Just "7ad5f850d711223713d6dcadc3dd48860321070c")
(Just "root@example.com, 2013-04-10 07:45:25")
)
[ DeviceInfo 0 StandAlone (LocalRemote Primary Unknown)
(LocalRemote UpToDate DUnknown) ' ' "r-----"
(PerfIndicators 0 0 33318 730 15 0 0 0 0 0 (Just 1)
(Just 'd') (Just 1048320))
Nothing
Nothing
Nothing
Nothing,
UnconfiguredDevice 3,
DeviceInfo 5 SyncSource (LocalRemote Secondary Secondary)
(LocalRemote UpToDate Inconsistent) 'C' "r---n-"
(PerfIndicators 716992 0 0 719432 0 43 0 33 18 0 (Just 1)
(Just 'f') (Just 335744))
(Just $ SyncStatus 68.5 335744 1048576 KiloByte (Time 0 0 5) 64800
Nothing KiloByte Second)
Nothing
Nothing
Nothing
]
-- | Test a DRBD 8.4 file.
case_drbd84 :: Assertion
case_drbd84 = testParser (drbdStatusParser []) "proc_drbd84.txt" $
DRBDStatus
( VersionInfo (Just "8.4.2") (Just "1") (Just "86-101") Nothing
(Just "7ad5f850d711223713d6dcadc3dd48860321070c")
(Just "root@example.com, 2013-04-10 07:45:25")
)
[ DeviceInfo 0 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate UpToDate) 'C' "r-----"
(PerfIndicators 1048576 0 0 1048776 0 64 0 0 0 0 (Just 1)
(Just 'f') (Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 1 Connected (LocalRemote Secondary Primary)
(LocalRemote UpToDate UpToDate) 'C' "r-----"
(PerfIndicators 0 1048576 1048576 0 0 64 0 0 0 0 (Just 1)
(Just 'f') (Just 0))
Nothing
Nothing
Nothing
Nothing,
UnconfiguredDevice 2,
DeviceInfo 4 WFConnection (LocalRemote Primary Unknown)
(LocalRemote UpToDate DUnknown) 'C' "r-----"
(PerfIndicators 0 0 0 200 0 0 0 0 0 0 (Just 1)
(Just 'f') (Just 1048320))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 6 Connected (LocalRemote Secondary Primary)
(LocalRemote Diskless UpToDate) 'C' "r-----"
(PerfIndicators 0 0 0 0 0 0 0 0 0 0 (Just 1) (Just 'b')
(Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 8 StandAlone (LocalRemote Secondary Unknown)
(LocalRemote UpToDate DUnknown) ' ' "r-----"
(PerfIndicators 0 0 0 200 0 0 0 0 0 0 (Just 1)
(Just 'f') (Just 1048320))
Nothing
Nothing
Nothing
Nothing
]
-- | Test a DRBD 8.4 file with the first resource empty.
case_drbd84_emptyfirst :: Assertion
case_drbd84_emptyfirst = testParser (drbdStatusParser [])
"proc_drbd84_emptyfirst.txt" $ DRBDStatus
( VersionInfo (Just "8.4.2") (Just "1") (Just "86-101") Nothing
(Just "7ad5f850d711223713d6dcadc3dd48860321070c")
(Just "root@example.com, 2013-04-10 07:45:25")
)
[ DeviceInfo 1 Connected (LocalRemote Secondary Primary)
(LocalRemote UpToDate UpToDate) 'C' "r-----"
(PerfIndicators 0 1048576 1048576 0 0 64 0 0 0 0 (Just 1)
(Just 'f') (Just 0))
Nothing
Nothing
Nothing
Nothing,
UnconfiguredDevice 2,
DeviceInfo 4 WFConnection (LocalRemote Primary Unknown)
(LocalRemote UpToDate DUnknown) 'C' "r-----"
(PerfIndicators 0 0 0 200 0 0 0 0 0 0 (Just 1)
(Just 'f') (Just 1048320))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 6 Connected (LocalRemote Secondary Primary)
(LocalRemote Diskless UpToDate) 'C' "r-----"
(PerfIndicators 0 0 0 0 0 0 0 0 0 0 (Just 1) (Just 'b')
(Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 8 StandAlone (LocalRemote Secondary Unknown)
(LocalRemote UpToDate DUnknown) ' ' "r-----"
(PerfIndicators 0 0 0 200 0 0 0 0 0 0 (Just 1)
(Just 'f') (Just 1048320))
Nothing
Nothing
Nothing
Nothing
]
-- | Test a DRBD 8.3 file with a NULL caracter inside.
case_drbd83_sync_krnl2_6_39 :: Assertion
case_drbd83_sync_krnl2_6_39 = testParser (drbdStatusParser [])
"proc_drbd83_sync_krnl2.6.39.txt" $ DRBDStatus
( VersionInfo (Just "8.3.1") (Just "88") (Just "86-89") Nothing
(Just "fd40f4a8f9104941537d1afc8521e584a6d3003c")
(Just "phil@fat-tyre, 2009-03-27 12:19:49")
)
[ DeviceInfo 0 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate UpToDate) 'C' "r----"
(PerfIndicators 140978 0 9906 131533 27 8 0 0 0 0 (Just 1)
(Just 'b') (Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 1 Connected (LocalRemote Secondary Primary)
(LocalRemote UpToDate UpToDate) 'C' "r---"
(PerfIndicators 0 140980 140980 0 0 8 0 0 0 0 (Just 1) (Just 'f')
(Just 0))
Nothing
Nothing
Nothing
Nothing,
UnconfiguredDevice 2,
DeviceInfo 3 SyncSource (LocalRemote Primary Secondary)
(LocalRemote UpToDate Inconsistent) 'A' "r-----"
(PerfIndicators 373888 0 0 374088 0 22 7 27 7 0 (Just 1)
(Just 'f') (Just 15358208))
(Just $ SyncStatus 2.4 14996 15360 MegaByte (Time 0 4 8) 61736 Nothing
KiloByte Second)
Nothing
Nothing
Nothing,
DeviceInfo 4 WFConnection (LocalRemote Primary Unknown)
(LocalRemote UpToDate DUnknown) 'C' "r----"
(PerfIndicators 140978 0 9906 131534 27 8 0 0 0 0 (Just 1)
(Just 'b') (Just 0))
Nothing
Nothing
Nothing
Nothing
]
-- | Test a DRBD 8.3 file with an ongoing synchronization.
case_drbd83_sync :: Assertion
case_drbd83_sync = testParser (drbdStatusParser []) "proc_drbd83_sync.txt" $
DRBDStatus
( VersionInfo (Just "8.3.1") (Just "88") (Just "86-89") Nothing
(Just "fd40f4a8f9104941537d1afc8521e584a6d3003c")
(Just "phil@fat-tyre, 2009-03-27 12:19:49")
)
[ DeviceInfo 0 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate UpToDate) 'C' "r----"
(PerfIndicators 140978 0 9906 131533 27 8 0 0 0 0 (Just 1)
(Just 'b') (Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 1 Connected (LocalRemote Secondary Primary)
(LocalRemote UpToDate UpToDate) 'C' "r---"
(PerfIndicators 0 140980 140980 0 0 8 0 0 0 0 (Just 1) (Just 'f')
(Just 0))
Nothing
Nothing
Nothing
Nothing,
UnconfiguredDevice 2,
DeviceInfo 3 SyncTarget (LocalRemote Primary Secondary)
(LocalRemote Inconsistent UpToDate) 'C' "r----"
(PerfIndicators 0 178176 178176 0 104 42 0 0 0 0 (Just 1)
(Just 'b') (Just 346112))
(Just $ SyncStatus 34.9 346112 524288 MegaByte (Time 0 0 5) 59392
Nothing KiloByte Second)
Nothing
Nothing
Nothing,
DeviceInfo 4 WFConnection (LocalRemote Primary Unknown)
(LocalRemote UpToDate DUnknown) 'C' "r----"
(PerfIndicators 140978 0 9906 131534 27 8 0 0 0 0 (Just 1)
(Just 'b') (Just 0))
Nothing
Nothing
Nothing
Nothing
]
-- | Test a DRBD 8.3 file not from git sources, with an ongoing synchronization
-- and the "want" field
case_drbd83_sync_want :: Assertion
case_drbd83_sync_want = testParser (drbdStatusParser [])
"proc_drbd83_sync_want.txt" $ DRBDStatus
( VersionInfo (Just "8.3.11") (Just "88") (Just "86-96")
(Just "2D876214BAAD53B31ADC1D6")
Nothing Nothing
)
[ DeviceInfo 0 SyncTarget (LocalRemote Secondary Primary)
(LocalRemote Inconsistent UpToDate) 'C' "r-----"
(PerfIndicators 0 460288 460160 0 0 28 2 4 1 0 (Just 1)
(Just 'f') (Just 588416))
(Just $ SyncStatus 44.4 588416 1048576 KiloByte (Time 0 0 8) 65736
(Just 61440) KiloByte Second)
Nothing
Nothing
Nothing,
UnconfiguredDevice 1,
UnconfiguredDevice 2,
UnconfiguredDevice 3
]
-- | Test a DRBD 8.3 file.
case_drbd83 :: Assertion
case_drbd83 = testParser (drbdStatusParser []) "proc_drbd83.txt" $
DRBDStatus
( VersionInfo (Just "8.3.1") (Just "88") (Just "86-89")
Nothing
(Just "fd40f4a8f9104941537d1afc8521e584a6d3003c")
(Just "phil@fat-tyre, 2009-03-27 12:19:49")
)
[ DeviceInfo 0 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate UpToDate) 'C' "r----"
(PerfIndicators 140978 0 9906 131533 27 8 0 0 0 0 (Just 1)
(Just 'b') (Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 1 Connected (LocalRemote Secondary Primary)
(LocalRemote UpToDate UpToDate) 'C' "r---"
(PerfIndicators 0 140980 140980 0 0 8 0 0 0 0 (Just 1) (Just 'f')
(Just 0))
Nothing
Nothing
Nothing
Nothing,
UnconfiguredDevice 2,
DeviceInfo 4 WFConnection (LocalRemote Primary Unknown)
(LocalRemote UpToDate DUnknown) 'C' "r----"
(PerfIndicators 140978 0 9906 131534 27 8 0 0 0 0 (Just 1)
(Just 'b') (Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 5 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate Diskless) 'C' "r----"
(PerfIndicators 140978 0 9906 131533 19 8 0 0 0 0 (Just 1)
(Just 'b') (Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 6 Connected (LocalRemote Secondary Primary)
(LocalRemote Diskless UpToDate) 'C' "r---"
(PerfIndicators 0 140978 140978 0 0 8 0 0 0 0 (Just 1) (Just 'f')
(Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 7 WFConnection (LocalRemote Secondary Unknown)
(LocalRemote UpToDate DUnknown) 'C' "r---"
(PerfIndicators 0 140978 140978 0 0 8 0 0 0 0 (Just 1) (Just 'f')
(Just 0))
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 8 StandAlone (LocalRemote Secondary Unknown)
(LocalRemote UpToDate DUnknown) ' ' "r---"
(PerfIndicators 0 140978 140978 0 0 8 0 0 0 0 (Just 1)
(Just 'f') (Just 0))
Nothing
Nothing
Nothing
Nothing
]
-- | Test a DRBD 8.0 file with a missing device.
case_drbd8 :: Assertion
case_drbd8 = testParser (drbdStatusParser []) "proc_drbd8.txt" $
DRBDStatus
( VersionInfo (Just "8.0.12") (Just "86") (Just "86") Nothing
(Just "5c9f89594553e32adb87d9638dce591782f947e3")
(Just "XXX")
)
[ DeviceInfo 0 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate UpToDate) 'C' "r---"
(PerfIndicators 4375577 0 4446279 674 1067 69 0 0 0 0 Nothing
Nothing Nothing)
Nothing
(Just $ AdditionalInfo 0 61 0 0 0 0 0)
(Just $ AdditionalInfo 0 257 793749 1067 0 0 1067)
Nothing,
DeviceInfo 1 Connected (LocalRemote Secondary Primary)
(LocalRemote UpToDate UpToDate) 'C' "r---"
(PerfIndicators 738320 0 738320 554400 67 0 0 0 0 0 Nothing
Nothing Nothing)
Nothing
(Just $ AdditionalInfo 0 61 0 0 0 0 0)
(Just $ AdditionalInfo 0 257 92464 67 0 0 67)
Nothing,
UnconfiguredDevice 2,
DeviceInfo 4 WFConnection (LocalRemote Primary Unknown)
(LocalRemote UpToDate DUnknown) 'C' "r---"
(PerfIndicators 738320 0 738320 554400 67 0 0 0 0 0 Nothing
Nothing Nothing)
Nothing
(Just $ AdditionalInfo 0 61 0 0 0 0 0)
(Just $ AdditionalInfo 0 257 92464 67 0 0 67)
Nothing,
DeviceInfo 5 Connected (LocalRemote Primary Secondary)
(LocalRemote UpToDate Diskless) 'C' "r---"
(PerfIndicators 4375581 0 4446283 674 1069 69 0 0 0 0 Nothing
Nothing Nothing)
Nothing
(Just $ AdditionalInfo 0 61 0 0 0 0 0)
(Just $ AdditionalInfo 0 257 793750 1069 0 0 1069)
Nothing,
DeviceInfo 6 Connected (LocalRemote Secondary Primary)
(LocalRemote Diskless UpToDate) 'C' "r---"
(PerfIndicators 0 4375581 5186925 327 75 214 0 0 0 0 Nothing
Nothing Nothing)
Nothing
Nothing
Nothing
Nothing,
DeviceInfo 7 WFConnection (LocalRemote Secondary Unknown)
(LocalRemote UpToDate DUnknown) 'C' "r---"
(PerfIndicators 0 0 0 0 0 0 0 0 0 0 Nothing Nothing Nothing)
Nothing
(Just $ AdditionalInfo 0 61 0 0 0 0 0)
(Just $ AdditionalInfo 0 257 0 0 0 0 0)
Nothing,
DeviceInfo 8 StandAlone (LocalRemote Secondary Unknown)
(LocalRemote UpToDate DUnknown) ' ' "r---"
(PerfIndicators 0 0 0 0 0 0 0 0 0 0 Nothing Nothing Nothing)
Nothing
(Just $ AdditionalInfo 0 61 0 0 0 0 0)
(Just $ AdditionalInfo 0 257 0 0 0 0 0)
Nothing
]
-- | Function for splitting a list in chunks of a given size.
-- FIXME: an equivalent function exists in Data.List.Split, but it seems
-- pointless to add this package as a dependence just for this single
-- use. In case it is ever added, just remove this function definition
-- and use the one from the package.
splitEvery :: Int -> [e] -> [[e]]
splitEvery i l = map (take i) (splitter l (:) []) where
splitter [] _ n = n
splitter li c n = li `c` splitter (drop i li) c n
-- | Function for testing whether a single comma-separated integer is
-- parsed correctly.
testCommaInt :: String -> Int -> Assertion
testCommaInt numString expectedResult =
case A.parseOnly commaIntParser $ pack numString of
Left msg -> assertFailure $ "Parsing failed: " ++ msg
Right obtained -> assertEqual numString expectedResult obtained
-- | Generate a property test for CommaInt numbers in a given range.
gen_prop_CommaInt :: Int -> Int -> Property
gen_prop_CommaInt minVal maxVal =
forAll (choose (minVal, maxVal)) $ \i ->
case A.parseOnly commaIntParser $ pack (generateCommaInt i) of
Left msg -> failTest $ "Parsing failed: " ++ msg
Right obtained -> i ==? obtained
where generateCommaInt x =
((reverse . intercalate ",") . splitEvery 3) . reverse $ show x
-- | Test if <4 digit integers are recognized correctly.
prop_commaInt_noCommas :: Property
prop_commaInt_noCommas = gen_prop_CommaInt 0 999
-- | Test if integers with 1 comma are recognized correctly.
prop_commaInt_1Comma :: Property
prop_commaInt_1Comma = gen_prop_CommaInt 1000 999999
-- | Test if integers with multiple commas are recognized correctly.
prop_commaInt_multipleCommas :: Property
prop_commaInt_multipleCommas = gen_prop_CommaInt 1000000 (maxBound ::
Int)
-- | Test whether the parser is actually able to behave as intended with
-- numbers without commas. That is, if a number with more than 3 digits
-- is parsed, only up to the first 3 digits are considered (because they
-- are a valid commaInt), and the rest is ignored.
-- e.g.: parse "1234" = 123
prop_commaInt_max3WithoutComma :: Property
prop_commaInt_max3WithoutComma =
forAll (choose (0, maxBound :: Int)) $ \i ->
case A.parseOnly commaIntParser $ pack (show i) of
Left msg -> failTest $ "Parsing failed: " ++ msg
Right obtained ->
obtained < 1000 .&&.
getFirst3Digits i ==? obtained
where getFirst3Digits x =
if x >= 1000
then getFirst3Digits $ x `div` 10
else x
-- | Test if non-triplets are handled correctly (they are assumed NOT being part
-- of the number).
case_commaInt_non_triplet :: Assertion
case_commaInt_non_triplet = testCommaInt "61,736,12" 61736
testSuite "Block/Drbd/Parser"
[ 'case_drbd80_emptyline,
'case_drbd80_emptyversion,
'case_drbd84_sync,
'case_drbd84,
'case_drbd84_emptyfirst,
'case_drbd83_sync_krnl2_6_39,
'case_drbd83_sync,
'case_drbd83_sync_want,
'case_drbd83,
'case_drbd8,
'case_commaInt_non_triplet,
'prop_commaInt_noCommas,
'prop_commaInt_1Comma,
'prop_commaInt_multipleCommas,
'prop_commaInt_max3WithoutComma
]