Test if the input file imported with the --mond-data option is
parsed properly.

Signed-off-by: Spyros Trigazis <[email protected]>
---
 Makefile.am                                    |    1 +
 src/Ganeti/HTools/ExtLoader.hs                 |    1 +
 test/data/mond-data.txt                        |    1 +
 test/hs/Test/Ganeti/HTools/ExtLoader.hs        |  110 ++++++++++++++++++++++++
 test/hs/Test/Ganeti/Hypervisor/Xen/XmParser.hs |   16 ----
 test/hs/Test/Ganeti/TestCommon.hs              |   17 ++++
 6 files changed, 130 insertions(+), 16 deletions(-)
 create mode 100644 test/data/mond-data.txt
 create mode 100644 test/hs/Test/Ganeti/HTools/ExtLoader.hs

diff --git a/Makefile.am b/Makefile.am
index 016db5f..bd831a5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -736,6 +736,7 @@ HS_TEST_SRCS = \
        test/hs/Test/Ganeti/HTools/CLI.hs \
        test/hs/Test/Ganeti/HTools/Cluster.hs \
        test/hs/Test/Ganeti/HTools/Container.hs \
+       test/hs/Test/Ganeti/HTools/ExtLoader.hs \
        test/hs/Test/Ganeti/HTools/Graph.hs \
        test/hs/Test/Ganeti/HTools/Instance.hs \
        test/hs/Test/Ganeti/HTools/Loader.hs \
diff --git a/src/Ganeti/HTools/ExtLoader.hs b/src/Ganeti/HTools/ExtLoader.hs
index 972dfec..8860a04 100644
--- a/src/Ganeti/HTools/ExtLoader.hs
+++ b/src/Ganeti/HTools/ExtLoader.hs
@@ -34,6 +34,7 @@ module Ganeti.HTools.ExtLoader
   , commonSuffix
   , maybeSaveData
   , queryAllMonDDCs
+  , pMonDData
   ) where
 
 import Control.Monad
diff --git a/test/data/mond-data.txt b/test/data/mond-data.txt
new file mode 100644
index 0000000..0f5447c
--- /dev/null
+++ b/test/data/mond-data.txt
@@ -0,0 +1 @@
+[{"node":"node1.example.com","reports":[{"name":"cpu-avg-load","version":"B","format_version":1,"timestamp":1379507272000000000,"category":null,"kind":0,"data":{"cpu_number":4,"cpus":[4.108859597350646e-2,4.456554528165781e-2,6.203619909502262e-2,5.595448881893895e-2],"cpu_total":0.203643517607712}}]},{"node":"node2.example.com","reports":[{"name":"cpu-avg-load","version":"B","format_version":1,"timestamp":1379507280000000000,"category":null,"kind":0,"data":{"cpu_number":2,"cpus":[4.155409618511363e-3,3.4586452012150787e-3],"cpu_total":7.614031289927129e-3}}]}]
diff --git a/test/hs/Test/Ganeti/HTools/ExtLoader.hs 
b/test/hs/Test/Ganeti/HTools/ExtLoader.hs
new file mode 100644
index 0000000..3ac49a1
--- /dev/null
+++ b/test/hs/Test/Ganeti/HTools/ExtLoader.hs
@@ -0,0 +1,110 @@
+{-| Unittests for the MonD data parse function -}
+
+{-
+
+Copyright (C) 2013 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.HTools.ExtLoader where
+
+import Data.Ratio
+
+import qualified Test.HUnit as HUnit
+import qualified Text.JSON as J
+
+import qualified Ganeti.BasicTypes as BT
+import qualified Ganeti.DataCollectors.CPUload as CPUload
+
+import Ganeti.Cpu.Types (CPUavgload(..))
+import Ganeti.DataCollectors.Types (DCReport(..))
+import Ganeti.HTools.ExtLoader
+import Ganeti.JSON
+import Test.Ganeti.TestCommon
+
+-- | Test a MonD data file.
+case_parseMonDData :: HUnit.Assertion
+case_parseMonDData = do
+  let mond_data_file = "mond-data.txt"
+      n1 = "node1.example.com"
+      n2 = "node2.example.com"
+      t1 = 1379507272000000000
+      t2 = 1379507280000000000
+      cpu_number1 = 4
+      cpu_number2 = 2
+      cpus1 = [ 0.04108859597350646,0.04456554528165781
+               , 0.06203619909502262,0.05595448881893895]
+      cpus2 = [0.004155409618511363,0.0034586452012150787]
+      cpu_total1 = 0.203643517607712
+      cpu_total2 = 0.007614031289927129
+      dcr1 = DCReport CPUload.dcName CPUload.dcVersion CPUload.dcFormatVersion
+               t1 CPUload.dcCategory CPUload.dcKind
+               (J.showJSON (CPUavgload cpu_number1 cpus1 cpu_total1))
+      dcr2 = DCReport CPUload.dcName CPUload.dcVersion CPUload.dcFormatVersion
+               t2 CPUload.dcCategory CPUload.dcKind
+               (J.showJSON (CPUavgload cpu_number2 cpus2 cpu_total2))
+      expected_list = [(n1,[dcr1]),(n2,[dcr2])]
+  ans <- readTestData mond_data_file
+  case pMonDData ans of
+    BT.Ok l -> HUnit.assertBool ("Parsing " ++ mond_data_file ++ " failed")
+                 (isAlEqual expected_list l)
+    BT.Bad s -> HUnit.assertFailure $ "Parsing failed: " ++ s
+
+-- | Check for quality two list of tuples.
+isAlEqual :: [(String, [DCReport])] -> [(String, [DCReport])] -> Bool
+isAlEqual a b = and (zipWith tupleIsAlEqual a b)
+
+-- | Check a tuple for quality.
+tupleIsAlEqual :: (String, [DCReport]) -> (String, [DCReport]) -> Bool
+tupleIsAlEqual (na, a) (nb, b) =
+  na == nb
+  && and (zipWith dcReportIsAlmostEqual a b)
+
+-- | Check if two DCReports are equal. Only reports from CPUload Data
+-- Collectors are supported.
+dcReportIsAlmostEqual :: DCReport -> DCReport -> Bool
+dcReportIsAlmostEqual a b =
+  dcReportName a == dcReportName b
+  && dcReportVersion a == dcReportVersion b
+  && dcReportFormatVersion a == dcReportFormatVersion b
+  && dcReportTimestamp a == dcReportTimestamp b
+  && dcReportCategory a == dcReportCategory b
+  && dcReportKind a == dcReportKind b
+  && case () of
+       _ | CPUload.dcName == dcReportName a ->
+             cpuavgloadDataIsAlmostEq (dcReportData a) (dcReportData b)
+         | otherwise -> False
+
+-- | Converts two JSValue objects and compares them.
+cpuavgloadDataIsAlmostEq :: J.JSValue -> J.JSValue -> Bool
+cpuavgloadDataIsAlmostEq a b =
+  case fromJVal a :: BT.Result CPUavgload of
+    BT.Bad _ -> False
+    BT.Ok cavA ->
+      case fromJVal b :: BT.Result CPUavgload of
+           BT.Bad _ -> False
+           BT.Ok cavB -> compareCPUavgload cavA cavB
+
+-- | Compares two CPuavgload objects.
+compareCPUavgload :: CPUavgload -> CPUavgload -> Bool
+compareCPUavgload a b =
+  let relError x y = relativeError x y <= 1e-9
+  in cavCpuNumber a == cavCpuNumber b
+     && relError (cavCpuTotal a) (cavCpuTotal b)
+     && length (cavCpus a) == length (cavCpus b)
+     && and (zipWith relError (cavCpus a) (cavCpus b))
diff --git a/test/hs/Test/Ganeti/Hypervisor/Xen/XmParser.hs 
b/test/hs/Test/Ganeti/Hypervisor/Xen/XmParser.hs
index 1951174..4d87e54 100644
--- a/test/hs/Test/Ganeti/Hypervisor/Xen/XmParser.hs
+++ b/test/hs/Test/Ganeti/Hypervisor/Xen/XmParser.hs
@@ -120,22 +120,6 @@ testUptimeInfo fileName expectedContent = do
     Left msg -> assertFailure $ "Parsing failed: " ++ msg
     Right obtained -> assertEqual fileName expectedContent obtained
 
--- | Computes the relative error of two 'Double' numbers.
---
--- This is the \"relative error\" algorithm in
--- http:\/\/randomascii.wordpress.com\/2012\/02\/25\/
--- comparing-floating-point-numbers-2012-edition (URL split due to too
--- long line).
-relativeError :: Double -> Double -> Double
-relativeError d1 d2 =
-  let delta = abs $ d1 - d2
-      a1 = abs d1
-      a2 = abs d2
-      greatest = max a1 a2
-  in if delta == 0
-       then 0
-       else delta / greatest
-
 -- | Determines whether two LispConfig are equal, with the exception of Double
 -- values, that just need to be \"almost equal\".
 --
diff --git a/test/hs/Test/Ganeti/TestCommon.hs 
b/test/hs/Test/Ganeti/TestCommon.hs
index 2340c5f..0f310de 100644
--- a/test/hs/Test/Ganeti/TestCommon.hs
+++ b/test/hs/Test/Ganeti/TestCommon.hs
@@ -65,6 +65,7 @@ module Test.Ganeti.TestCommon
   , testParser
   , genPropParser
   , genNonNegative
+  , relativeError
   ) where
 
 import Control.Applicative
@@ -404,3 +405,19 @@ genPropParser parser s expected =
 genNonNegative :: Gen Int
 genNonNegative =
   fmap fromIntegral (arbitrary::Gen (Test.QuickCheck.NonNegative Int))
+
+-- | Computes the relative error of two 'Double' numbers.
+--
+-- This is the \"relative error\" algorithm in
+-- http:\/\/randomascii.wordpress.com\/2012\/02\/25\/
+-- comparing-floating-point-numbers-2012-edition (URL split due to too
+-- long line).
+relativeError :: Double -> Double -> Double
+relativeError d1 d2 =
+  let delta = abs $ d1 - d2
+      a1 = abs d1
+      a2 = abs d2
+      greatest = max a1 a2
+  in if delta == 0
+       then 0
+       else delta / greatest
-- 
1.7.10.4

Reply via email to