From 33ce4d2d991456a67a6025187b4b8aaa85e3bd03 Mon Sep 17 00:00:00 2001 From: Spyros Trigazis Date: Mon, 30 Sep 2013 08:57:42 +0300 Subject: [PATCH] Add test for mond-data mock file Test if the input file imported with the --mond-data option is parsed properly. Signed-off-by: Spyros Trigazis Signed-off-by: Michele Tartara Reviewed-by: Michele Tartara --- 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