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