Revision 2d52359b htest/Test/Ganeti/Query/Filter.hs
b/htest/Test/Ganeti/Query/Filter.hs | ||
---|---|---|
70 | 70 |
Ok a -> stop . failTest $ "Expected failure in " ++ descr ++ |
71 | 71 |
" but got " ++ show a |
72 | 72 |
|
73 |
-- | A helper to construct a list of results from an expected names list. |
|
74 |
namesToResult :: [String] -> [[ResultEntry]] |
|
75 |
namesToResult = map ((:[]) . ResultEntry RSNormal . Just . showJSON) |
|
76 |
|
|
77 |
-- | Generates a cluster and returns its node names too. |
|
78 |
genClusterNames :: Int -> Int -> Gen (ConfigData, [String]) |
|
79 |
genClusterNames min_nodes max_nodes = do |
|
80 |
numnodes <- choose (min_nodes, max_nodes) |
|
81 |
cfg <- genEmptyCluster numnodes |
|
82 |
return (cfg, niceSort . Map.keys . fromContainer $ configNodes cfg) |
|
83 |
|
|
73 | 84 |
-- * Test cases |
74 | 85 |
|
75 | 86 |
-- | Tests single node filtering: eq should return it, and (lt and gt) |
76 | 87 |
-- should fail. |
77 | 88 |
prop_node_single_filter :: Property |
78 | 89 |
prop_node_single_filter = |
79 |
forAll (choose (1, maxNodes)) $ \numnodes -> |
|
80 |
forAll (genEmptyCluster numnodes) $ \cfg -> |
|
81 |
let allnodes = niceSort . Map.keys . fromContainer $ configNodes cfg in |
|
90 |
forAll (genClusterNames 1 maxNodes) $ \(cfg, allnodes) -> |
|
82 | 91 |
forAll (elements allnodes) $ \nname -> |
83 | 92 |
let fvalue = QuotedString nname |
84 | 93 |
buildflt n = n "name" fvalue |
85 |
expsingle = [[ResultEntry RSNormal (Just (showJSON nname))]]
|
|
94 |
expsingle = namesToResult [nname]
|
|
86 | 95 |
othernodes = nname `delete` allnodes |
87 |
expnot = map ((:[]) . ResultEntry RSNormal . Just . showJSON) othernodes
|
|
96 |
expnot = namesToResult othernodes
|
|
88 | 97 |
test_query = checkQueryResults cfg . makeNodeQuery |
89 | 98 |
in conjoin |
90 | 99 |
[ test_query (buildflt EQFilter) "single-name 'EQ' filter" expsingle |
... | ... | |
102 | 111 |
-- the 'AndFilter' case breaks. |
103 | 112 |
prop_node_many_filter :: Property |
104 | 113 |
prop_node_many_filter = |
105 |
forAll (choose (2, maxNodes)) $ \numnodes -> |
|
106 |
forAll (genEmptyCluster numnodes) $ \cfg -> |
|
107 |
let nnames = niceSort . Map.keys . fromContainer $ configNodes cfg |
|
108 |
eqfilter = map (EQFilter "name" . QuotedString) nnames |
|
109 |
alln = map ((:[]) . ResultEntry RSNormal . Just . showJSON) nnames |
|
114 |
forAll (genClusterNames 2 maxNodes) $ \(cfg, nnames) -> |
|
115 |
let eqfilter = map (EQFilter "name" . QuotedString) nnames |
|
116 |
alln = namesToResult nnames |
|
110 | 117 |
test_query = checkQueryResults cfg . makeNodeQuery |
111 | 118 |
num_zero = NumericValue 0 |
112 | 119 |
in conjoin |
... | ... | |
118 | 125 |
, test_query (GTFilter "sinst_cnt" num_zero) "sinst_cnt 'GT' 0" [] |
119 | 126 |
] |
120 | 127 |
|
128 |
-- | Tests name ordering consistency: requesting a 'simple filter' |
|
129 |
-- results in identical name ordering as the wanted names, requesting |
|
130 |
-- a more complex filter results in a niceSort-ed order. |
|
131 |
prop_node_name_ordering :: Property |
|
132 |
prop_node_name_ordering = |
|
133 |
forAll (genClusterNames 2 6) $ \(cfg, nnames) -> |
|
134 |
forAll (elements (subsequences nnames)) $ \sorted_nodes -> |
|
135 |
forAll (elements (permutations sorted_nodes)) $ \chosen_nodes -> |
|
136 |
let orfilter = OrFilter $ map (EQFilter "name" . QuotedString) chosen_nodes |
|
137 |
alln = namesToResult chosen_nodes |
|
138 |
all_sorted = namesToResult $ niceSort chosen_nodes |
|
139 |
test_query = checkQueryResults cfg . makeNodeQuery |
|
140 |
in conjoin |
|
141 |
[ test_query orfilter "simple filter/requested" alln |
|
142 |
, test_query (AndFilter [orfilter]) "complex filter/sorted" all_sorted |
|
143 |
] |
|
144 |
|
|
121 | 145 |
-- | Tests node regex filtering. This is a very basic test :( |
122 | 146 |
prop_node_regex_filter :: Property |
123 | 147 |
prop_node_regex_filter = |
124 |
forAll (choose (0, maxNodes)) $ \numnodes -> |
|
125 |
forAll (genEmptyCluster numnodes) $ \cfg -> |
|
126 |
let nnames = niceSort . Map.keys . fromContainer $ configNodes cfg |
|
127 |
expected = map ((:[]) . ResultEntry RSNormal . Just . showJSON) nnames |
|
128 |
regex = mkRegex ".*"::Result FilterRegex |
|
129 |
in case regex of |
|
130 |
Bad msg -> failTest $ "Can't build regex?! Error: " ++ msg |
|
131 |
Ok rx -> |
|
132 |
checkQueryResults cfg (makeNodeQuery (RegexpFilter "name" rx)) |
|
133 |
"rows for all nodes regexp filter" |
|
134 |
expected |
|
148 |
forAll (genClusterNames 0 maxNodes) $ \(cfg, nnames) -> |
|
149 |
case mkRegex ".*"::Result FilterRegex of |
|
150 |
Bad msg -> failTest $ "Can't build regex?! Error: " ++ msg |
|
151 |
Ok rx -> |
|
152 |
checkQueryResults cfg (makeNodeQuery (RegexpFilter "name" rx)) |
|
153 |
"rows for all nodes regexp filter" $ namesToResult nnames |
|
135 | 154 |
|
136 | 155 |
-- | Tests node regex filtering. This is a very basic test :( |
137 | 156 |
prop_node_bad_filter :: String -> Int -> Property |
138 | 157 |
prop_node_bad_filter rndname rndint = |
139 |
forAll (choose (1, maxNodes)) $ \numnodes -> |
|
140 |
forAll (genEmptyCluster numnodes) $ \cfg -> |
|
141 |
let regex = mkRegex ".*"::Result FilterRegex |
|
142 |
test_query = expectBadQuery cfg . makeNodeQuery |
|
158 |
forAll (genClusterNames 1 maxNodes) $ \(cfg, _) -> |
|
159 |
let test_query = expectBadQuery cfg . makeNodeQuery |
|
143 | 160 |
string_value = QuotedString rndname |
144 | 161 |
numeric_value = NumericValue $ fromIntegral rndint |
145 |
in case regex of
|
|
162 |
in case mkRegex ".*"::Result FilterRegex of
|
|
146 | 163 |
Bad msg -> failTest $ "Can't build regex?! Error: " ++ msg |
147 | 164 |
Ok rx -> |
148 | 165 |
conjoin |
... | ... | |
175 | 192 |
testSuite "Query/Filter" |
176 | 193 |
[ 'prop_node_single_filter |
177 | 194 |
, 'prop_node_many_filter |
195 |
, 'prop_node_name_ordering |
|
178 | 196 |
, 'prop_node_regex_filter |
179 | 197 |
, 'prop_node_bad_filter |
180 | 198 |
, 'prop_makeSimpleFilter |
Also available in: Unified diff