Statistics
| Branch: | Tag: | Revision:

root / test / hs / Test / Ganeti / Hypervisor / Xen / XmParser.hs @ c5a957c3

History | View | Annotate | Download (6.3 kB)

1 b8585908 Michele Tartara
{-# LANGUAGE TemplateHaskell #-}
2 b8585908 Michele Tartara
{-# OPTIONS_GHC -fno-warn-orphans #-}
3 b8585908 Michele Tartara
4 b8585908 Michele Tartara
{-| Unittests for @xm list --long@ parser -}
5 b8585908 Michele Tartara
6 b8585908 Michele Tartara
{-
7 b8585908 Michele Tartara
8 b8585908 Michele Tartara
Copyright (C) 2013 Google Inc.
9 b8585908 Michele Tartara
10 b8585908 Michele Tartara
This program is free software; you can redistribute it and/or modify
11 b8585908 Michele Tartara
it under the terms of the GNU General Public License as published by
12 b8585908 Michele Tartara
the Free Software Foundation; either version 2 of the License, or
13 b8585908 Michele Tartara
(at your option) any later version.
14 b8585908 Michele Tartara
15 b8585908 Michele Tartara
This program is distributed in the hope that it will be useful, but
16 b8585908 Michele Tartara
WITHOUT ANY WARRANTY; without even the implied warranty of
17 b8585908 Michele Tartara
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 b8585908 Michele Tartara
General Public License for more details.
19 b8585908 Michele Tartara
20 b8585908 Michele Tartara
You should have received a copy of the GNU General Public License
21 b8585908 Michele Tartara
along with this program; if not, write to the Free Software
22 b8585908 Michele Tartara
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 b8585908 Michele Tartara
02110-1301, USA.
24 b8585908 Michele Tartara
25 b8585908 Michele Tartara
-}
26 b8585908 Michele Tartara
27 b8585908 Michele Tartara
module Test.Ganeti.Hypervisor.Xen.XmParser
28 b8585908 Michele Tartara
  ( testHypervisor_Xen_XmParser
29 b8585908 Michele Tartara
  ) where
30 b8585908 Michele Tartara
31 b8585908 Michele Tartara
import Test.HUnit
32 b8585908 Michele Tartara
import Test.QuickCheck as QuickCheck hiding (Result)
33 b8585908 Michele Tartara
34 b8585908 Michele Tartara
import Test.Ganeti.TestHelper
35 b8585908 Michele Tartara
import Test.Ganeti.TestCommon
36 b8585908 Michele Tartara
37 b8585908 Michele Tartara
import Control.Monad (liftM)
38 b8585908 Michele Tartara
import qualified Data.Attoparsec.Text as A
39 b8585908 Michele Tartara
import Data.Text (pack)
40 b8585908 Michele Tartara
import Data.Char
41 b8585908 Michele Tartara
import qualified Data.Map as Map
42 c5a957c3 Michele Tartara
import Text.Printf
43 b8585908 Michele Tartara
44 b8585908 Michele Tartara
import Ganeti.Hypervisor.Xen.Types
45 b8585908 Michele Tartara
import Ganeti.Hypervisor.Xen.XmParser
46 b8585908 Michele Tartara
47 b8585908 Michele Tartara
{-# ANN module "HLint: ignore Use camelCase" #-}
48 b8585908 Michele Tartara
49 b8585908 Michele Tartara
-- * Arbitraries
50 b8585908 Michele Tartara
51 b8585908 Michele Tartara
-- | Arbitrary instance for generating configurations.
52 b8585908 Michele Tartara
-- A completely arbitrary configuration would contain too many lists and its
53 b8585908 Michele Tartara
-- size would be to big to be actually parsable in reasonable time.
54 b8585908 Michele Tartara
-- This Arbitrary builds a random Config that is still of a reasonable size.
55 b8585908 Michele Tartara
-- Avoid generating strings that might be interpreted as numbers.
56 b8585908 Michele Tartara
instance Arbitrary LispConfig where
57 b8585908 Michele Tartara
  arbitrary = frequency
58 b8585908 Michele Tartara
    [ (5, liftM LCString (genName `suchThat` (not . canBeNumber)))
59 b8585908 Michele Tartara
    , (5, liftM LCDouble arbitrary)
60 b8585908 Michele Tartara
    , (1, liftM LCList (choose(1,20) >>= (`vectorOf` arbitrary)))
61 b8585908 Michele Tartara
    ]
62 b8585908 Michele Tartara
63 b8585908 Michele Tartara
-- | Determines conservatively whether a string could be a number.
64 b8585908 Michele Tartara
canBeNumber :: String -> Bool
65 b8585908 Michele Tartara
canBeNumber [] = False
66 b8585908 Michele Tartara
canBeNumber (c:[]) = canBeNumberChar c
67 b8585908 Michele Tartara
canBeNumber (c:xs) = canBeNumberChar c && canBeNumber xs
68 b8585908 Michele Tartara
69 b8585908 Michele Tartara
-- | Determines whether a char can be part of the string representation of a
70 b8585908 Michele Tartara
-- number (even in scientific notation).
71 b8585908 Michele Tartara
canBeNumberChar :: Char -> Bool
72 b8585908 Michele Tartara
canBeNumberChar c = isDigit c || (c `elem` "eE-")
73 b8585908 Michele Tartara
74 c5a957c3 Michele Tartara
-- | Generates an arbitrary @xm uptime@ output line.
75 c5a957c3 Michele Tartara
instance Arbitrary UptimeInfo where
76 c5a957c3 Michele Tartara
  arbitrary = do
77 c5a957c3 Michele Tartara
    name <- genFQDN
78 c5a957c3 Michele Tartara
    NonNegative idNum <- arbitrary :: Gen (NonNegative Int)
79 c5a957c3 Michele Tartara
    NonNegative days <- arbitrary :: Gen (NonNegative Int)
80 c5a957c3 Michele Tartara
    hours <- choose (0, 23) :: Gen Int
81 c5a957c3 Michele Tartara
    mins <- choose (0, 59) :: Gen Int
82 c5a957c3 Michele Tartara
    secs <- choose (0, 59) :: Gen Int
83 c5a957c3 Michele Tartara
    let uptime :: String
84 c5a957c3 Michele Tartara
        uptime =
85 c5a957c3 Michele Tartara
          if days /= 0
86 c5a957c3 Michele Tartara
            then printf "%d days, %d:%d:%d" days hours mins secs
87 c5a957c3 Michele Tartara
            else printf "%d:%d:%d" hours mins secs
88 c5a957c3 Michele Tartara
    return $ UptimeInfo name idNum uptime
89 c5a957c3 Michele Tartara
90 b8585908 Michele Tartara
-- * Helper functions for tests
91 b8585908 Michele Tartara
92 b8585908 Michele Tartara
-- | Function for testing whether a domain configuration is parsed correctly.
93 b8585908 Michele Tartara
testDomain :: String -> Map.Map String Domain -> Assertion
94 b8585908 Michele Tartara
testDomain fileName expectedContent = do
95 c5a957c3 Michele Tartara
  fileContent <- readTestData fileName
96 c5a957c3 Michele Tartara
  case A.parseOnly xmListParser $ pack fileContent of
97 c5a957c3 Michele Tartara
    Left msg -> assertFailure $ "Parsing failed: " ++ msg
98 c5a957c3 Michele Tartara
    Right obtained -> assertEqual fileName expectedContent obtained
99 c5a957c3 Michele Tartara
100 c5a957c3 Michele Tartara
-- | Function for testing whether a @xm uptime@ output (stored in a file)
101 c5a957c3 Michele Tartara
-- is parsed correctly.
102 c5a957c3 Michele Tartara
testUptimeInfo :: String -> Map.Map Int UptimeInfo -> Assertion
103 c5a957c3 Michele Tartara
testUptimeInfo fileName expectedContent = do
104 c5a957c3 Michele Tartara
  fileContent <- readTestData fileName
105 c5a957c3 Michele Tartara
  case A.parseOnly xmUptimeParser $ pack fileContent of
106 c5a957c3 Michele Tartara
    Left msg -> assertFailure $ "Parsing failed: " ++ msg
107 c5a957c3 Michele Tartara
    Right obtained -> assertEqual fileName expectedContent obtained
108 b8585908 Michele Tartara
109 b8585908 Michele Tartara
-- | Determines whether two LispConfig are equal, with the exception of Double
110 b8585908 Michele Tartara
-- values, that just need to be "almost equal".
111 b8585908 Michele Tartara
-- Meant mainly for testing purposes, given that Double values may be slightly
112 b8585908 Michele Tartara
-- rounded during parsing.
113 b8585908 Michele Tartara
isAlmostEqual :: LispConfig -> LispConfig -> Bool
114 b8585908 Michele Tartara
isAlmostEqual (LCList c1) (LCList c2) =
115 b8585908 Michele Tartara
  (length c1 == length c2) &&
116 b8585908 Michele Tartara
  foldr
117 b8585908 Michele Tartara
    (\current acc -> (acc && uncurry isAlmostEqual current))
118 b8585908 Michele Tartara
    True
119 b8585908 Michele Tartara
    (zip c1 c2)
120 b8585908 Michele Tartara
isAlmostEqual (LCString s1) (LCString s2) = s1 == s2
121 b8585908 Michele Tartara
isAlmostEqual (LCDouble d1) (LCDouble d2) = abs (d1-d2) <= 1e-12
122 b8585908 Michele Tartara
isAlmostEqual _ _ = False
123 b8585908 Michele Tartara
124 b8585908 Michele Tartara
-- | Function to serialize LispConfigs in such a way that they can be rebuilt
125 b8585908 Michele Tartara
-- again by the lispConfigParser.
126 b8585908 Michele Tartara
serializeConf :: LispConfig -> String
127 b8585908 Michele Tartara
serializeConf (LCList c) = "(" ++ unwords (map serializeConf c) ++ ")"
128 b8585908 Michele Tartara
serializeConf (LCString s) = s
129 b8585908 Michele Tartara
serializeConf (LCDouble d) = show d
130 b8585908 Michele Tartara
131 c5a957c3 Michele Tartara
-- | Function to serialize UptimeInfos in such a way that they can be rebuilt
132 c5a957c3 Michele Tartara
-- againg by the uptimeLineParser.
133 c5a957c3 Michele Tartara
serializeUptime :: UptimeInfo -> String
134 c5a957c3 Michele Tartara
serializeUptime (UptimeInfo name idNum uptime) =
135 c5a957c3 Michele Tartara
  printf "%s\t%d\t%s" name idNum uptime
136 c5a957c3 Michele Tartara
137 b8585908 Michele Tartara
-- | Test whether a randomly generated config can be parsed.
138 b8585908 Michele Tartara
-- Implicitly, this also tests that the Show instance of Config is correct.
139 b8585908 Michele Tartara
prop_config :: LispConfig -> Property
140 b8585908 Michele Tartara
prop_config conf =
141 b8585908 Michele Tartara
  case A.parseOnly lispConfigParser . pack . serializeConf $ conf of
142 b8585908 Michele Tartara
        Left msg -> fail $ "Parsing failed: " ++ msg
143 b8585908 Michele Tartara
        Right obtained -> property $ isAlmostEqual obtained conf
144 b8585908 Michele Tartara
145 c5a957c3 Michele Tartara
-- | Test whether a randomly generated UptimeInfo text line can be parsed.
146 c5a957c3 Michele Tartara
prop_uptimeInfo :: UptimeInfo -> Property
147 c5a957c3 Michele Tartara
prop_uptimeInfo uInfo =
148 c5a957c3 Michele Tartara
  case A.parseOnly uptimeLineParser . pack . serializeUptime $ uInfo of
149 c5a957c3 Michele Tartara
    Left msg -> fail $ "Parsing failed: " ++ msg
150 c5a957c3 Michele Tartara
    Right obtained -> obtained ==? uInfo
151 c5a957c3 Michele Tartara
152 b8585908 Michele Tartara
-- | Test a Xen 4.0.1 @xm list --long@ output.
153 b8585908 Michele Tartara
case_xen401list :: Assertion
154 b8585908 Michele Tartara
case_xen401list = testDomain "xen-xm-list-long-4.0.1.txt" $
155 b8585908 Michele Tartara
  Map.fromList
156 b8585908 Michele Tartara
    [ ("Domain-0", Domain 0 "Domain-0" 184000.41332 ActualRunning Nothing)
157 b8585908 Michele Tartara
    , ("instance1.example.com", Domain 119 "instance1.example.com" 24.116146647
158 b8585908 Michele Tartara
      ActualBlocked Nothing)
159 b8585908 Michele Tartara
    ]
160 b8585908 Michele Tartara
161 c5a957c3 Michele Tartara
-- | Test a Xen 4.0.1 @xm uptime@ output.
162 c5a957c3 Michele Tartara
case_xen401uptime :: Assertion
163 c5a957c3 Michele Tartara
case_xen401uptime = testUptimeInfo "xen-xm-uptime-4.0.1.txt" $
164 c5a957c3 Michele Tartara
  Map.fromList
165 c5a957c3 Michele Tartara
    [ (0, UptimeInfo "Domain-0" 0 "98 days,  2:27:44")
166 c5a957c3 Michele Tartara
    , (119, UptimeInfo "instance1.example.com" 119 "15 days, 20:57:07")
167 c5a957c3 Michele Tartara
    ]
168 c5a957c3 Michele Tartara
169 b8585908 Michele Tartara
testSuite "Hypervisor/Xen/XmParser"
170 b8585908 Michele Tartara
          [ 'prop_config
171 c5a957c3 Michele Tartara
          , 'prop_uptimeInfo
172 b8585908 Michele Tartara
          , 'case_xen401list
173 c5a957c3 Michele Tartara
          , 'case_xen401uptime
174 b8585908 Michele Tartara
          ]