root / test / hs / Test / Ganeti / Query / Query.hs @ b54ecf12
History | View | Annotate | Download (15.3 kB)
1 | 91c1a265 | Iustin Pop | {-# LANGUAGE TemplateHaskell, BangPatterns #-} |
---|---|---|---|
2 | b9bdc10e | Iustin Pop | {-# OPTIONS_GHC -fno-warn-orphans #-} |
3 | b9bdc10e | Iustin Pop | |
4 | b9bdc10e | Iustin Pop | {-| Unittests for ganeti-htools. |
5 | b9bdc10e | Iustin Pop | |
6 | b9bdc10e | Iustin Pop | -} |
7 | b9bdc10e | Iustin Pop | |
8 | b9bdc10e | Iustin Pop | {- |
9 | b9bdc10e | Iustin Pop | |
10 | 36162faf | Iustin Pop | Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc. |
11 | b9bdc10e | Iustin Pop | |
12 | b9bdc10e | Iustin Pop | This program is free software; you can redistribute it and/or modify |
13 | b9bdc10e | Iustin Pop | it under the terms of the GNU General Public License as published by |
14 | b9bdc10e | Iustin Pop | the Free Software Foundation; either version 2 of the License, or |
15 | b9bdc10e | Iustin Pop | (at your option) any later version. |
16 | b9bdc10e | Iustin Pop | |
17 | b9bdc10e | Iustin Pop | This program is distributed in the hope that it will be useful, but |
18 | b9bdc10e | Iustin Pop | WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | b9bdc10e | Iustin Pop | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 | b9bdc10e | Iustin Pop | General Public License for more details. |
21 | b9bdc10e | Iustin Pop | |
22 | b9bdc10e | Iustin Pop | You should have received a copy of the GNU General Public License |
23 | b9bdc10e | Iustin Pop | along with this program; if not, write to the Free Software |
24 | b9bdc10e | Iustin Pop | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
25 | b9bdc10e | Iustin Pop | 02110-1301, USA. |
26 | b9bdc10e | Iustin Pop | |
27 | b9bdc10e | Iustin Pop | -} |
28 | b9bdc10e | Iustin Pop | |
29 | b9bdc10e | Iustin Pop | module Test.Ganeti.Query.Query (testQuery_Query) where |
30 | b9bdc10e | Iustin Pop | |
31 | b9bdc10e | Iustin Pop | import Test.HUnit (Assertion, assertEqual) |
32 | b9bdc10e | Iustin Pop | import Test.QuickCheck hiding (Result) |
33 | b9bdc10e | Iustin Pop | import Test.QuickCheck.Monadic |
34 | b9bdc10e | Iustin Pop | |
35 | b9bdc10e | Iustin Pop | import Data.Function (on) |
36 | b9bdc10e | Iustin Pop | import Data.List |
37 | b9bdc10e | Iustin Pop | import qualified Data.Map as Map |
38 | b9bdc10e | Iustin Pop | import Data.Maybe |
39 | 91c1a265 | Iustin Pop | import qualified Data.Set as Set |
40 | e7124835 | Iustin Pop | import Text.JSON (JSValue(..), showJSON) |
41 | b9bdc10e | Iustin Pop | |
42 | b9bdc10e | Iustin Pop | import Test.Ganeti.TestHelper |
43 | b9bdc10e | Iustin Pop | import Test.Ganeti.TestCommon |
44 | b9bdc10e | Iustin Pop | import Test.Ganeti.Objects (genEmptyCluster) |
45 | b9bdc10e | Iustin Pop | |
46 | b9bdc10e | Iustin Pop | import Ganeti.BasicTypes |
47 | 5183e8be | Iustin Pop | import Ganeti.Errors |
48 | 91c1a265 | Iustin Pop | import Ganeti.JSON |
49 | 91c1a265 | Iustin Pop | import Ganeti.Objects |
50 | a7e484c4 | Iustin Pop | import Ganeti.Query.Filter |
51 | 36162faf | Iustin Pop | import qualified Ganeti.Query.Group as Group |
52 | b9bdc10e | Iustin Pop | import Ganeti.Query.Language |
53 | 36162faf | Iustin Pop | import qualified Ganeti.Query.Node as Node |
54 | b9bdc10e | Iustin Pop | import Ganeti.Query.Query |
55 | a7e484c4 | Iustin Pop | import qualified Ganeti.Query.Job as Job |
56 | 91c1a265 | Iustin Pop | import Ganeti.Utils (sepSplit) |
57 | b9bdc10e | Iustin Pop | |
58 | 5b11f8db | Iustin Pop | {-# ANN module "HLint: ignore Use camelCase" #-} |
59 | 5b11f8db | Iustin Pop | |
60 | b9bdc10e | Iustin Pop | -- * Helpers |
61 | b9bdc10e | Iustin Pop | |
62 | b9bdc10e | Iustin Pop | -- | Checks if a list of field definitions contains unknown fields. |
63 | b9bdc10e | Iustin Pop | hasUnknownFields :: [FieldDefinition] -> Bool |
64 | b9bdc10e | Iustin Pop | hasUnknownFields = (QFTUnknown `notElem`) . map fdefKind |
65 | b9bdc10e | Iustin Pop | |
66 | b9bdc10e | Iustin Pop | -- * Test cases |
67 | b9bdc10e | Iustin Pop | |
68 | a7e484c4 | Iustin Pop | -- ** Node queries |
69 | a7e484c4 | Iustin Pop | |
70 | b9bdc10e | Iustin Pop | -- | Tests that querying any existing fields, via either query or |
71 | b9bdc10e | Iustin Pop | -- queryFields, will not return unknown fields. |
72 | b9bdc10e | Iustin Pop | prop_queryNode_noUnknown :: Property |
73 | b9bdc10e | Iustin Pop | prop_queryNode_noUnknown = |
74 | b9bdc10e | Iustin Pop | forAll (choose (0, maxNodes) >>= genEmptyCluster) $ \cluster -> |
75 | 36162faf | Iustin Pop | forAll (elements (Map.keys Node.fieldsMap)) $ \field -> monadicIO $ do |
76 | b9bdc10e | Iustin Pop | QueryResult fdefs fdata <- |
77 | 1283cc38 | Iustin Pop | run (query cluster False (Query (ItemTypeOpCode QRNode) |
78 | 1283cc38 | Iustin Pop | [field] EmptyFilter)) >>= resultProp |
79 | b9bdc10e | Iustin Pop | QueryFieldsResult fdefs' <- |
80 | 1283cc38 | Iustin Pop | resultProp $ queryFields (QueryFields (ItemTypeOpCode QRNode) [field]) |
81 | 942a9a6a | Iustin Pop | stop $ conjoin |
82 | 942a9a6a | Iustin Pop | [ printTestCase ("Got unknown fields via query (" ++ |
83 | 942a9a6a | Iustin Pop | show fdefs ++ ")") (hasUnknownFields fdefs) |
84 | 942a9a6a | Iustin Pop | , printTestCase ("Got unknown result status via query (" ++ |
85 | 942a9a6a | Iustin Pop | show fdata ++ ")") |
86 | 942a9a6a | Iustin Pop | (all (all ((/= RSUnknown) . rentryStatus)) fdata) |
87 | 942a9a6a | Iustin Pop | , printTestCase ("Got unknown fields via query fields (" ++ |
88 | 942a9a6a | Iustin Pop | show fdefs'++ ")") (hasUnknownFields fdefs') |
89 | 942a9a6a | Iustin Pop | ] |
90 | b9bdc10e | Iustin Pop | |
91 | b9bdc10e | Iustin Pop | -- | Tests that an unknown field is returned as such. |
92 | b9bdc10e | Iustin Pop | prop_queryNode_Unknown :: Property |
93 | b9bdc10e | Iustin Pop | prop_queryNode_Unknown = |
94 | b9bdc10e | Iustin Pop | forAll (choose (0, maxNodes) >>= genEmptyCluster) $ \cluster -> |
95 | 36162faf | Iustin Pop | forAll (arbitrary `suchThat` (`notElem` Map.keys Node.fieldsMap)) |
96 | b9bdc10e | Iustin Pop | $ \field -> monadicIO $ do |
97 | b9bdc10e | Iustin Pop | QueryResult fdefs fdata <- |
98 | 1283cc38 | Iustin Pop | run (query cluster False (Query (ItemTypeOpCode QRNode) |
99 | 1283cc38 | Iustin Pop | [field] EmptyFilter)) >>= resultProp |
100 | b9bdc10e | Iustin Pop | QueryFieldsResult fdefs' <- |
101 | 1283cc38 | Iustin Pop | resultProp $ queryFields (QueryFields (ItemTypeOpCode QRNode) [field]) |
102 | 942a9a6a | Iustin Pop | stop $ conjoin |
103 | 942a9a6a | Iustin Pop | [ printTestCase ("Got known fields via query (" ++ show fdefs ++ ")") |
104 | 942a9a6a | Iustin Pop | (not $ hasUnknownFields fdefs) |
105 | 942a9a6a | Iustin Pop | , printTestCase ("Got /= ResultUnknown result status via query (" ++ |
106 | 942a9a6a | Iustin Pop | show fdata ++ ")") |
107 | 942a9a6a | Iustin Pop | (all (all ((== RSUnknown) . rentryStatus)) fdata) |
108 | 942a9a6a | Iustin Pop | , printTestCase ("Got a Just in a result value (" ++ |
109 | 942a9a6a | Iustin Pop | show fdata ++ ")") |
110 | 942a9a6a | Iustin Pop | (all (all (isNothing . rentryValue)) fdata) |
111 | 942a9a6a | Iustin Pop | , printTestCase ("Got known fields via query fields (" ++ show fdefs' |
112 | 942a9a6a | Iustin Pop | ++ ")") (not $ hasUnknownFields fdefs') |
113 | 942a9a6a | Iustin Pop | ] |
114 | b9bdc10e | Iustin Pop | |
115 | b9bdc10e | Iustin Pop | -- | Checks that a result type is conforming to a field definition. |
116 | b9bdc10e | Iustin Pop | checkResultType :: FieldDefinition -> ResultEntry -> Property |
117 | b9bdc10e | Iustin Pop | checkResultType _ (ResultEntry RSNormal Nothing) = |
118 | b9bdc10e | Iustin Pop | failTest "Nothing result in RSNormal field" |
119 | b9bdc10e | Iustin Pop | checkResultType _ (ResultEntry _ Nothing) = passTest |
120 | b9bdc10e | Iustin Pop | checkResultType fdef (ResultEntry RSNormal (Just v)) = |
121 | b9bdc10e | Iustin Pop | case (fdefKind fdef, v) of |
122 | b9bdc10e | Iustin Pop | (QFTText , JSString {}) -> passTest |
123 | b9bdc10e | Iustin Pop | (QFTBool , JSBool {}) -> passTest |
124 | b9bdc10e | Iustin Pop | (QFTNumber , JSRational {}) -> passTest |
125 | b9bdc10e | Iustin Pop | (QFTTimestamp , JSRational {}) -> passTest |
126 | b9bdc10e | Iustin Pop | (QFTUnit , JSRational {}) -> passTest |
127 | b9bdc10e | Iustin Pop | (QFTOther , _) -> passTest -- meh, QFT not precise... |
128 | b9bdc10e | Iustin Pop | (kind, _) -> failTest $ "Type mismatch, field definition says " ++ |
129 | b9bdc10e | Iustin Pop | show kind ++ " but returned value is " ++ show v ++ |
130 | b9bdc10e | Iustin Pop | " for field '" ++ fdefName fdef ++ "'" |
131 | b9bdc10e | Iustin Pop | checkResultType _ (ResultEntry r (Just _)) = |
132 | b9bdc10e | Iustin Pop | failTest $ "Just result in " ++ show r ++ " field" |
133 | b9bdc10e | Iustin Pop | |
134 | b9bdc10e | Iustin Pop | -- | Tests that querying any existing fields, the following three |
135 | b9bdc10e | Iustin Pop | -- properties hold: RSNormal corresponds to a Just value, any other |
136 | b9bdc10e | Iustin Pop | -- value corresponds to Nothing, and for a RSNormal and value field, |
137 | b9bdc10e | Iustin Pop | -- the type of the value corresponds to the type of the field as |
138 | b9bdc10e | Iustin Pop | -- declared in the FieldDefinition. |
139 | b9bdc10e | Iustin Pop | prop_queryNode_types :: Property |
140 | b9bdc10e | Iustin Pop | prop_queryNode_types = |
141 | b9bdc10e | Iustin Pop | forAll (choose (0, maxNodes)) $ \numnodes -> |
142 | b9bdc10e | Iustin Pop | forAll (genEmptyCluster numnodes) $ \cfg -> |
143 | 36162faf | Iustin Pop | forAll (elements (Map.keys Node.fieldsMap)) $ \field -> monadicIO $ do |
144 | b9bdc10e | Iustin Pop | QueryResult fdefs fdata <- |
145 | 1283cc38 | Iustin Pop | run (query cfg False (Query (ItemTypeOpCode QRNode) |
146 | 1283cc38 | Iustin Pop | [field] EmptyFilter)) >>= resultProp |
147 | 942a9a6a | Iustin Pop | stop $ conjoin |
148 | 942a9a6a | Iustin Pop | [ printTestCase ("Inconsistent result entries (" ++ show fdata ++ ")") |
149 | 942a9a6a | Iustin Pop | (conjoin $ map (conjoin . zipWith checkResultType fdefs) fdata) |
150 | 942a9a6a | Iustin Pop | , printTestCase "Wrong field definitions length" |
151 | 942a9a6a | Iustin Pop | (length fdefs ==? 1) |
152 | 942a9a6a | Iustin Pop | , printTestCase "Wrong field result rows length" |
153 | 942a9a6a | Iustin Pop | (all ((== 1) . length) fdata) |
154 | 942a9a6a | Iustin Pop | , printTestCase "Wrong number of result rows" |
155 | b9bdc10e | Iustin Pop | (length fdata ==? numnodes) |
156 | 942a9a6a | Iustin Pop | ] |
157 | b9bdc10e | Iustin Pop | |
158 | b9bdc10e | Iustin Pop | -- | Test that queryFields with empty fields list returns all node fields. |
159 | b9bdc10e | Iustin Pop | case_queryNode_allfields :: Assertion |
160 | b9bdc10e | Iustin Pop | case_queryNode_allfields = do |
161 | e7124835 | Iustin Pop | fdefs <- case queryFields (QueryFields (ItemTypeOpCode QRNode) []) of |
162 | e7124835 | Iustin Pop | Bad msg -> fail $ "Error in query all fields: " ++ |
163 | e7124835 | Iustin Pop | formatError msg |
164 | e7124835 | Iustin Pop | Ok (QueryFieldsResult v) -> return v |
165 | e7124835 | Iustin Pop | let field_sort = compare `on` fdefName |
166 | e7124835 | Iustin Pop | assertEqual "Mismatch in all fields list" |
167 | e7124835 | Iustin Pop | (sortBy field_sort . map (\(f, _, _) -> f) $ Map.elems Node.fieldsMap) |
168 | e7124835 | Iustin Pop | (sortBy field_sort fdefs) |
169 | b9bdc10e | Iustin Pop | |
170 | 91c1a265 | Iustin Pop | -- | Check if cluster node names are unique (first elems). |
171 | 91c1a265 | Iustin Pop | areNodeNamesSane :: ConfigData -> Bool |
172 | 91c1a265 | Iustin Pop | areNodeNamesSane cfg = |
173 | 91c1a265 | Iustin Pop | let fqdns = map nodeName . Map.elems . fromContainer $ configNodes cfg |
174 | 91c1a265 | Iustin Pop | names = map (head . sepSplit '.') fqdns |
175 | 91c1a265 | Iustin Pop | in length names == length (nub names) |
176 | 91c1a265 | Iustin Pop | |
177 | 91c1a265 | Iustin Pop | -- | Check that the nodes reported by a name filter are sane. |
178 | 91c1a265 | Iustin Pop | prop_queryNode_filter :: Property |
179 | 91c1a265 | Iustin Pop | prop_queryNode_filter = |
180 | 91c1a265 | Iustin Pop | forAll (choose (1, maxNodes)) $ \nodes -> |
181 | 91c1a265 | Iustin Pop | forAll (genEmptyCluster nodes `suchThat` |
182 | 91c1a265 | Iustin Pop | areNodeNamesSane) $ \cluster -> monadicIO $ do |
183 | 91c1a265 | Iustin Pop | let node_list = map nodeName . Map.elems . fromContainer $ |
184 | 91c1a265 | Iustin Pop | configNodes cluster |
185 | 91c1a265 | Iustin Pop | count <- pick $ choose (1, nodes) |
186 | 91c1a265 | Iustin Pop | fqdn_set <- pick . genSetHelper node_list $ Just count |
187 | 91c1a265 | Iustin Pop | let fqdns = Set.elems fqdn_set |
188 | 91c1a265 | Iustin Pop | names = map (head . sepSplit '.') fqdns |
189 | 91c1a265 | Iustin Pop | flt = makeSimpleFilter "name" $ map Left names |
190 | 91c1a265 | Iustin Pop | QueryResult _ fdata <- |
191 | 91c1a265 | Iustin Pop | run (query cluster False (Query (ItemTypeOpCode QRNode) |
192 | 91c1a265 | Iustin Pop | ["name"] flt)) >>= resultProp |
193 | 91c1a265 | Iustin Pop | stop $ conjoin |
194 | 91c1a265 | Iustin Pop | [ printTestCase "Invalid node names" $ |
195 | 91c1a265 | Iustin Pop | map (map rentryValue) fdata ==? map (\f -> [Just (showJSON f)]) fqdns |
196 | 91c1a265 | Iustin Pop | ] |
197 | 91c1a265 | Iustin Pop | |
198 | a7e484c4 | Iustin Pop | -- ** Group queries |
199 | a9d6f4e0 | Agata Murawska | |
200 | a9d6f4e0 | Agata Murawska | prop_queryGroup_noUnknown :: Property |
201 | a9d6f4e0 | Agata Murawska | prop_queryGroup_noUnknown = |
202 | a9d6f4e0 | Agata Murawska | forAll (choose (0, maxNodes) >>= genEmptyCluster) $ \cluster -> |
203 | e7124835 | Iustin Pop | forAll (elements (Map.keys Group.fieldsMap)) $ \field -> monadicIO $ do |
204 | e7124835 | Iustin Pop | QueryResult fdefs fdata <- |
205 | e7124835 | Iustin Pop | run (query cluster False (Query (ItemTypeOpCode QRGroup) |
206 | e7124835 | Iustin Pop | [field] EmptyFilter)) >>= |
207 | e7124835 | Iustin Pop | resultProp |
208 | e7124835 | Iustin Pop | QueryFieldsResult fdefs' <- |
209 | e7124835 | Iustin Pop | resultProp $ queryFields (QueryFields (ItemTypeOpCode QRGroup) [field]) |
210 | e7124835 | Iustin Pop | stop $ conjoin |
211 | e7124835 | Iustin Pop | [ printTestCase ("Got unknown fields via query (" ++ show fdefs ++ ")") |
212 | e7124835 | Iustin Pop | (hasUnknownFields fdefs) |
213 | e7124835 | Iustin Pop | , printTestCase ("Got unknown result status via query (" ++ |
214 | e7124835 | Iustin Pop | show fdata ++ ")") |
215 | e7124835 | Iustin Pop | (all (all ((/= RSUnknown) . rentryStatus)) fdata) |
216 | e7124835 | Iustin Pop | , printTestCase ("Got unknown fields via query fields (" ++ show fdefs' |
217 | e7124835 | Iustin Pop | ++ ")") (hasUnknownFields fdefs') |
218 | e7124835 | Iustin Pop | ] |
219 | a9d6f4e0 | Agata Murawska | |
220 | a9d6f4e0 | Agata Murawska | prop_queryGroup_Unknown :: Property |
221 | a9d6f4e0 | Agata Murawska | prop_queryGroup_Unknown = |
222 | a9d6f4e0 | Agata Murawska | forAll (choose (0, maxNodes) >>= genEmptyCluster) $ \cluster -> |
223 | 36162faf | Iustin Pop | forAll (arbitrary `suchThat` (`notElem` Map.keys Group.fieldsMap)) |
224 | a9d6f4e0 | Agata Murawska | $ \field -> monadicIO $ do |
225 | a9d6f4e0 | Agata Murawska | QueryResult fdefs fdata <- |
226 | 1283cc38 | Iustin Pop | run (query cluster False (Query (ItemTypeOpCode QRGroup) |
227 | 1283cc38 | Iustin Pop | [field] EmptyFilter)) >>= resultProp |
228 | a9d6f4e0 | Agata Murawska | QueryFieldsResult fdefs' <- |
229 | 1283cc38 | Iustin Pop | resultProp $ queryFields (QueryFields (ItemTypeOpCode QRGroup) [field]) |
230 | 942a9a6a | Iustin Pop | stop $ conjoin |
231 | 942a9a6a | Iustin Pop | [ printTestCase ("Got known fields via query (" ++ show fdefs ++ ")") |
232 | 942a9a6a | Iustin Pop | (not $ hasUnknownFields fdefs) |
233 | 942a9a6a | Iustin Pop | , printTestCase ("Got /= ResultUnknown result status via query (" ++ |
234 | 942a9a6a | Iustin Pop | show fdata ++ ")") |
235 | 942a9a6a | Iustin Pop | (all (all ((== RSUnknown) . rentryStatus)) fdata) |
236 | 942a9a6a | Iustin Pop | , printTestCase ("Got a Just in a result value (" ++ |
237 | 942a9a6a | Iustin Pop | show fdata ++ ")") |
238 | 942a9a6a | Iustin Pop | (all (all (isNothing . rentryValue)) fdata) |
239 | 942a9a6a | Iustin Pop | , printTestCase ("Got known fields via query fields (" ++ show fdefs' |
240 | 942a9a6a | Iustin Pop | ++ ")") (not $ hasUnknownFields fdefs') |
241 | 942a9a6a | Iustin Pop | ] |
242 | a9d6f4e0 | Agata Murawska | |
243 | a9d6f4e0 | Agata Murawska | prop_queryGroup_types :: Property |
244 | a9d6f4e0 | Agata Murawska | prop_queryGroup_types = |
245 | a9d6f4e0 | Agata Murawska | forAll (choose (0, maxNodes)) $ \numnodes -> |
246 | a9d6f4e0 | Agata Murawska | forAll (genEmptyCluster numnodes) $ \cfg -> |
247 | 36162faf | Iustin Pop | forAll (elements (Map.keys Group.fieldsMap)) $ \field -> monadicIO $ do |
248 | a9d6f4e0 | Agata Murawska | QueryResult fdefs fdata <- |
249 | 1283cc38 | Iustin Pop | run (query cfg False (Query (ItemTypeOpCode QRGroup) |
250 | 1283cc38 | Iustin Pop | [field] EmptyFilter)) >>= resultProp |
251 | 942a9a6a | Iustin Pop | stop $ conjoin |
252 | 942a9a6a | Iustin Pop | [ printTestCase ("Inconsistent result entries (" ++ show fdata ++ ")") |
253 | 942a9a6a | Iustin Pop | (conjoin $ map (conjoin . zipWith checkResultType fdefs) fdata) |
254 | 942a9a6a | Iustin Pop | , printTestCase "Wrong field definitions length" (length fdefs ==? 1) |
255 | 942a9a6a | Iustin Pop | , printTestCase "Wrong field result rows length" |
256 | a9d6f4e0 | Agata Murawska | (all ((== 1) . length) fdata) |
257 | 942a9a6a | Iustin Pop | ] |
258 | a9d6f4e0 | Agata Murawska | |
259 | a9d6f4e0 | Agata Murawska | case_queryGroup_allfields :: Assertion |
260 | a9d6f4e0 | Agata Murawska | case_queryGroup_allfields = do |
261 | e7124835 | Iustin Pop | fdefs <- case queryFields (QueryFields (ItemTypeOpCode QRGroup) []) of |
262 | e7124835 | Iustin Pop | Bad msg -> fail $ "Error in query all fields: " ++ |
263 | e7124835 | Iustin Pop | formatError msg |
264 | e7124835 | Iustin Pop | Ok (QueryFieldsResult v) -> return v |
265 | e7124835 | Iustin Pop | let field_sort = compare `on` fdefName |
266 | e7124835 | Iustin Pop | assertEqual "Mismatch in all fields list" |
267 | e7124835 | Iustin Pop | (sortBy field_sort . map (\(f, _, _) -> f) $ Map.elems Group.fieldsMap) |
268 | e7124835 | Iustin Pop | (sortBy field_sort fdefs) |
269 | e7124835 | Iustin Pop | |
270 | e7124835 | Iustin Pop | -- | Check that the node count reported by a group list is sane. |
271 | e7124835 | Iustin Pop | -- |
272 | e7124835 | Iustin Pop | -- FIXME: also verify the node list, etc. |
273 | e7124835 | Iustin Pop | prop_queryGroup_nodeCount :: Property |
274 | e7124835 | Iustin Pop | prop_queryGroup_nodeCount = |
275 | e7124835 | Iustin Pop | forAll (choose (0, maxNodes)) $ \nodes -> |
276 | e7124835 | Iustin Pop | forAll (genEmptyCluster nodes) $ \cluster -> monadicIO $ |
277 | e7124835 | Iustin Pop | do |
278 | e7124835 | Iustin Pop | QueryResult _ fdata <- |
279 | e7124835 | Iustin Pop | run (query cluster False (Query (ItemTypeOpCode QRGroup) |
280 | e7124835 | Iustin Pop | ["node_cnt"] EmptyFilter)) >>= resultProp |
281 | e7124835 | Iustin Pop | stop $ conjoin |
282 | e7124835 | Iustin Pop | [ printTestCase "Invalid node count" $ |
283 | e7124835 | Iustin Pop | map (map rentryValue) fdata ==? [[Just (showJSON nodes)]] |
284 | e7124835 | Iustin Pop | ] |
285 | a9d6f4e0 | Agata Murawska | |
286 | a7e484c4 | Iustin Pop | -- ** Job queries |
287 | a7e484c4 | Iustin Pop | |
288 | a7e484c4 | Iustin Pop | -- | Tests that querying any existing fields, via either query or |
289 | a7e484c4 | Iustin Pop | -- queryFields, will not return unknown fields. This uses 'undefined' |
290 | a7e484c4 | Iustin Pop | -- for config, as job queries shouldn't use the configuration, and an |
291 | a7e484c4 | Iustin Pop | -- explicit filter as otherwise non-live queries wouldn't return any |
292 | a7e484c4 | Iustin Pop | -- result rows. |
293 | a7e484c4 | Iustin Pop | prop_queryJob_noUnknown :: Property |
294 | a7e484c4 | Iustin Pop | prop_queryJob_noUnknown = |
295 | a7e484c4 | Iustin Pop | forAll (listOf (arbitrary::Gen (Positive Integer))) $ \ids -> |
296 | a7e484c4 | Iustin Pop | forAll (elements (Map.keys Job.fieldsMap)) $ \field -> monadicIO $ do |
297 | a7e484c4 | Iustin Pop | let qtype = ItemTypeLuxi QRJob |
298 | a7e484c4 | Iustin Pop | flt = makeSimpleFilter (nameField qtype) $ |
299 | a7e484c4 | Iustin Pop | map (\(Positive i) -> Right i) ids |
300 | a7e484c4 | Iustin Pop | QueryResult fdefs fdata <- |
301 | a7e484c4 | Iustin Pop | run (query undefined False (Query qtype [field] flt)) >>= resultProp |
302 | a7e484c4 | Iustin Pop | QueryFieldsResult fdefs' <- |
303 | a7e484c4 | Iustin Pop | resultProp $ queryFields (QueryFields qtype [field]) |
304 | a7e484c4 | Iustin Pop | stop $ conjoin |
305 | a7e484c4 | Iustin Pop | [ printTestCase ("Got unknown fields via query (" ++ |
306 | a7e484c4 | Iustin Pop | show fdefs ++ ")") (hasUnknownFields fdefs) |
307 | a7e484c4 | Iustin Pop | , printTestCase ("Got unknown result status via query (" ++ |
308 | a7e484c4 | Iustin Pop | show fdata ++ ")") |
309 | a7e484c4 | Iustin Pop | (all (all ((/= RSUnknown) . rentryStatus)) fdata) |
310 | a7e484c4 | Iustin Pop | , printTestCase ("Got unknown fields via query fields (" ++ |
311 | a7e484c4 | Iustin Pop | show fdefs'++ ")") (hasUnknownFields fdefs') |
312 | a7e484c4 | Iustin Pop | ] |
313 | a7e484c4 | Iustin Pop | |
314 | a7e484c4 | Iustin Pop | -- | Tests that an unknown field is returned as such. |
315 | a7e484c4 | Iustin Pop | prop_queryJob_Unknown :: Property |
316 | a7e484c4 | Iustin Pop | prop_queryJob_Unknown = |
317 | a7e484c4 | Iustin Pop | forAll (listOf (arbitrary::Gen (Positive Integer))) $ \ids -> |
318 | a7e484c4 | Iustin Pop | forAll (arbitrary `suchThat` (`notElem` Map.keys Job.fieldsMap)) |
319 | a7e484c4 | Iustin Pop | $ \field -> monadicIO $ do |
320 | a7e484c4 | Iustin Pop | let qtype = ItemTypeLuxi QRJob |
321 | a7e484c4 | Iustin Pop | flt = makeSimpleFilter (nameField qtype) $ |
322 | a7e484c4 | Iustin Pop | map (\(Positive i) -> Right i) ids |
323 | a7e484c4 | Iustin Pop | QueryResult fdefs fdata <- |
324 | a7e484c4 | Iustin Pop | run (query undefined False (Query qtype [field] flt)) >>= resultProp |
325 | a7e484c4 | Iustin Pop | QueryFieldsResult fdefs' <- |
326 | a7e484c4 | Iustin Pop | resultProp $ queryFields (QueryFields qtype [field]) |
327 | a7e484c4 | Iustin Pop | stop $ conjoin |
328 | a7e484c4 | Iustin Pop | [ printTestCase ("Got known fields via query (" ++ show fdefs ++ ")") |
329 | a7e484c4 | Iustin Pop | (not $ hasUnknownFields fdefs) |
330 | a7e484c4 | Iustin Pop | , printTestCase ("Got /= ResultUnknown result status via query (" ++ |
331 | a7e484c4 | Iustin Pop | show fdata ++ ")") |
332 | a7e484c4 | Iustin Pop | (all (all ((== RSUnknown) . rentryStatus)) fdata) |
333 | a7e484c4 | Iustin Pop | , printTestCase ("Got a Just in a result value (" ++ |
334 | a7e484c4 | Iustin Pop | show fdata ++ ")") |
335 | a7e484c4 | Iustin Pop | (all (all (isNothing . rentryValue)) fdata) |
336 | a7e484c4 | Iustin Pop | , printTestCase ("Got known fields via query fields (" ++ show fdefs' |
337 | a7e484c4 | Iustin Pop | ++ ")") (not $ hasUnknownFields fdefs') |
338 | a7e484c4 | Iustin Pop | ] |
339 | a7e484c4 | Iustin Pop | |
340 | a7e484c4 | Iustin Pop | -- ** Misc other tests |
341 | bc4cdeef | Iustin Pop | |
342 | bc4cdeef | Iustin Pop | -- | Tests that requested names checking behaves as expected. |
343 | bc4cdeef | Iustin Pop | prop_getRequestedNames :: Property |
344 | bc4cdeef | Iustin Pop | prop_getRequestedNames = |
345 | 5006418e | Iustin Pop | forAll genName $ \node1 -> |
346 | 1283cc38 | Iustin Pop | let chk = getRequestedNames . Query (ItemTypeOpCode QRNode) [] |
347 | bc4cdeef | Iustin Pop | q_node1 = QuotedString node1 |
348 | bc4cdeef | Iustin Pop | eq_name = EQFilter "name" |
349 | bc4cdeef | Iustin Pop | eq_node1 = eq_name q_node1 |
350 | bc4cdeef | Iustin Pop | in conjoin [ printTestCase "empty filter" $ chk EmptyFilter ==? [] |
351 | bc4cdeef | Iustin Pop | , printTestCase "and filter" $ chk (AndFilter [eq_node1]) ==? [] |
352 | bc4cdeef | Iustin Pop | , printTestCase "simple equality" $ chk eq_node1 ==? [node1] |
353 | bc4cdeef | Iustin Pop | , printTestCase "non-name field" $ |
354 | bc4cdeef | Iustin Pop | chk (EQFilter "foo" q_node1) ==? [] |
355 | bc4cdeef | Iustin Pop | , printTestCase "non-simple filter" $ |
356 | bc4cdeef | Iustin Pop | chk (OrFilter [ eq_node1 , LTFilter "foo" q_node1]) ==? [] |
357 | bc4cdeef | Iustin Pop | ] |
358 | bc4cdeef | Iustin Pop | |
359 | b9bdc10e | Iustin Pop | testSuite "Query/Query" |
360 | b9bdc10e | Iustin Pop | [ 'prop_queryNode_noUnknown |
361 | b9bdc10e | Iustin Pop | , 'prop_queryNode_Unknown |
362 | b9bdc10e | Iustin Pop | , 'prop_queryNode_types |
363 | 91c1a265 | Iustin Pop | , 'prop_queryNode_filter |
364 | b9bdc10e | Iustin Pop | , 'case_queryNode_allfields |
365 | a9d6f4e0 | Agata Murawska | , 'prop_queryGroup_noUnknown |
366 | a9d6f4e0 | Agata Murawska | , 'prop_queryGroup_Unknown |
367 | a9d6f4e0 | Agata Murawska | , 'prop_queryGroup_types |
368 | a9d6f4e0 | Agata Murawska | , 'case_queryGroup_allfields |
369 | e7124835 | Iustin Pop | , 'prop_queryGroup_nodeCount |
370 | a7e484c4 | Iustin Pop | , 'prop_queryJob_noUnknown |
371 | a7e484c4 | Iustin Pop | , 'prop_queryJob_Unknown |
372 | bc4cdeef | Iustin Pop | , 'prop_getRequestedNames |
373 | b9bdc10e | Iustin Pop | ] |