Revision 15f4c8ca

b/.gitignore
1
apidoc
1
/apidoc/
2
/.hpc/
3
/coverage/
2 4

  
3 5
*.o
4 6
*.patch
......
15 17
hbal
16 18
hscan
17 19
hail
20
test
18 21
*.prof*
19 22
*.stat
23
*.tix
20 24

  
21 25
version
22 26
Version.hs
b/Ganeti/HTools/Node.hs
5 5
-}
6 6

  
7 7
module Ganeti.HTools.Node
8
    ( Node(failN1, name, idx, t_mem, n_mem, f_mem, t_dsk, f_dsk,
8
    ( Node(failN1, name, idx, t_mem, n_mem, f_mem, r_mem, t_dsk, f_dsk,
9 9
           p_mem, p_dsk, p_rem,
10 10
           plist, slist, offline)
11 11
    , List
b/Ganeti/HTools/QC.hs
1
module Ganeti.HTools.QC
2
    where
3

  
4
import Test.QuickCheck
5
import Data.Maybe
6
import qualified Ganeti.HTools.CLI as CLI
7
import qualified Ganeti.HTools.Cluster as Cluster
8
import qualified Ganeti.HTools.Container as Container
9
import qualified Ganeti.HTools.IAlloc as IAlloc
10
import qualified Ganeti.HTools.Instance as Instance
11
import qualified Ganeti.HTools.Loader as Loader
12
import qualified Ganeti.HTools.Node as Node
13
import qualified Ganeti.HTools.PeerMap as PeerMap
14
import qualified Ganeti.HTools.Rapi as Rapi
15
import qualified Ganeti.HTools.Text as Text
16
import qualified Ganeti.HTools.Types as Types
17
import qualified Ganeti.HTools.Utils as Utils
18

  
19
-- copied from the introduction to quickcheck
20
instance Arbitrary Char where
21
    arbitrary     = choose ('\32', '\128')
22

  
23
-- let's generate a random instance
24
instance Arbitrary Instance.Instance where
25
    arbitrary = do
26
      name <- arbitrary
27
      mem <- choose(0, 100)
28
      dsk <- choose(0, 100)
29
      run_st <- arbitrary
30
      pn <- arbitrary
31
      sn <- arbitrary
32
      return $ Instance.create name mem dsk run_st pn sn
33

  
34
-- and a random node
35
instance Arbitrary Node.Node where
36
    arbitrary = do
37
      name <- arbitrary
38
      mem_t <- arbitrary
39
      mem_f <- choose (0, mem_t)
40
      mem_n <- choose (0, mem_t - mem_f)
41
      dsk_t <- arbitrary
42
      dsk_f <- choose (0, dsk_t)
43
      offl <- arbitrary
44
      npeers <- choose (0, 100)
45
      let n = Node.create name (fromIntegral mem_t) mem_n mem_f
46
              (fromIntegral dsk_t) dsk_f offl
47
          n' = Node.buildPeers n Container.empty npeers
48
      return n'
49

  
50
-- | Make sure add is idempotent
51
prop_PeerMap_addIdempotent pmap key elem =
52
    fn puniq == fn (fn puniq)
53
    where fn = PeerMap.add key elem
54
          puniq = PeerMap.accumArray const pmap
55
          _types = (pmap::PeerMap.PeerMap,
56
                    key::PeerMap.Key, elem::PeerMap.Elem)
57

  
58
-- | Make sure remove is idempotent
59
prop_PeerMap_removeIdempotent pmap key =
60
    fn puniq == fn (fn puniq)
61
    where fn = PeerMap.remove key
62
          puniq = PeerMap.accumArray const pmap
63
          _types = (pmap::PeerMap.PeerMap,
64
                    key::PeerMap.Key)
65

  
66
-- | Make sure a missing item returns 0
67
prop_PeerMap_findMissing pmap key =
68
    PeerMap.find key (PeerMap.remove key puniq) == 0
69
    where fn = PeerMap.remove key
70
          puniq = PeerMap.accumArray const pmap
71
          _types = (pmap::PeerMap.PeerMap,
72
                    key::PeerMap.Key)
73

  
74
-- | Make sure an added item is found
75
prop_PeerMap_addFind pmap key elem =
76
    PeerMap.find key (PeerMap.add key elem puniq) == elem
77
    where puniq = PeerMap.accumArray const pmap
78
          _types = (pmap::PeerMap.PeerMap,
79
                    key::PeerMap.Key, elem::PeerMap.Elem)
80

  
81
-- | Manual check that maxElem returns the maximum indeed, or 0 for null
82
prop_PeerMap_maxElem pmap =
83
    PeerMap.maxElem puniq == if null puniq then 0
84
                             else (maximum . snd . unzip) puniq
85
    where
86
          puniq = PeerMap.accumArray const pmap
87
          _types = pmap::PeerMap.PeerMap
88

  
89
prop_Node_addPri node inst = (Instance.mem inst >= Node.f_mem node ||
90
                              Instance.dsk inst >= Node.f_dsk node) &&
91
                             (not $ Node.failN1 node)
92
                             ==>
93
                             isNothing(Node.addPri node inst)
94
    where _types = (node::Node.Node, inst::Instance.Instance)
95

  
96
prop_Node_addSec node inst pdx =
97
    (Instance.mem inst >= (Node.f_mem node - Node.r_mem node) ||
98
     Instance.dsk inst >= Node.f_dsk node) &&
99
    (not $ Node.failN1 node)
100
    ==> isNothing(Node.addSec node inst pdx)
101
        where _types = (node::Node.Node, inst::Instance.Instance, pdx::Int)
b/Makefile
1
HPROGS = hbal hn1 hscan hail
1
HPROGS = hbal hn1 hscan hail test
2 2
HSRCS := $(wildcard Ganeti/HTools/*.hs)
3 3
HDDIR = apidoc
4 4

  
5 5
DOCS = README.html NEWS.html
6 6

  
7
HFLAGS = -O2 -W -fwarn-monomorphism-restriction -fwarn-tabs
8
HEXTRA =
9

  
10
HPCEXCL = --exclude Main --exclude Ganeti.HTools.QC
11

  
7 12
# Haskell rules
8 13

  
9 14
all: $(HPROGS)
10 15

  
11 16
$(HPROGS): %: %.hs Ganeti/HTools/Version.hs $(HSRCS) Makefile
12
	ghc --make -O2 -W $@
17
	ghc --make $(HFLAGS) $(HEXTRA) $@
13 18

  
14 19
$(DOCS) : %.html : %
15 20
	rst2html $< $@
......
53 58
	gzip -v9 $$ANAME ; \
54 59
	tar tzvf $$ANAME.gz
55 60

  
56
.PHONY : all doc maintainer-clean clean dist
61
check:
62
	rm -f *.tix *.mix test
63
	$(MAKE) HEXTRA=-fhpc test
64
	./test
65
ifeq ($(T),markup)
66
	mkdir -p coverage
67
	hpc markup --destdir=coverage test $(HPCEXCL)
68
else
69
	hpc report test $(HPCEXCL)
70
endif
71

  
72
.PHONY : all doc maintainer-clean clean dist check
b/test.hs
1
{-| Unittest runner for htools
2

  
3
-}
4

  
5
module Main(main) where
6

  
7
import Test.QuickCheck.Batch
8
import Ganeti.HTools.QC
9

  
10
options = TestOptions
11
      { no_of_tests         = 500
12
      , length_of_tests     = 5
13
      , debug_tests         = False }
14

  
15
main = do
16
  runTests "PeerMap" options
17
       [ run prop_PeerMap_addIdempotent
18
       , run prop_PeerMap_removeIdempotent
19
       , run prop_PeerMap_maxElem
20
       , run prop_PeerMap_addFind
21
       , run prop_PeerMap_findMissing
22
       ]
23

  
24
  runTests "Node" options
25
       [ run prop_Node_addPri
26
       , run prop_Node_addSec
27
       ]

Also available in: Unified diff