Statistics
| Branch: | Tag: | Revision:

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
  ]